Amazon-cognito-identity-js: How to access AWS_IAM protected API endpoint?

Created on 28 Apr 2016  路  5Comments  路  Source: amazon-archives/amazon-cognito-identity-js

Hi
I got all examples working now, but cannot figure out how to access an API Gateway Endpoint that is protected with AWS_IAM authorisation.

Is that even possible?

And in case it is possible, is there also a way to access with the unauthorized role?

This is all a bit confusing and I can't find a good documentation with typical use cases and flows for UserPools and API access.

Most helpful comment

OK, thanks to StackOverflow here is the missing piece of the puzzle.

For the Cognito Identity to be able to make calls to an AWS_IAM protected API Gateway Endpoint the IAM Role for the Cognito Identity or the complete Cognito Identity Pool needs to grant access to the API Gateway Endpoints like this:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"           
      ],
      "Resource": [
        "arn:aws:execute-api:us-east-1:<account>:<rest-api>/*/POST/myendpoint"
      ]
    }
  ]
}

All 5 comments

Hi Bernd,

I believe the following forum post might have more information about what you are trying to achieve:

https://forums.aws.amazon.com/thread.jspa?threadID=230067&tstart=0

Ionut.

Thanks @itrestian . That post gives a good overview.

But I am still confused about how UserPools and Cognito Identities actually work together (client side JS implementation).

Here is the scenario:

  1. Somebody comes to my page - he is then given a new unauthorized cognito identity.
  2. Even though he is unauthorized, he should still be able to get data from some API Gateway Endpoints that are protected with AWS_IAM.
  3. Now he decides to sign up to a UserPool.
  4. Sign up and confirmation succeeds.
  5. Now he signs in successfully to the UserPool.

var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData); cognitoUser.authenticateUser(authenticationDetails, { onSuccess: function onSuccess(result) { console.log('access token + ' + result.getAccessToken().getJwtToken());

That brings back an access token.

  • I assume this is a Cognito UserPools Token rather than a Cognito Identity Pools Token ?
  • And what about the unauthorized cognito identity he was using before he signed in ?

Do you have an code example on how to turn this returned token from the UserPools sign in into something that can be used to make calls to an API Gateway Endpoint that is protected with AWS_IAM (and might link to the unauthorized cognito id he used before) ?

  1. Now he closes the browser and comes back sometime later (minutes later).
    He has signed in previously before he closed the browser, but I can't figure out how to get his identity and access credentials now that he is back to my site without forcing him to sign in again !?

Hope you can help me with that. Once I got that working I'd like to put it all together in a blog, since it would most likely help a lot of people to get started much faster with Cognito User Pools.

Thanks

Hi Bernd,

Just to address some of the questions.

The access token is used only to access functionality within the User Pools feature. The id Token that is returned can be used similarly to this https://github.com/aws/amazon-cognito-identity-js/issues/7

Also if he closes the browser, the tokens can be retrieved from local storage using Use case 15 in the examples to get a session.

Ionut.

@itrestian Thank you. I am almost there, but have most likely a problem to understand how to configure IAM Roles to get that all to work.

Please see this StackOverflow question.

Thank you

I want to call an AWS API Gateway Endpoint that is protected with AWS_IAM using the generated JavaScript API SDK.

I have a Cognito UserPool and a Cognito Identity Pool. Both properly synced via ClientId.

I use this code to Sign in and get the Cognito Identity

AWS.config.region = 'us-east-1'; // Region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: 'us-east-1:XXXXXXXXXXXXXXXXXXXXXXXX' // your identity pool id here
});

AWSCognito.config.region = 'us-east-1';
AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: 'us-east-1:XXXXXXXXXXXXXXXXXXXXXXXX' // your identity pool id here
});

var poolData = {
  UserPoolId: 'us-east-1_XXXXXXXX',
  ClientId: 'XXXXXXXXXXXXXXXXXXXXXXXX'
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);


var authenticationData = {
  Username: 'user',
  Password: '12345678',
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var userData = {
  Username: 'user',
  Pool: userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
  onSuccess: function (result) {
  console.log('access token + ' + result.getAccessToken().getJwtToken());

  AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: 'us-east-1:XXXXXXXXXXXXXXXXXXXX',
    IdentityId: AWS.config.credentials.identityId,
    Logins: {
      'cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXX': result.idToken.jwtToken
    }
  });

  AWS.config.credentials.get(function (err) {
    // now I'm using authenticated credentials
    if(err)
    {
      console.log('error in autheticatig AWS'+err);
    }
    else
    {
      console.log(AWS.config.credentials.identityId);

    }
  });
  },

  onFailure: function (err) {
    alert(err);
  }

});

All this succeeds and I have an authorized Cognito Identity now.

Now I try to call the API Gateway Endpoint to execute the Lambda Function it points to.

  var apigClient = apigClientFactory.newClient({
    accessKey: AWS.config.credentials.accessKeyId, //'ACCESS_KEY',
    secretKey: AWS.config.credentials.secretAccessKey, //'SECRET_KEY',
    sessionToken: AWS.config.credentials.sessionToken, // 'SESSION_TOKEN', //OPTIONAL: If you are using temporary credentials you must include the session token
    region: 'us-east-1' // OPTIONAL: The region where the API is deployed, by default this parameter is set to us-east-1
  });

  var params = {
    // This is where any modeled request parameters should be added.
    // The key is the parameter name, as it is defined in the API in API Gateway.
  };

  var body = {
    // This is where you define the body of the request,
    query: '{person {firstName lastName}}'
  };

  var additionalParams = {
    // If there are any unmodeled query parameters or headers that must be
    //   sent with the request, add them here.
    headers: {},
    queryParams: {}
  };

  apigClient.graphqlPost(params, body, additionalParams)
    .then(function (result) {
      // Add success callback code here.
      console.log(result);
    }).catch(function (result) {
    // Add error callback code here.
    console.log(result);
  });

But unfortunately this fails. The OPTIONS request succeeds with 200 but the POST then fails with 403.

I am pretty sure that there is no CORS problem here.

I am pretty sure the problem has to do with IAM Roles and AWS Resource Configurations.

My question is basically, can you please provide me with all the necessary AWS Resource Configurations and IAM Roles that are necessary for this to work please?

Resources I have are

  • API Gateway - with deployed API Endpoints
  • Lambda Function - called by the Endpoint
  • Cognito User Pool - with App synced to the Identity Pool
  • Cognito Identity Pool - with Authorized and Unauthorized Role mapped to it.
  • IAM Roles - for the Lambda Function and the Authorized and Unauthorized Role of the Cognito Identity Pool.

But I don't know how these Resources need to be configured properly to get this to work.

Thank you

OK, thanks to StackOverflow here is the missing piece of the puzzle.

For the Cognito Identity to be able to make calls to an AWS_IAM protected API Gateway Endpoint the IAM Role for the Cognito Identity or the complete Cognito Identity Pool needs to grant access to the API Gateway Endpoints like this:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"           
      ],
      "Resource": [
        "arn:aws:execute-api:us-east-1:<account>:<rest-api>/*/POST/myendpoint"
      ]
    }
  ]
}
Was this page helpful?
0 / 5 - 0 ratings