AWS: Restrict Cognito Authorized User to specific Lambda Functions

情到浓时终转凉″ 提交于 2019-12-02 02:54:34

So I've found a solution to my problem. Here is the summary of my experiences:

  • Cognito Authorizer is more like a yes/no authorizer (authenticated or not; user groups are not evaluated)
  • Therefore I went with AWS IAM Authorizer in the API Gateway, which will evaluate the user group roles
  • Instead of a JWT the AWS signature v4 authorization has to be passed (there is a plugin for postman and several packages on npm)
  • Since I am using an API Gateway I had to change the role policy resources to execute-api:Invoke

In detail:

UserRole:

{
  "Version": "2012-10-17",
  "Statement": [
    "Action": [
      "lambda:InvokeFunction",
      "lambda:InvokeAsync"
    ],
   "Resource": [
     "arn:aws:execute-api:region:accountid:api-id/stage/GET/items
    ],
    "Effect": "Allow"
  ]
}

AdminRole:

{
  "Version": "2012-10-17",
  "Statement": [
    "Action": [
      "lambda:InvokeFunction",
      "lambda:InvokeAsync"
    ],
   "Resource": [
     "arn:aws:execute-api:region:accountid:api-id/stage/GET/items
     "arn:aws:execute-api:region:accountid:api-id/stage/*/users
    ],
    "Effect": "Allow"
  ]
}

Instead of passing the ID Token into the Authorization header, I had to use Postman AWS Signature, which requires at least an AccessKey and a SecretKey. Those two can be retrieved when I sign in my user using the aws-sdk. aws-sdk-js with TypeScript as example:

import { CognitoUserPool, CognitoUser, AuthenticationDetails } from 'amazon-cognito-identity-js';

const userPool = new CognitoUserPool({
  UserPoolId: 'my pool id',
  ClientId: 'my client id'
});

function signIn(username: string, password: string) {
  const authData = {
    Username: username,
    Password: password,
  };

  const authDetails = new AuthenticationDetails(authData);
  const userData = {
    Username: username,
    Pool: userPool,
  };

  const cognitoUser = new CognitoUser(userData);
  cognitoUser.authenticateUser(authDetails, {
    onSuccess: (result) => {
      const cognitoIdpKey = `cognito-idp.${region}.amazonaws.com/${userPool.getUserPoolId()}`;

      const credentials = new AWS.CognitoIdentityCredentials({
        IdentityPoolId: 'identity pool id,
        Logins: {
          [cognitoIdpKey]: result.getIdToken().getJwtToken(),
        }
      });
      AWS.config.update({
        credentials,
      });

      credentials.refreshPromise()
        .then(() => {
          console.log('Success refresh. Required data:', (credentials as any).data.Credentials);
        })
        .catch(err => console.error('credentials refresh', err));
    }
  });
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!