1

I created a AWS API Gateway set with authentication = AWS_IAM to call a Lambda function. Now, to call this API I understand that I need to sign the request and as stated in the AWS documentation the correct way is to add the Authorization header calculated using AWS Signature V4 which need an access_key and a secret_key. On my client side the user authenticate with AWS Cognito first and receive the JWT tokens (id token access token and refresh token) but I cannot find the access_key/secret _key in them. How can I calculate the AWS Signature V4 from the tokens received from AWS Cognito?

AleCat83
  • 1,443
  • 3
  • 22
  • 41

1 Answers1

2

I believe you can't (with 99,99999 of certainty)!

Please confirm that you are authenticating your users with AWS Cognito User Pool. You probably are because Cognito User Pool is the service that provides JWT. In this case, the token will assure the service that receives it (API Gateway) that your user is registered in a specific identity directory (User Pool). Your service should evaluate if it will provide access or not to its resources for users registered in this specific directory with the provided claims (groups, roles, etc).

When you secure your API Gateway endpoints with AWS_IAM you are saying that only identities that AWS can recognize inside its own identity directory (Users or Roles) are allowed to perform actions on the resource. In general, users registered in Cognito User Pools are not considered by AWS as valid identities.

For a Cognito User Pool user to be considered a valid AWS identity, you have two options:

1 - Configure your AWS account to use external Identity Providers and Federation. Not a simple thing and a solution to a different use case. In summary, don't choose this one.

2 - Use another AWS product (with a name that creates a lot of confusion) called Cognito Identity Pool. This service evaluates if the JWT token is allowed in that context (you configure it inside the Identity Pool). If is a valid token from a registered identity directory, Cognito Identity Pool will exchange your JWT token for a AWS Access Key, AWS Secret Key and AWS Session Token associated with a specific IAM Role. You can then use these keys to sign your request. But keep in mind that with this change you will lose your capacity to identity the specific user in API Gateway and in the downstream services called by API Gateway. If you need to have the JWT token in your downstream services, you can do it with a little bit of additional effort. You can't find a way here: https://stackoverflow.com/a/57961207/6471284

Gustavo Tavares
  • 2,579
  • 15
  • 29
  • Thanks for the reply. I am actually using the Identity provider. I am now able to auth the API calls using AWS Amplify. Now I was wondering if there is a way to call the rest API from the backend (PHP) having the access token stored in session. So the user authenticate on the client site, get the token, send the token to the backend, store it into session and use it to call the REST API when a new page is loaded (giving that the session is still there). – AleCat83 Mar 12 '20 at 19:53
  • You probably can introspect your local storage in amplify and get the tokens. But I believe that in your case it is not needed. Maybe I didn’t understood correctly your use case, but If you are already in the backend, assuming that your backend is inside AWS because it is secured by IAM in API Gateway, you can query your backend environment and get the credentials for your execution role. If you are using Aws Lambda you can find then in AWS_ACCESS_KEY or AWS_SECRET_ACCESS_KEY env variables. They also are available on EC2 and ECS. Probably also in Fargate. – Gustavo Tavares Mar 12 '20 at 20:44