Wenn Sie AWS API Gateway verwenden, können Sie den AWS Lambda Authorizer für HTTP-APIs verwenden, um die Anfragen zu autorisieren. In diesem Blog zeige ich Ihnen, wie Sie ein mit KMS signiertes JWT-Token in einem Lambda unter Verwendung der Golang-Laufzeitumgebung validieren. Für die Beispiele verwende ich API Gateway V2 mit HTTP-APIs mit der Version v2 authorizer payload format und für die Ressourcen verwende ich Terraform.
Warum sollten Sie das JWT am Gateway validieren wollen?
Die Validierung des JWT-Tokens am Gateway hat mehrere Vorteile:
- Die JWT-Logik muss nicht in jedem Dienst implementiert werden, was den Wartungsaufwand reduziert.
- Steigerung der Leistung durch Zwischenspeicherung des Autorisierungsergebnisses für nachfolgende Anfragen
- Erhöhung der Sicherheit durch Verlangsamung der Angreifer durch Ratenbegrenzung und Zwischenspeicherung des Autorisierungsergebnisses
Wenn Sie sich dafür entscheiden, die JWT-Validierungslogik nicht in jedem Dienst zu implementieren, verlassen Sie sich voll und ganz auf das API Gateway, was ein Sicherheitsrisiko darstellen könnte. Indem Sie jeden Dienst das JWT-Token validieren lassen, verringern Sie den Sprengradius und stellen sicher, dass das API-Gateway keine einzelne Schwachstelle darstellt. Sie müssen sich also Ihren Anwendungsfall und Ihre Geschäftsanforderungen genau ansehen und auf dieser Grundlage eine Entscheidung treffen.
So richten Sie den Lambda Authorizer ein
Unten finden Sie den Golang Lambda-Code, den Sie auch auf GitHub finden können.
package main
import (
"context"
"os"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/kms"
"github.com/matelang/jwt-go-aws-kms/v2/jwtkms"
"github.com/golang-jwt/jwt/v5"
"github.com/sirupsen/logrus"
)
var log = logrus.New()
var KmsKeyID = os.Getenv("KMS_JWT_KEY_ID")
func HandleRequest(ctx context.Context, request events.APIGatewayCustomAuthorizerRequestTypeRequest) (events.APIGatewayV2CustomAuthorizerSimpleResponse, error) {
awsConfig, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
log.Errorf("aws config failed to load %s", err)
return events.APIGatewayV2CustomAuthorizerSimpleResponse{
IsAuthorized: false,
}, nil
}
kmsConfig := jwtkms.NewKMSConfig(kms.NewFromConfig(awsConfig), KmsKeyID, false)
claims := jwt.RegisteredClaims{}
_, err = jwt.ParseWithClaims(request.Headers["authorization"],
&claims, func(token *jwt.Token) (interface{}, error) {
return kmsConfig, nil
})
if err != nil {
log.Errorf("can not parse/verify token %s", err)
return events.APIGatewayV2CustomAuthorizerSimpleResponse{
IsAuthorized: false,
}, nil
}
log.Infof("validated token with claims: %v", claims)
return events.APIGatewayV2CustomAuthorizerSimpleResponse{
IsAuthorized: true,
}, nil
}
func main() {
lambda.Start(HandleRequest)
}
Um den Lambda Authorizer zum API Gateway hinzuzufügen, benötigen Sie die folgenden Ressourcen:
resource "aws_apigatewayv2_authorizer" "jwt" {
api_id = APIGATEWAY_ARN // Add your API Gateway here
authorizer_type = "REQUEST"
authorizer_uri = aws_lambda_function.jwt_authorizer.invoke_arn
identity_sources = ["$request.header.Authorization"]
name = "jwt-authorizer"
authorizer_payload_format_version = "2.0"
enable_simple_responses = true
}
resource "aws_lambda_function" "jwt_authorizer" {
s3_bucket = "BUCKET_NAME"
s3_key = "KEY"
function_name = "jwt-authorizer"
role = aws_iam_role.lambda_execution.arn // The role needs 'kms:GetPublicKey' permissions
handler = "jwt-validator-lambda"
environment {
variables = {
KMS_JWT_KEY_ID = aws_kms_key.jwt.id
}
}
runtime = "go1.x"
}
resource "aws_lambda_permission" "api_gateway" {
statement_id = "AllowExecutionFromApiGateway"
action = "lambda:InvokeFunction"
function_name = "jwt-authorizer"
principal = "apigateway.amazonaws.com"
source_arn = "arn:aws:execute-api:REGION_NAME:ACCOUNT_ID:${aws_apigatewayv2_api.main.id}/authorizers/${aws_apigatewayv2_authorizer.jwt.id}"
}
resource "aws_kms_key" "jwt" {
description = "jwt"
deletion_window_in_days = 7
customer_master_key_spec = "ECC_NIST_P521"
key_usage = "SIGN_VERIFY"
}
Die Lambda-Funktion benötigt kms:GetPublicKey Berechtigungen, um den öffentlichen Schlüssel zu lesen, der zum Signieren des JWT-Tokens verwendet wird.
Fazit
Zusammenfassend lässt sich sagen, dass die Validierung von JWT-Tokens am API-Gateway Vorteile bietet, wie z. B. einen geringeren Wartungsaufwand, eine verbesserte Leistung und eine erhöhte Sicherheit. Es ist jedoch wichtig, dass Sie diese Vorteile gegen die potenziellen Risiken abwägen und die spezifischen Anforderungen Ihrer Anwendung berücksichtigen, bevor Sie sich für den besten Ansatz entscheiden.
Verfasst von

Tibor Hercz
Tibor is a Cloud Consultant specialized in AWS with a strong background in Software engineering and has a passion for Compute, Networking and Security. His goal is to create simple Cloud Solutions that increases the efficiency and overall happiness of the teams and business. Sharing knowledge is important to him, so you will see him blogging and sharing knowledge about solutions he has built.
Contact




