Get Cognito user pool identity in Lambda function
Asked Answered
A

2

16

I have a Lambda function handling POST requests triggered by the API Gateway. The latter is set up to authorize via a Cognito user pool authorizer. Authorization works - if I pass a user's ID token, the request is processed, if I don't I get a 401.

However, I can't get the authorized user's identity in the Lambda function. All documentation makes me believe that it should be in the context, but it isn't. I can't map it in there, either. What's more, there doesn't seem to be a way to query the user pool for a user given their ID token, either.

Do I need an identity pool to accomplish this? If so, how does that work? And why wouldn't the API gateway automatically pass on the user's identity?

Alginate answered 28/5, 2018 at 23:18 Comment(0)
L
32

It depends on if you have Use Lambda Proxy Integration selected in the Integration Request for the lambda. If you have it set then all the token's claims will be passed through on event.requestContext.authorizer.claims.

If you are not using Lambda Proxy Integration then you need to use a Body Mapping Template in the Integration Request for the lambda. An example template with the application/json Content-Type is:

"context" : {
    "sub" : "$context.authorizer.claims.sub",
    "username" : "$context.authorizer.claims['cognito:username']",
    "email" : "$context.authorizer.claims.email",
    "userId" : "$context.authorizer.claims['custom:userId']"
}

This is expecting that there is a custom attribute called userId in the User Pool of course, and they are readable by the client.

You cannot use the id token against the aws cognito-idp APIs, you need to use the access token. You can however use AdminGetUser call with the username, if your lambda is authorized.

Linked answered 1/6, 2018 at 1:5 Comment(5)
+1 Also works in python except event is a dictionary and each key listed above needs to be accessed as a dictionary key.Keneth
for some reason $context.authorizer.claims.email always returns null. I do see value being passed for sub. Any pointers?Employment
if I enable "Lambda Proxy Integration" I can't get CORS to work, no matter what, I get CORS errors in my webapp. Why is that?Supersede
@Supersede the return value of Lambda is considered as response and that should allow the origin not API GatewayLepore
To whom it may concern: you need to make a new deployment in order for changes to the integration mapping template to really take effect. I had to comment things out of my cloud formation template in order to persuade cloud formation to do so.Rickety
T
4

Use the event.requestContext.authorizer.claims.sub to get user's Cognito identity sub, which is basically their ID. This assumes you're using Proxy Integration with API Gateway and Lambda.

Here's a simple example using Node; should be similar across other SDKs.

exports.handler = async (event, context, callback) => {
    let cognitoIdentity = event.requestContext.authorizer.claims.sub

    // do something with `cognitoIdentity` here

    const response = {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Origin": "*"
        },        
        body: JSON.stringify("some data for user"),
    };
    return response;
};
Twohanded answered 18/11, 2018 at 23:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.