当我尝试使用 AWS Cognito 登录时,我收到关于我的自定义 Lambda 触发器的 AccessDeniedException

When I try to login using AWS Cognito I get an AccessDeniedException about my custom Lambda trigger

我正在调用 adminInitiateAuth 并为我自己的 lambda 取回一个奇怪的 AccessDeniedException。

这是我调用的代码:

      var params = {
        AuthFlow: "ADMIN_NO_SRP_AUTH",
        ClientId: "@cognito_client_id@",
        UserPoolId: "@cognito_pool_id@",
        AuthParameters: {
          USERNAME : username,
          PASSWORD : tempPassword
        },
      };
      cognitoIdentityServiceProvider.adminInitiateAuth(params, function(error, data) {
        if (error) {
          console.log("ERROR! Login failed: " + JSON.stringify(error), error.stack);
        } else {
          console.log("Login sent back: " + JSON.stringify(data));
        }
      });

我收到的错误消息是:

ERROR! Login failed: {"message":"arn:aws:lambda:us-east-1:201473124518:function:main-devryan-users_onCognitoLogin failed with error AccessDeniedException.","code":"UnexpectedLambdaException","time":"2017-02-25T18:54:15.109Z","requestId":"ce42833f-fb8b-11e6-929b-2f78b63faa12","statusCode":400,"retryable":false,"retryDelay":1.0853444458916783} UnexpectedLambdaException: arn:aws:lambda:us-east-1:201473124518:function:main-devryan-users_onCognitoLogin failed with error AccessDeniedException.

有人知道我为什么会收到此错误吗?

发生这种情况是因为我重新创建了 API 网关和 Lambdas(使用无服务器),事实证明 Cognito 控制台在通过控制台添加为触发器时偷偷添加了联系给定 Lambda 函数的权限。


要在您的 CloudFormation / serverless.yml 文件中修复此问题:

resources:
  Resources:
    OnCognitoSignupPermission:
      Type: 'AWS::Lambda::Permission'
      Properties:
        Action: "lambda:InvokeFunction"
        FunctionName:
          Fn::GetAtt: [ "UsersUnderscoreonCognitoSignupLambdaFunction", "Arn"]
        Principal: "cognito-idp.amazonaws.com"
        SourceArn:
          Fn::Join: [ "", [ "arn:aws:cognito-idp", ":", Ref: "AWS::Region", ":", Ref: "AWS::AccountId", ":", "userpool/", "@cognito_pool_id@" ] ]

要在 AWS 控制台中修复此问题

  • 转到 Cognito 控制台
  • 选择您的用户池
  • 转到"Triggers"
  • 删除您的自定义触发器(将其设置为 None)并单击 "Save"
  • 现在将其重置并再次单击 "Save"

这里 an interesting Amazon forum post 让我走上了正确的轨道。

除了我尝试通过 CloudFormation 使用我的 Cognito 用户池配置 Lambda 之外,我遇到了与您类似的问题。

在 Ryan 发布的 link 中,有人发布了一个代码示例。即 Cognito 需要适当的权限来调用 lambda 函数。

MyLambdaInvocationPermission:
  Type: AWS::Lambda::Permission
  Properties:
    Action: lambda:InvokeFunction
    FunctionName: !GetAtt MyLambdaFunctionName.Arn
    Principal: cognito-idp.amazonaws.com
    SourceArn: !GetAtt MyCognitoUserPoolName.Arn

您可以从 lambda 角色添加权限(为 cognito 创建策略并添加到 lamda 角色)。当我陷入困境时,这解决了我的问题

创建 cloudformation 堆栈时 - 我遇到了类似

的错误
User:arn:aws::12345678:user/xyz is not authorized to perform:
cognito-idp:CreateUserPool on resource:*(Service:AWSCognitoIdentityProviderService;
Status Code: 400; Error Code: AccessDeniedException;Request ID: xxxxx)

解决方法:

  • 继续进入处于回滚状态的堆栈 -> 检查事件并可以看到,(创建失败)一些我无权访问的角色,
  • 所以,我检查了分配给我的 IAM 策略 - 我没有访问权限。
  • 我创建了一个新策略,并通过从 AWS 导入它作为内联策略分配给自己。

    aws-cognito-idp

    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Cognito-IDP",
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction",
                "cognito-idp:*"
            ],
            "Resource": "*"
        }
    ]
}

note: you can restrict the access on resource and cognito-idp user.

有了这个 - 我能够成功地为模块创建和部署 cloudformation 堆栈。

对于最终出现在这里的人,试图通过 terraform 添加认知触发器,您需要做的就是添加一个 aws_lambda_permission 资源:

resource "aws_lambda_permission" "allow_execution_from_user_pool" {
  statement_id = "AllowExecutionFromUserPool"
  action = "lambda:InvokeFunction"
  function_name = aws_lambda_function.<lambda>.function_name
  principal = "cognito-idp.amazonaws.com"
  source_arn = aws_cognito_user_pool.<pool>.arn
}

在这个伟大的 post 中发现:https://www.integralist.co.uk/posts/cognito/