Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the authenticated user's email address in node.js AWS Lambda?

I have an Angular app that uses the AWS javascript SDK, and can successfully login with Facebook and Google. I am able to create the Cognito identity and I see the identity in my Federated Identity pool. I am also able to use my IAM authenticated API endpoints (I see the user's cognitoId in the Lambda I am calling).

I want to use the user's email address as the key in the database (DynamoDB), so I am trying to figure out how to access the user's email address from a trusted source, either Cognito (preferred) or the Authentication Provider's JWT.

What is the best way to access the user's email address?

Update: On the client side (javascript) I'm using Federated Identities with Google and Facebook tokens. The social login is working, and I can get authenticated with Cognito just fine, passing the Logins:

AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: 'us-east-1:****',
    Logins: {
      'accounts.google.com': authResult['id_token']
    }
});

I then do AWS.config.credentials.get() and I can get things like AWS.config.credentials.identityId, but I can't find accessToken or the methods to call to get the JWT. I believe I need to call result.getAccessToken().getJwtToken(), but I can't find it.

All of the examples where they get the accessToken seem to use .authenticateUser(authenticationDetails()), but the details include a user name and password (not Federated login).

like image 383
flyingMonkeys Avatar asked Dec 28 '16 02:12

flyingMonkeys


People also ask

How do I authenticate AWS Lambda?

To sign in directly to the AWS Management Console , use your password with your root user email address or your IAM user name. You can access AWS programmatically using your root user or IAM users access keys. AWS provides SDK and command line tools to cryptographically sign your request using your credentials.

Does AWS lambda support node JS?

AWS Lambda now supports Node. js 16 as both a managed runtime and a container base image. Developers creating serverless applications in Lambda with Node. js 16 can take advantage of new features such as support for Apple silicon for local development, the timers promises API, and enhanced performance.


1 Answers

tldr; Send the accessToken post-authentication to lambda and use CognitoIdentityServiceProvider.getUser() to obtain the attributes.

I spent hours fumbling around with the ID tokens and from what I can tell, the only way to get a user's actual identity is to use a combination of the accessToken provided from a successful authentication and the getUser call from the identity provider. This only appears to be for the NodeJS SDK and nothing else.

I am using Amazon's API Gateway for my application and Lambda in the background. After a successful authentication, you can access the accessToken and feed it to a Cognito server provider. From there, you can save the details locally, but it presents a large security issue if you plan to use this information on the backend. Since it's local storage, the user can just adjust the user attributes to whatever they like.

To get around this, you can pass the accessToken to the lambda function directly and perform the same process on the server. Doing this ensures that the user attributes have not been manipulated or tampered with. Be sure to use HTTPS on your API to avoid leaking the accessToken to others who could use the AWS SDK to get the internal details.

var AWS = require("aws-sdk");

AWS.config.region = '<REGION-ID>';

exports.lambda_handler = function(event, context) {
  var accessToken = event['accessToken'];
  var provider = new AWS.CognitoIdentityServiceProvider();
  provider.getUser({
    AccessToken: accessToken
  }, function(err, obj) {
    context.succeed({
      'user': obj
    });
  });
};
like image 75
user1257332 Avatar answered Sep 21 '22 23:09

user1257332