3

I currently have a number of Lambdas which query a DynamoDB. The Lambda is exposed/invoked via an API Gateway REST API which is configured to use AWS_IAM authorization.

My Cognito user pool is currently assigning different IAM roles based on various information, and most importantly, the IAM role is limiting access to the specific row on the DynamoDB that matches the user's Cognito Identity ID. These roles work as expected, and when querying the DynamoDB directly, the roles only allow a user to read their own row.

However I need some manipulation done before returning the data to the user, so I currently have the lambda performing the query instead of accessing dynamo directly. The lambda is obviously configured with its own Lambda Execution Role which currently gives read access to the entire DB.

However what I am trying to do is to pass the users Cognito Credentials through Api Gateway, through to Lambda and then have lambda assume the IAM role of the logged in user before making the dynamo query, thereby only allowing the Lambda to read from the user's own row in the DynamoDB.

I've spent a few days trying everything from AWS_IAM authorization, to Cognito User Pool Authorization and any other ideas I've found online, however I have never actually managed to get the Lambda to assume the role.

Currently I have "Invoke using caller credentials" enabled for the Api Gateway method, and my code is reading the Cognito Identity ID from the event as such:

const cognitoIdentityId = event.requestContext.identity.cognitoIdentityId`

And I am passing this into the Dynamo query, however

1) I'm not sure if this is secure enough / would allow someone to manipulate a request to access someone elses data.

2) I'm no expert, but it "feels" like I should be using a fine-grained IAM role for this, rather than just relying on my Dynamo query being correct

If anyone can advise if I am approaching this the right way, or if it's even possible, or if there is a better approach that would be great.

Thanks!

Mark McKim
  • 553
  • 1
  • 5
  • 9

1 Answers1

3

You can get temporary credentials for your cognito identity to get temporary access key, secret key and sessions key. These expire after an hour just like the access and id token. But you can use these credentials to let the lambda assume the role of your logged in user. You can find the documentation for getting these credentials here.

Ninad Gaikwad
  • 4,272
  • 2
  • 13
  • 23
  • Thanks for the reply. That sounds like what I am trying to achieve but I'm not clear on how to pass the token through Api Gateway and down to Lambda. Currently I am using AWS_IAM authentication and all I have access to is the Cognito Identity ID. I also wasn't sure 1) If this is good practice passing the token this way and 2) If this was the best way to achieve what I wanted. – Mark McKim Aug 01 '19 at 12:19
  • 1
    You can pass the idtoken to Api Gateway. Then use GetCredentialsForIdentity API to fetch temporary credentials for the user by passing the identity pool id and the id token. https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html – Ninad Gaikwad Aug 01 '19 at 13:20
  • OK great. Thanks for the clarification. Is there an "in-built" way of doing this using Amplify and Api Gateway? Or should I just manually add the token as an "IDToken" header to each request? (I assume I can't use the Authorization header as this is required for AWS_IAM authentication at the Api Gateway layer?) – Mark McKim Aug 01 '19 at 13:48
  • You can just manually add the idtoken. It is pretty secure since it will expire within an hour anyway. And you can keep the identity pool id saved as environment variable on your lambda. – Ninad Gaikwad Aug 01 '19 at 13:56
  • 1
    Awesome. Thanks. I have seen people refer to switching the Authorization type from AWS_IAM to a Cognito User Pool Authorizer and then passing the ID token as the Authorization header on the request. Would that accomplish the same job with less complexity? (And still allow me to accomplish the same thing in the lambda), or would you recommend sticking with AWS_IAM as the authorisation type? Thanks for your help! – Mark McKim Aug 01 '19 at 14:00
  • 1
    That would be a much better strategy. Cognito user pool land identity pool work great together – Ninad Gaikwad Aug 01 '19 at 14:03
  • 1
    Awesome. I'll give that a try! Thanks for all your help! – Mark McKim Aug 01 '19 at 14:08