When building serverless APIs, security is critical. One common way to secure APIs is by requiring clients to present a JWT token.
AWS API Gateway supports Lambda Authorizers, allowing you to write custom authorization logic using a Lambda function.
In today's post, we’ll cover:
- What is a Lambda Authorizer?
- How to build a simple Lambda Authorizer with Node.js
- How to connect it to your API Gateway with AWS SAM
🧠 What Is a Lambda Authorizer?
A Lambda Authorizer is a Lambda function that AWS API Gateway calls before forwarding the request to your main Lambda handler.
It can:
- Validate a JWT token
- Verify user roles/permissions
- Allow or deny access based on custom logic
You can write the logic yourself, giving you maximum flexibility compared to built-in IAM or Cognito authorizers.
🛠 Step 1: Create the Authorizer Lambda
Here’s a simple authorizer.ts example:
import { APIGatewayTokenAuthorizerEvent, APIGatewayAuthorizerResult } from "aws-lambda"; import { Logger } from "@aws-lambda-powertools/logger"; import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm"; import jwt from "jsonwebtoken"; const ssmClient = new SSMClient(); const logger = new Logger(); const secretName = process.env.SECRET_NAME! const generatePolicy = (principalId, effect, resource) => ({ principalId, policyDocument: { Version: '2012-10-17', Statement: [ { Action: 'execute-api:Invoke', Effect: effect, Resource: resource, }, ], }, }); export const handler = async (event: APIGatewayTokenAuthorizerEvent): Promise<APIGatewayAuthorizerResult> => { const token = event.authorizationToken if (!token) { throw new Error("Unauthorized"); } const command = new GetParameterCommand({ Name: secretName, WithDecryption: true }); const response = await ssmClient.send(command); const secret = response.Parameter!.Value!; try { const decoded = jwt.verify(token, secret); return generatePolicy('user', 'Allow', event.methodArn); } catch (error) { logger.error("JWT verification failed", err); throw new Error("Unauthorized"); } };
📜 Step 2: Define the Authorizer in template.yml
Resources: AuthorizerFunction: Type: AWS::Serverless::Function Properties: Handler: authorizer.handler Runtime: nodejs22.x Environment: Variables: JWT_SECRET: "your-secret-here" Policies: - Statement: Effect: Allow Action: - ssm:GetParameter Resource: "[path-to-resource]" HelloWorldFunction: Type: AWS::Serverless::Function Properties: Handler: index.handler Runtime: nodejs22.x Events: HelloWorldApi: Type: Api Properties: Path: /hello Method: get RestApiId: !Ref MyApi MyApi: Type: AWS::Serverless::Api Properties: StageName: prod Auth: DefaultAuthorizer: LambdaAuthorizer Authorizers: LambdaAuthorizer: FunctionArn: !GetAtt AuthorizerFunction.Arn
⚡️ Bonus Tip: HTTP API + JWT Authorizers
If you're using HTTP API instead of REST API, you can configure a JWT Authorizer without needing a custom Lambda Authorizer — built-in, easier, and faster!
Resources: MyHttpApi: Type: AWS::Serverless::HttpApi Properties: Auth: Authorizers: MyJwtAuthorizer: JwtConfiguration: issuer: https://your-issuer.com audience: - your-audience IdentitySource: "$request.header.Authorization" DefaultAuthorizer: MyJwtAuthorizer
✅ Benefits:
- No Lambda function to maintain
- Faster authentication (native integration)
- Lower cost
Conclusion
Using Lambda Authorizers with JWT gives you powerful, flexible API security.
✅ Now your API is secured with a custom Lambda Authorizer that verifies JWT tokens.
✅ Full control over authentication and authorization.
✅ For simple cases, prefer HTTP API + Native JWT authorizers for speed and simplicity
Top comments (0)