1

I'm using Amazon Mobile Hub to build a mobile app. I used AWS Cognito within the MobileHub to authenticate users with sign up and sign in. I'm now trying to use AWS Lambda to communicate with DynamoDB to do some operations.

While doing that, I stumbled upon a problem which is that I'm not sure how to verify a user. In a sense that if I send the Access Token via Cloud Logic to my Lambda function, how would I verify that token and move forward with my operations with the username retrieved from that token?

This SDK allows Lambda functions to communicate with AWS Cognito features but I didn't find any useful functions to actually verify tokens. https://github.com/aws/amazon-cognito-identity-js

2 Answers 2

1

You can use Custom Authorizers in AWS apigateway to authorize the API request. The access token can be send as request header for all authenticated APIs and when it reach to API gateway custom authorizer logic will invoke hence a lambda function will invoke and that access token can be validated. Here is the example for custom authorizer.

Sign up to request clarification or add additional context in comments.

Comments

1

So you have two options when using Cognito for authorization.

1) You can attach a Cognito Authorizer to the API, which "Just works", under the hood cognito verifies the token. You don't get much control over the authorization process, it's either a yes or a no basically.

2) As prateek said you can use a custom authorizer, something a bit like this, note: I've put the key in the code this is a very bad idea and you should store it in an environment variable KMS encrypted.

import jwt from 'jsonwebtoken' export default (event, context, callback) => { const key = '' // <--- YOU GET THIS KEY FROM https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json. jwt.verify(event.authorizationToken, key, (err, decoded) => { if (err) { console.log('JWT VALIDATION ERROR') callback(null, responder.unAuthorised()) return } const principalId = decoded.user.username const apiOptions = {} const tmp = event.methodArn.split(':') const apiGatewayArnTmp = tmp[5].split('/') const awsAccountId = tmp[4] apiOptions.region = tmp[3] apiOptions.restApiId = apiGatewayArnTmp[0] apiOptions.stage = apiGatewayArnTmp[1] const method = apiGatewayArnTmp[2] let resource = '/' // root resource if (apiGatewayArnTmp[3]) { resource += apiGatewayArnTmp[3] } const policy = new AuthPolicy(principalId, awsAccountId, apiOptions) // DENY policy.denyMethod(AuthPolicy.HttpVerb.POST, "/someEndpoint") // PERMIT policy.allowMethod(AuthPolicy.HttpVerb.POST, "/someEndpoint") const authResponse = policy.build() // YOU CAN EMBED ANYTHING ELSE YOU WANT TO ADD LIKE SO: authResponse.context = { username: decoded.username, someKey: someInfo, } callback(null, authResponse) }) // jwt.verify( } 

I can't remember what claims cognito puts in its token, but after you jwt.verify just console log the decoded token and you'll see a load of information from you user pool, you can then pass that down in authResponse.context and it'll appear within your lambda under event.requestContext.authorizer.

Remember that the Identity Token is the one that'll contain the info from the user pool.

1 Comment

Okay, so what I've done is I called my API using CloudLogic and passed my access token from the Cognito sign in through the POST method body. Then, my back-end code verifies and gets a username from that token using CognitoIdentityServiceProvider. That's okay, right?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.