Я использую AWS Cognito для аутентификации своих пользователей, и после аутентификации они могут вызывать мой API (API Gateway + Lambda).Я делаю все это, используя Serverless Framework.
После проверки подлинности, когда они вызывают конечную точку, требующую этой проверки подлинности, моя лямбда получит атрибуты пользователя через request.RequestContext.Authorizer["claims"]
.У меня была идея создать промежуточное программное обеспечение для аутентификации, чтобы ввести текущего пользователя в контекст.Но я уверен, что делаю что-то не так (или могу быть улучшен).
Как это работает:
my-lambda-handler.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),
)
}
middlewares / 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)
}
}
models / 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
}
У меня два вопроса:
- Это правильный путьопределить функцию (функцию аутентификации), которая получает функцию и возвращает другую функцию?Поскольку это слишком многословно, я чувствую, что это неправильно.
- Есть ли способ дополнить
ctx
атрибутом user
?Способ, которым я пытаюсь, вижу ошибку ctx.user undefined (type context.Context has no field or method user)
Заранее спасибо.