I want to use an Amazon Cognito user pool as the authentication method for my application. What is a secure way for me to verify the ID and access tokens sent by clients to my application?

When clients authenticate to your application with a user pool, Amazon Cognito sends an ID token. You might want to manually verify that ID token to trust the information contained in it. Some examples include:

  • You created a web application and want to use an Amazon Cognito user pool for authentication.
  • You use an Amazon Cognito user pool for authentication and an Amazon Cognito identity pool to retrieve AWS Security Token Service (AWS STS) temporary credentials. AWS Lambda is invoked with those credentials, but Lambda doesn’t have information about who originally authenticated with the user pool.

To get Amazon Cognito user details contained in an Amazon Cognito JSON Web Token (JWT), you can decode it and verify the signature. To decode and verify Amazon Cognito JWT using AWS Lambda, see Decode and verify Amazon Cognito JWT tokens on the GitHub website.

After a user logs in, an Amazon Cognito user pool returns a JWT, which is a base64-encoded JSON string that contains information about the user (called claims). Amazon Cognito returns three tokens: the ID token, the access token, and the refresh token. The ID token contains the user fields defined in the Amazon Cognito user pool.

JWT tokens include three sections: a header, a payload, and a signature.

The following is the header of a sample ID token. The header contains the key ID (“kid”), as well as the algorithm (“alg”) used to sign the token. In this example, the algorithm is “RS256”, which is an RSA signature with SHA-256.

{
  "kid": "abcdefghijklmnopqrsexample=",
  "alg": "RS256"
}

The following is an example of the payload, which has information about the user, as well as timestamps of the token creation and expiration.

{
  "sub": "aaaaaaaa-bbbb-cccc-dddd-example",
  "aud": "xxxxxxxxxxxxexample",
  "email_verified": true,
  "token_use": "id",
  "auth_time": 1500009400,
  "iss": "https://cognito-idp.ap-southeast-2.amazonaws.com/ap-southeast-2_example",
  "cognito:username": "anaya",
  "exp": 1500013000,
  "given_name": "Anaya",
  "iat": 1500009400,
  "email": "anaya@example.com"
}

The following is an example of the signature, which is a hashed combination of the header and the payload. Amazon Cognito generates two pairs of RSA keys for each user pool. One of the private keys is used to sign the token. The corresponding public key becomes available at an address in this format:

https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json

The JSON file is structured in this format:

{
    "keys": [{
        "alg": "RS256",
        "e": "AQAB",
        "kid": "abcdefghijklmnopqrsexample=",
        "kty": "RSA",
        "n": "lsjhglskjhgslkjgh43lj5h34lkjh34lkjht3example",
        "use": "sig"
    }, {
        "alg":
        "RS256",
        "e": "AQAB",
        "kid": "fgjhlkhjlkhexample=",
        "kty": "RSA",
        "n": "sgjhlk6jp98ugp98up34hpexample",
        "use": "sig"
    }]
}

To verify the signature of an Amazon Cognito JWT, first search for the key with a key ID that matches the key ID of the JWT. Then, use libraries to decode the token and verify the signature. Be sure to also verify that:

  • The token is not expired.
  • The audience ("aud") specified in the payload matches the app client ID created in the Amazon Cognito user pool.

This resolution is suitable for most applications. To use AWS Lambda for this resolution, see Decode and verify Amazon Cognito JWT tokens on the GitHub website.


Did this page help you? Yes | No

Back to the AWS Support Knowledge Center

Need help? Visit the AWS Support Center.

Published: 2018-02-13