Как создать промежуточное ПО для аутентификации внутри AWS Lambda

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

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

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

my-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).
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
1 168
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

type HandlerFunc func(ResponseWriter, *Request)

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

func AuthMiddleware(nextHop HandlerFunc) HandlerFunc

Обновлено: не определяет ли лямбда-библиотека такой тип для сигнатуры функции? Я ожидал, что один будет существовать.

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

Обновлено: только что увидел имя пакета. LGTM действительно.

2-й вопрос:

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

Другие вопросы по теме