4
votes

I am starting with serverless on AWS, and I am using AWS Cognito for user authentication and authorization. For what I saw on the documentation and examples out there, you can make groups for allowing certain users to be able to use an Api Gateway endpoint, attaching a role and a policy to that group. I try this, and then made a simple client and try with two different users, and both are able to get a 200 status code instead of one of them getting that it is unauthorize. For creating the role I went to IAM, create role, role for identity provider access, grant access to web identity providers, and then I choose Amazon Cognito and choose my user pool of Cognito. Trust Relationship:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "cognito-identity.amazonaws.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "us-east-1_8TAUVKbGP"
        }
      }
    }
  ]
} 

Policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "execute-api:Invoke"
            ],
            "Resource": [
                "my-arn-resourse-from-api-gateway"
            ]
        }
    ]
}

Then I assigned this role to my admin group and add a user to that group, which should allow access to that Api Gateway resource by attaching that policy to the user when it signs in. But when I try with a user not in that group it still works. By the way, on my Api Gateway resource in the request I put for authorization my cognito pool.

Thanks very much!

3

3 Answers

5
votes

Ok finally I got it to work perfectly! The problem was in my IAM Role, in the trust relationship document

"Condition": {
        "StringEquals": {
          "cognito-identity.amazonaws.com:aud": "identity_pool_id"
        },

In that part instead of using my Identity Pool Id, I was using my User Pool Id. Once that was fixed, I got the credentials back, and tried in Postman using those credentials and it worked perfectly. Then I change the same user to another role, and access was denied as planned! The most importante part for using role authorization on an easy way, is as agent420 said to use AWS_IAM method for securing the api, then the rest is handle by aws.

0
votes

You would need to use the AWS_IAM method instead for your use case. Also, in this case all your API requests would need to be SIGv4 signed. You can use Postman (chrome extension) for testing. It includes an option for AWS credentials.

0
votes

I try what you said! I think I am in the right way but AWS.config.credentials is returning sessionToken, and accessKeyId both with null. This is the code I am using:

let poolData = {
      UserPoolId : 'my_user_pool_id',
      ClientId : 'my_app_client_id'
    };

    let authenticationData = {
      Username : 'username',
      Password : 'password',
    };

    let userPool = new CognitoUserPool(poolData);

    let userData = {
      Username : 'username',
      Pool : userPool
    };

    let authenticationDetails = new AuthenticationDetails(authenticationData);

    let cognitoUser = new CognitoUser(userData);

    cognitoUser.authenticateUser(authenticationDetails, {
      onSuccess: (result) => {
        console.log(result);

        AWS.config.region = 'my_region';

        AWS.config.credentials = new AWS.CognitoIdentityCredentials({
          IdentityPoolId : 'my_identity_pool_id',
          Logins : {
            'cognito-idp.my_region.amazonaws.com/my_user_pool_id' : result.getIdToken().getJwtToken()
          }
        });

        console.log(AWS.config.credentials);
      },
      onFailure: (error) => {

      }
    });

The result from the authenticateUser returns the expected tokens. The problem I think is when retrieving the CognitoIdentityCredentials.

Thanks very much!