How to get Cognito identityId in AWS Lambda Functions

avatar

Borislav Hadzhiev

Thu Apr 22 20214 min read

Updated on Thu Apr 22 2021

In order to get access to the cognito identityId in Lambda we have to call the getId method on the CognitoIdentity constructor.

Getting the Identity Id of Cognito Users in Lambda #

In order to get the identityId of a Cognito user in a Lambda function we have to call the getId method on the CognitoIdentity class.

The code for this article is available on GitHub

Let's look at the complete code of a helper method, which retrieves and returns the identityId of a Cognito user.

src/cognito-id/index.ts
import AWS from 'aws-sdk';

export function getCognitoIdentityId(
  jwtToken: string,
): Promise<string> | never {
  const params = getCognitoIdentityIdParams(jwtToken);
  const cognitoIdentity = new AWS.CognitoIdentity();

  // ๐Ÿ‘‡ get and return the identityId
  return cognitoIdentity
    .getId(params)
    .promise()
    .then(data => {
      if (data.IdentityId) {
        return data.IdentityId;
      }
      throw new Error('Invalid authorization token.');
    });
}

// ๐Ÿ‘‡ construct the parameters for the getId method
function getCognitoIdentityIdParams(jwtToken: string) {
  const {
    USER_POOL_ID,
    ACCOUNT_ID,
    IDENTITY_POOL_ID,
    AWS_DEFAULT_REGION,
  } = process.env;
  const loginsKey = `cognito-idp.${AWS_DEFAULT_REGION}.amazonaws.com/${USER_POOL_ID}`;

  return {
    IdentityPoolId: IDENTITY_POOL_ID,
    AccountId: ACCOUNT_ID,
    Logins: {
      [loginsKey]: jwtToken,
    },
  };
}

Let's go over the code snippet.

We have created a getCognitoIdentityId function, which:

  • retrieves and returns the identityId of a Cognito user
  • takes a single parameter - the jwtToken of the user making the request, most commonly sent via the Authorization Http Header
  • calls the getId method on the CognitoIdentity class via the aws-sdk

We have also created a getCognitoIdentityParams function, which is responsible for constructing the parameters the getId method takes.

In this implementation, the USER_POOL_ID, IDENTITY_POOL_ID and ACCOUNT_ID values have been passed to the lambda as environment variables. The AWS_DEFAULT_REGION value would also have to be replaced with the region your User Pool is deployed in.

A very important detail is, that we access the user's jwt token from theAuthorization header. Based on the JWT token the Cognito service is able to return the user's identityId.

Verifying our Solution works #

In order to test the getCognitoIdentityId function, I've created a simple CDK stack, which provisions:

  • Cognito user pool
  • Cognito user pool client
  • Cognito identity pool
  • Lambda function that gets and returns the User's identity id
  • Api gateway with Lambda proxy integration
The code for this article is available on GitHub

Project Set up #

  1. Clone the GitHub repository

  2. Install the dependencies

shell
npm install
  1. Create the CDK stack
shell
npx cdk deploy \
  --outputs-file ./cdk-outputs.json
  1. Open the AWS Console and the stack named cdk-stack should be created in your default region

Testing our Solution #

Let's test the lambda function, that gets the identityId of a Cognito user.

In order to test the flow, we have to:

  1. create a Cognito user
  2. confirm the user so they can sign in
  3. log the user in to get a JWT token
  4. use the token to invoke our API endpoint which will call the function and return the cognito identity id
You can find the User Pool Id, User Pool Client Id and Api Url identifiers in thecdk-outputs.json file in the root directory of your project. Alternatively you can grab them using the AWS Console.
Make sure you don't confuse the User Pool id and the User Pool Client id, because the commands below use both.
  1. Sign a user up, using the aws cli:
shell
aws cognito-idp sign-up \
  --client-id YOUR_USER_POOL_CLIENT_ID \
  --username "test@test.com" \
  --password "password123"
  1. Confirm the user, so they can sign in
shell
aws cognito-idp admin-confirm-sign-up \
  --user-pool-id YOUR_USER_POOL_ID \
  --username "test@test.com"

At this point if you look at the Cognito User Pool, you would see that the user is confirmed and ready to sign in:

user pool user

  1. Log the user in
shell
aws cognito-idp initiate-auth \
  --auth-flow USER_PASSWORD_AUTH \
  --auth-parameters \
  USERNAME="test@test.com",PASSWORD="password123" \
  --client-id YOUR_USER_POOL_CLIENT_ID

You will get a verbose response, because of the length of the tokens. We only care about the IdToken, so copy and paste it into a notepad, because we will need it.

Make sure that you copy the IdToken, not the Access or Refresh Tokens.
  1. Hit our api to get the lambda identityId. You can find the api url in the cdk-outputs.json file in the root directory, or by opening the API gateway console.
shell
curl --location --request GET 'YOUR_API_URL/cognitoid' \
  --header 'Authorization: YOUR_ID_TOKEN'

The response should look like:

api-response
{"identityId": "eu-central-1:5b117ba7-3a85-4fa4-a6c9-a8415d7ccdc8"}

At this point we know, that we were able to get a cognito user's identity id in our lambda function.

Clean up #

In order to delete the provisioned resources, run the destroy command:

shell
npx cdk destroy

Conclusion #

We are able to access the cognito user's identityId by calling the CognitoIdentity().getId method.

Based on the JWT token that was sent in the Authorization header cognito will determine the user's identityId.

Further Reading #

Join my newsletter

I'll send you 1 email a week with links to all of the articles I've written that week

Buy Me A Coffee