Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Cognito - Developer Authenticated Identities in JavaScript(Browser)

I have trouble getting credentials in a browser script.

The authentication server returns cognito_identityId and cognito_token.

Then I set a Cookie:

  • $.cookie('cognito_identityId')
  • $.cookie('cognito_token')

I tried to get credentials in 4 ways on the browser, and all Failed:

  1. CognitoIdentityCredentials

    AWS.config.credentials = new AWS.CognitoIdentityCredentials({
        IdentityPoolId: 'us-east-1:xxxxxxxxxxxx'
        IdentityId: $.cookie('cognito_identityId'),
        Logins: {
            'myauth': $.cookie('cognito_token')
        }
    });
    

    // => Error: Missing required key 'IdentityId' in params

  2. assumeRoleWithWebIdentity

    var params = {
      RoleArn: 'arn:aws:iam::xxxxxxxxxxxx:role/Cognito_xxxxxxxAuth_Role',
      RoleSessionName: 'xxxxxxxxxxx',
      WebIdentityToken: $.cookie('cognito_token'),
      DurationSeconds: 900,
      ProviderId: 'myauth'
    };
    var sts = new AWS.STS({apiVersion: '2011-06-15'});
    sts.assumeRoleWithWebIdentity(params, function(err, data) {
      if (err) console.log(err, err.stack); // an error occurred
      else     console.log(data);           // successful response
    });
    

    // => AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity

PolicyDocument

{
"Version": "2012-10-17",
"Statement": [
  {
    "Sid": "",
    "Effect": "Allow",
    "Principal": {
      "Federated": "cognito-identity.amazonaws.com"
    },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringEquals": {
        "cognito-identity.amazonaws.com:aud": "us-east-1:xxxxxxxxxxxxx"
      },
      "ForAnyValue:StringLike": {
        "cognito-identity.amazonaws.com:amr": "authenticated"
      }
    }
  }
]
}
  1. GetCredentialsForIdentity

    var params = {
        IdentityId: $.cookie('cognito_identityId'),
        Logins: {
          "myauth": $.cookie('oauth.io_token')
        }
    };
    var cognitoidentity = new AWS.CognitoIdentity({apiVersion: '2014-06-30'});
    cognitoidentity.getCredentialsForIdentity(params, function(err, data) {
      if (err) {
        console.log(err, err.stack); // an error occurred
      }
      else {
        console.log(data);           // successful response
      }
    });
    

    // => InvalidParameterException: Please provide a valid public provider

  2. WebIdentityCredentials

    AWS.config.credentials = new AWS.WebIdentityCredentials({
        RoleArn: 'arn:aws:iam::xxxxxxxx:role/Cognito_xxxxxxxxxxAuth_Role',
        WebIdentityToken: $.cookie('cognito_token')
    });
    

    // => Error: There were 2 validation errors: // * MissingRequiredParameter: Missing required key 'IdentityPoolId' in params // * MissingRequiredParameter: Missing required key 'IdentityId' in params

Questions:

  • What am I doing wrong?

  • What is the correct way to use this?

Thank you.


Thank you for your kindness.

I tyied your advice, but did not change.

Error messages.

POST https://cognito-identity.us-east-1.amazonaws.com/ 400 (Bad Request)
POST https://cognito-identity.us-east-1.amazonaws.com/ 400 (Bad Request)
Error: Missing required key 'IdentityId' in params
    at fail (chrome-extension://hmjdjbikinkmjbilihjibcihbkbjdgjf/bower_components/aws-sdk-js/dist/aws-sdk.js:2163:37)
    at validateStructure (chrome-extension://hmjdjbikinkmjbilihjibcihbkbjdgjf/bower_components/aws-sdk-js/dist/aws-sdk.js:2084:14)
    at validateMember (chrome-extension://hmjdjbikinkmjbilihjibcihbkbjdgjf/bower_components/aws-sdk-js/dist/aws-sdk.js:2110:21)
    at validate (chrome-extension://hmjdjbikinkmjbilihjibcihbkbjdgjf/bower_components/aws-sdk-js/dist/aws-sdk.js:2059:10)
    at Request.VALIDATE_PARAMETERS (chrome-extension://hmjdjbikinkmjbilihjibcihbkbjdgjf/bower_components/aws-sdk-js/dist/aws-sdk.js:800:32)
    at Request.callListeners (chrome-extension://hmjdjbikinkmjbilihjibcihbkbjdgjf/bower_components/aws-sdk-js/dist/aws-sdk.js:3913:20)
    at callNextListener (chrome-extension://hmjdjbikinkmjbilihjibcihbkbjdgjf/bower_components/aws-sdk-js/dist/aws-sdk.js:3903:12)
    at chrome-extension://hmjdjbikinkmjbilihjibcihbkbjdgjf/bower_components/aws-sdk-js/dist/aws-sdk.js:787:9
    at finish (chrome-extension://hmjdjbikinkmjbilihjibcihbkbjdgjf/bower_components/aws-sdk-js/dist/aws-sdk.js:126:7)
    at chrome-extension://hmjdjbikinkmjbilihjibcihbkbjdgjf/bower_components/aws-sdk-js/dist/aws-sdk.js:142:9

There are source code below link.

https://github.com/bisque33/my-custom-dictionary

and server side is a AWS Lambda Function.

var aws = require('aws-sdk');
aws.config.region = 'us-east-1';
var cognitoidentity = new aws.CognitoIdentity();
var identityPoolId = 'us-east-1:0dccff0d-5fd7-4d14-b38f-d27204feaecc';

console.log('Loading function');

exports.handler = function(event, context) {
    console.log('token: %s', event.token);

    var params = {
        IdentityPoolId: identityPoolId,
        Logins: {
            'oauth.io': event.token
        }
    };
    cognitoidentity.getOpenIdTokenForDeveloperIdentity(params,function(err,data){
        if(err){
            console.log(err);
            context.fail('Something went wrong');
        }else{
            context.succeed(data);
        }
    });
};

This program is Google-Chrome-Extension.

  • AWS Lambda Function returns token by getOpenIdTokenForDeveloperIdentity.
  • app/scripts/popup.js calls Lambda Function and set cookies.
  • app/scripts/background.js calls AWS.config.credentials.get, and returns error.

Am I using it wrong?


Update for Additional Information

Thank you for the additional information.

Error appears on 104 line on background.js

AWS.config.credentials.get(function(){

and 115 line on background.js

      dataset.synchronize(

And, My explaination was not enough. Facebook authentication needs the domain(ex. http :// example.com). However, Google-Chrome-Ext does not have domain. It has a domain 'chrome-extension://xxxxxxxxxxxxxxxxxxxx'. Then, I use https://oauth.io. It proxies any authentication and accepts chrome-extension domain.

Popup.js does Facebook authentication through oauth.io sdk. It gets a facebook token, and gives to getOpenIdTokenForDeveloperIdentity. I think facebook token.substr(0,14) is unique. But, If it is wrong, I use another unique identifier(ex. email-address.)


Sorry, I was wrong. AWS.config.credentials.get gives an Error:

Error: Invalid login token.

And, dataset.synchronize shows this Error:

Error: Missing required key 'IdentityId' in params
like image 608
bisque Avatar asked Aug 12 '15 23:08

bisque


People also ask

How do you authenticate with Cognito?

Go to AWS Cognito service and click “Manage Identity Pools”. 2. Enter “Identity pool name”, expand the “Authentication providers” section and select “Cognito” tab. This is where the Cognito authentication provider will be registered with the Identity pool.

How do I use AWS Cognito in node JS?

First login to your aws account and go to cognito section. If you don't have an aws account yet, create a free account which will be free for an year. Then go to Cognito section and then create a user pool. Give a name for the pool.


1 Answers

The first approach you have, using CognitoIdentityCredentials, is most likely the best approach for you to take. I can't spot exactly what's causing the error for you but lets try a couple things:

  1. When using Developer Authenticated Identities, you do need to specify the IdentityId when initializing CognitoIdentityCredentials. You need to get the IdentityId value from the call to GetOpenIdTokenForDeveloperIdentity. However, you shouldn't need to preserve the IdentityId value in a cookie as CognitoIdentityCredentials will cache the id by default in the browser's local storage.
  2. As for your Logins map: It looks like you're trying to use Developer Authenticated Identities. With the JavaScript SDK, use the key 'cognito-identity.amazonaws.com' and make sure the value is the token returned from your backend's call to getOpenIdTokenForDeveloperIdentity.

If you continue to have problem using the CognitoIdentityCredentials approach, please reply here with some more info such as the exact method/code you're calling when you receive the error message, and the traced output (i.e. with console.log('%o',..)) of the params input just before your call to the CognitoIdentityCredentials constructor.


Update Based on Additional Information Provided

I still need to know exactly which line of code you receive the error on, but based on the information provided I think I can still help...

Based on what I see in background.js, it looks like you're trying to initialize CognitoIdentityCredentials using a Developer Authenticated Identities provider. This is where I'm guessing that you're receiving the error.

However, in Popup.js, it looks like you're trying to authenticate the user with Facebook. If you're authenticating your users with Facebook, you should just pass the facebook access token into your Logins map when using Cognito. Just use graph.facebook.com as the key in the Logins map and the access token from Facebook. More detail on how to do this is in the Facebook Integration topic of the Amazon Cognito developer guide.

Facebook vs Developer Authenticated Identities

We can get Developer Authenticated Identities to work for you, but in this case, it doesn't look like the right solution for you since you're not actually doing any additional authentication on the identity in your Lambda function and the unique user identifier that you're passing into the getOpenIdTokenForDeveloperIdentity operation appears to be the facebook token, which is not good by the way since the token itself will change between user sessions even for the same user. Usually a good unique identifier is an email address or a user id used by an internal system.

Facebook Login & Redirects

Since you're ultimately trying to use Facebook for login and Amazon Cognito has built-in integration for Facebook, the best thing for you to do is get an access token from Facebook and pass in the Facebook token to Cognito's login map directly. I'm not sure if this will work with Auth.io or not (I'm just not familiar with it), but as long as Auth.io gives your JavaScript code a bonefide facebook token and you add the same Facebook App ID to both Auth.io and Amazon Cognito's Console, it should work. However, you mentioned you want to use Auth.io to avoid Facebook doing a redirect to a landing page. I could be mistaken, but I'm pretty sure if you're using Facebook's JavaScript SDK you won't need a redirect page. You should only need the redirect page if you're doing Facebook's Manually Build a Login Flow.

like image 200
Scott Willeke Avatar answered Sep 20 '22 21:09

Scott Willeke