Я использую 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)
.