Как создать промежуточное программное обеспечение для аутентификации в AWS Lambda - PullRequest
0 голосов
/ 30 октября 2018

Я использую AWS Cognito для аутентификации своих пользователей, и после аутентификации они могут вызывать мой API (API Gateway + Lambda). Я делаю все это с помощью Serverless Framework.

После проверки подлинности, когда они вызывают конечную точку, которая требует эту проверку подлинности, моя лямбда будет получать атрибуты пользователя через request.RequestContext.Authorizer["claims"]. У меня была идея создать промежуточное программное обеспечение для аутентификации, чтобы ввести текущего пользователя в контекст. Но я уверен, что я делаю что-то не так (или могу быть улучшен).

Как это работает:

мой-lambda.go:

package main

import (
    "context"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/company/api/middlewares"
)

func Handler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    fmt.Println(ctx.user)

    return events.APIGatewayProxyResponse{}, nil
}

func main() {
    lambda.Start(
        middlewares.Authentication(Handler),
    )
}

промежуточное программное / authentication.go

package middlewares

import (
    "context"

    "github.com/aws/aws-lambda-go/events"
    "github.com/company/api/models"
)

func Authentication(next func(context.Context, events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)) func(context.Context, events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    var user models.User

    return func(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
        claims := request.RequestContext.Authorizer["claims"]

        // Find user by claims properties.
        if err := user.Current(claims); err != nil {
            return events.APIGatewayProxyResponse{}, err
        }

        ctx.user = user
        return next(ctx, request)
    }
}

Модели / user.go:

package models

import (
    "github.com/jinzhu/gorm"
    "github.com/mitchellh/mapstructure"
)

type User struct {
    gorm.Model
    // Override ID cause we are using cognito.
    Email string `gorm:"primary_key,not null"`
    Site  Site
}

func (u *User) Current(claims interface{}) error {
    if err := mapstructure.Decode(claims, u); err != nil {
        panic(err)
    }

    if err := Database.Find(u).Error; err != nil {
        return err
    }
    return nil
}

У меня есть 2 вопроса:

  • Является ли это правильным способом определения функции (функции аутентификации), которая получает функцию и возвращает другую функцию? Поскольку это слишком многословно, я чувствую, что это неправильно.
  • Есть ли способ дополнить ctx атрибутом user? Кстати, что я пытаюсь, я вижу ошибку ctx.user undefined (type context.Context has no field or method user).

1 Ответ

0 голосов
/ 30 октября 2018

1-й вопрос об использовании промежуточного программного обеспечения:

Нет ничего плохого в подходе. Возможно, функция будет выглядеть немного лучше, если вы определите тип функции и будете использовать определенное имя. net/http делает то же самое с HandlerFunc:

type HandlerFunc func(ResponseWriter, *Request)

Что сделает подпись промежуточного программного обеспечения более разумной:

func AuthMiddleware(nextHop HandlerFunc) HandlerFunc

РЕДАКТИРОВАТЬ: разве лямбда-библиотека не определяет такой тип для сигнатуры функции? Я ожидал бы, что один будет существовать.

Также я не знаю, имеет ли смысл суффикс Middleware в вашем случае, но я думаю, некоторый суффикс должен иметь смысл для вас, чтобы дать немного больше контекста названию функции и сделать это более понятным. AuthenticationMiddleware может быть примером.

РЕДАКТИРОВАТЬ: только что увидел название пакета. LGTM действительно.

2-й вопрос:

См. это для правильного использования context. Также есть общий питфал: context.WithValue возвращает новый контекст для использования. Поэтому не следует ожидать, что переданный контекст параметра будет мутирован, и следует использовать новый возвращаемый контекст.

...