API Gateway: Using a Cognito User Pool authorizer to inject userid and email into request


I inherited an API Gateway setup that uses a Cognito User Pool as an authorizer. For some reason, the Lambda functions that serve the API do the authorization all over again, taking the "Authorization" header from the request and doing their own JWT decode routine. So far as I know this is unnecessary, since if the request gets to this point the user is already authenticated against Cognito.

So I think I can remove that extra layer of authentication. My question is about getting access to the user's Cognito attributes such as username and email. The code right now uses the "cognito_idp" boto3 client to make a "get_user" call with the access token from the "Authentication" header. I have to think that this is redundant! But while the request has fields for Cognito user attributes, they're all set to None.

Am I missing something about the proper way to get access to a user's attributes via the Cognito authorizer?

1 Answer
Accepted Answer

If you have set Cognito User Pool Authentication in API Gateway, you are right that API Gateway will block the request if it is not a valid user.

The identity token or access token from Cognito User Pool will be a JWT token. Validating the JWT at the backend is an extra layer of protection if your backend wants to ensure that there is no rogue actor in the middle that is sending requests with fake JWT tokens directly bypassing the API Gateway. There are other ways to prevent that scenario, but the person from whom you inherited the application may have had that thought process.

Also if your backend needs claims from the JWT token to do other things and need access to the claims, then the backend has to parse the JWT.

If users have registered in the Cognito user pool user properties such as email and phone number, then those properties should be available in the JWT claims. Do you see those as blank for a user who has those properties set in the Cognito user pool?

profile pictureAWS
answered 2 years ago
profile picture
reviewed 3 months ago
  • Thanks very much for this reply! I appreciate the background on the JWT validation, and the fact that there might be a good reason for doing the validation over again in the Lambda function.

    As for the Cognito user attributes, I was expecting them to be present in the context that is passed to the Lambda. There's supposed to be a "context.authorizer" object, with a further "claims" attribute, but the "authorizer" attribute doesn't exist. Other documentation mentions a "context.identity" object, which I see, and a "context.identity.cognito_identity_id" attribute, but that is None in my case.

    The username is indeed available via the decoded JWT payload. So it looks like my options are to read it from the JWT payload and skip the Cognito lookup, or do the Cognito lookup and skip the JWT token decoding. But I was expecting that the Cognito user attributes would be made available via the "context" argument to the Lambda! Is this not the case?

    Thanks again

  • Did you do the mapping in the Integration Request to get the fields from the Cognito identity token context to the integration, as explained in this - https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-enable-cognito-user-pool.html

    Unless the mapping is done, it won't automatically show up in your backend.

  • That's what I was missing! Thanks so much for that pointer. It will be very nice to clear all this unnecessary code out of there.

  • I follow what you are saying here, but you authenticate to the API using the Access token, not the ID token. If he is using the standard JWT Authorizer on his routes, I do not think that will accept the ID token. It has to be the access token, and that doesn't give you all those claims.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions