Introduction

An API that is exposed to the public must admit only callers whose identity has been confirmed and who are permitted to perform the requested action. This guide explains how such protection is built with Amazon Cognito and Amazon API Gateway. Readers who are new to these services should first read the guides on Amazon Cognito and Amazon API Gateway.

What is the pattern?

The pattern combines a Cognito user pool, which authenticates users and issues tokens, with API Gateway, which validates those tokens before a request is admitted. Validation is performed by an authorizer, which is a component that checks the identity and permissions of a caller. Two forms of authorizer are available. A Cognito authorizer validates a token from a user pool without custom code, and a Lambda authorizer runs a function that applies custom logic.

Why does it exist?

Verifying a caller correctly is difficult and easy to get wrong. Tokens must be validated, expired tokens must be refused, and permissions must be enforced. If each API were to build this from the beginning, the risk of a security flaw would be high. The pattern exists so that authentication is provided by Cognito and validation is provided by API Gateway, which leaves the backend to enforce only the decisions that depend on the data.

How it works

The user signs in to the user pool and receives an ID token and an access token. On each request, the client sends a token in the Authorization header. API Gateway invokes the authorizer, which verifies the signature, the expiration time, and the audience of the token. If the token is valid, the request is forwarded to the backend, most often a Lambda function, together with the claims from the token.

The backend then performs authorization. A user can be placed in a Cognito group, and the group appears as a claim in the token. A scope is a value in an access token that states what the token is permitted to do. The backend reads these claims and permits or refuses the action accordingly.

Architecture diagram

User | sign in v Cognito user pool --> issues ID and access tokens | | Authorization: Bearer v API Gateway --> authorizer validates the token | (signature, expiry, audience) v Lambda backend --> reads the claims (group, scope) and enforces what the caller may do

Advantages

Disadvantages

Common use cases

Best practices

Common mistakes

Further reading in this library

Frequently Asked Questions

How does API Gateway validate a Cognito token?
A Cognito authorizer is attached to the API. The token in the Authorization header is checked against the user pool, and the signature, expiration, and audience are verified. The request is admitted only if the token is valid.
What is the difference between authentication and authorization in this design?
Authentication confirms who the caller is, established by the valid token. Authorization decides what the caller may do, determined from the groups or scopes in the token and enforced by the backend.
What is the difference between a Cognito authorizer and a Lambda authorizer?
A Cognito authorizer validates a user pool token with no custom code. A Lambda authorizer runs a function that can apply custom logic, used when validation must go beyond the standard check.
How is access limited by role?
A user can be placed in a Cognito group that appears as a claim in the token. The backend reads this claim and permits or refuses the action. Scopes can be used in a similar way.
Should the backend re-check the caller even after the gateway validates the token?
Yes. The gateway confirms that the token is valid, but the backend should still enforce what the specific caller may do for the specific resource.
AWS Cognito book cover
Go deeper ยท Book as a Service™
AWS Cognito

This article is the summary. The book is the full, continuously updated reference: authorizers, groups and scopes, Lambda triggers, token validation, and securing a real website.

View the book