Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call AWS API Gateway Endpoint with Cognito Id (+configuration)?

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

like image 746
Christine Avatar asked Apr 29 '16 04:04

Christine


2 Answers

What access permissions does the role of the Cognito Identity have? Make sure it has access to perform execute-api:Invoke on your API.

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

You can get the exact resource ARN from the method settings page in the web console.

like image 124
Lorenzo de Lara Avatar answered Oct 26 '22 19:10

Lorenzo de Lara


Even after following everything I was getting the same error. And the reason was I missed the "sessionToken" while initialising the apigClient.

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 });

//OPTIONAL: If you are using temporary credentials you must include the session token -- is not really optional

like image 20
Partha Avatar answered Oct 26 '22 17:10

Partha