FREE TOOL

Cognito JWT Inspector

Paste an Amazon Cognito ID or access token and see its claims explained - token_use, cognito:groups, exp, iss, aud and client_id - and why an API rejects it: expired, an ID token instead of an access token, another user pool or app client.

  • Your data never leaves your browser: everything is calculated by JavaScript on this page, not on a server.
  • Nothing you enter is uploaded, processed on a server or stored. Check it in your browser's developer tools (Network tab).
  • Once the page has loaded, the tool works without an internet connection.

Cognito token

An ID or access token, an Authorization: Bearer header, or the whole output of aws cognito-idp initiate-auth. It is decoded here and never leaves your browser.

What the API expects

Optional: from the authorizer, the verifier's configuration or the app's settings - to name a token of the wrong type, user pool or app client.

See the claims ↓
Cognito user pools, tokens and API Gateway authorizers are AWS Developer Associate topicsTry free DVA-C02 practice questions with answers and explanations.DVA-C02 questions →

Cognito ID token vs access token

A Cognito user pool issues three tokens at every sign-in. The ID token says who the user is, for your app; the access token says what the caller may do, for your APIs; the refresh token gets new ones of both. The ID and access tokens are JSON Web Tokens anyone can decode - which is why this page can show their claims without your pool's keys - while the refresh token is encrypted.

ClaimID tokenAccess token
token_useidaccess
App client IDin audin client_id
scopenonethe OAuth scopes granted
Usernamecognito:usernameusername
cognito:groupsyesyes
Email, name, custom attributesyes, those the app client may readno
sub, iss, exp, iat, auth_timeyesyes

exp, iat and auth_time are seconds since 1970 in UTC. auth_time is when the user signed in and stays the same across refreshes; iat is when the token itself was issued. ID and access tokens last 60 minutes by default and between 5 minutes and 1 day as set per app client; the refresh token lasts 30 days by default.

Why an API rejects a Cognito token

SymptomMost common cause
401 Unauthorized after about an hourThe token expired: the app has to refresh it with the refresh token before exp
401 from a REST API method with OAuth scopes, or an HTTP API route with authorization scopesThe ID token was sent: only the access token has scope
CognitoJwtInvalidTokenUseError from aws-jwt-verifyThe ID token was sent where the verifier expects the access token
401 with a token that worked in another environmentA token of another user pool - each pool signs with its own keys, and iss names the pool
401 from an HTTP API JWT authorizer although the pool is rightThe token's app client is not in the authorizer's audience: aud for ID tokens, client_id for access tokens
The token has no email or custom attributesIt is an access token; the attributes are in the ID token, or come from GetUser

A REST API's Cognito user pool authorizer treats the token as an ID token unless the method has OAuth scopes; then it needs the access token and checks its scopes. An HTTP API's JWT authorizer takes either, as long as the issuer is https://cognito-idp.REGION.amazonaws.com/POOL_ID and the app client ID is in its audience list. Tokens from the sign-in API (InitiateAuth) carry only the scope aws.cognito.signin.user.admin; custom scopes come only through managed login or the OAuth endpoints.

How to verify a Cognito JWT

Decoding a token is not verifying it - anyone can write a token with any claims. A server must check, in this order: the signature, with the public key from the pool's JSON Web Key Set (https://cognito-idp.REGION.amazonaws.com/POOL_ID/.well-known/jwks.json) whose kid matches the token header's; that iss is the pool; that token_use is the type it expects; that aud or client_id is its app client; and that exp has not passed. AWS's aws-jwt-verify library for Node.js does all of it:

import { CognitoJwtVerifier } from "aws-jwt-verify";

const verifier = CognitoJwtVerifier.create({
  userPoolId: "us-east-1_EXAMPLE1",
  tokenUse: "access",
  clientId: "1example23456789abcdefghij",
});

// Throws if the signature, issuer, token type, app client or expiry is wrong.
const payload = await verifier.verify(token);

Behind API Gateway, let the authorizer verify the token, and read the claims it passes on (event.requestContext.authorizer.claims for a REST API, event.requestContext.authorizer.jwt.claims for an HTTP API).

Frequently asked questions

Is it safe to paste a Cognito token here?

The token is decoded in your browser: nothing you paste is uploaded, processed on a server or stored. The page only counts that the inspector was used and which mistake it named, never the token or its claims. A token is still a credential until it expires, so paste only into pages you trust - and prefer an expired one.

Can I decode the Cognito refresh token?

No. It is encrypted with a key only Cognito has (a JWE, five parts instead of three), and no API accepts it. Use it only to get new ID and access tokens.

Where are the user's groups?

In cognito:groups, in both the ID and the access token, listing the groups the user belongs to. The ID token also has cognito:roles and cognito:preferred_role, the IAM roles of those groups that an identity pool can assume for the user.

How do I change how long the tokens last?

Per app client: set ID token, access token and refresh token expiration in the console, or IdTokenValidity, AccessTokenValidity, RefreshTokenValidity and TokenValidityUnits with update-user-pool-client. Tokens already issued keep their exp.

References

Understanding the identity (ID) token
Understanding the access token
Refresh tokens
Verifying JSON web tokens
Control access to REST APIs using Amazon Cognito user pools
Control access to HTTP APIs with JWT authorizers
aws-jwt-verify