amazon-web-servicesamazon-cognitoaws-serverlessaws-sam

Adding identity pool auth to AWS Serverless application


We are migrating our server-side operations from separate Lambda functions and an API managed in API Gateway, to a single SAM deployment.

Users are registered anonymously in an existing Cognito Identity Pool and receive a token when they log in, which is used to sign all subsequent requests.

In AWS gateway, we set "Method Request" => "Authorization" to "AWS IAM" for each endpoint, which works as required:

Screengrab of AWS API Gateway

I am trying to replicate this setup in my SAM template, but cannot get it to work and nearly all of the documentation relates to user pools, rather than identity pools.

Based on this, it looks like all I should need to do is add DefaultAuthorizer: AWS_IAM to my SAM template, but this rejects all requests with a 403 error.

So far I have also tried:

Resources:
  ClientContentApi:
    Type: AWS::Serverless::Api
    Properties:
      Auth:
        DefaultAuthorizer: AWS_IAM
  ClientContentAuthorizer:
    Type: AWS::ApiGateway::Authorizer
    Properties:
      Type: TOKEN
      Name: DefaultAuthorizer
      RestApiId: !Ref ClientContentApi
      IdentitySource: "method.request.header.Authorization,method.request.header.X-Amz-Date,method.request.header.X-Amz-Security-Token"
      AuthorizerUri: "<The ARN of my identity pool>"

When I try to deploy this, I get the following error:

Invalid Authorizer URI: . Authorizer URI should be a valid API Gateway ARN that represents a Lambda function invocation.

This seems to suggest I need a separate Lambda function to authorise requests, but this wasn't necessary previously and I'd like to avoid any unnecessary setup.

What am I doing wrong and how can I replicate my API gateway auth setup in my SAM template?


Solution

  • I eventually got this working with the following setup:

    The only extra information I added to my SAM template was:

    Auth:
      DefaultAuthorizer: AWS_IAM
      AddDefaultAuthorizerToCorsPreflight: false
      InvokeRole: NONE
    

    It's also necessary to add permissions to invoke your API to the unauth IAM role for your identity pool. You should have an IAM role with the name Cognito_<your-identity-pool-name>Unauth_Role, e.g.

    { 
        "Version": "2012-10-17", 
        "Statement": [ 
            { 
                "Effect": "Allow", 
                "Action": [ 
                    "execute-api:Invoke" 
                ], 
                "Resource": [ 
                    "arn:aws:execute-api:<region>:<account_id>:<api_id>/*" 
                ] 
            } 
        ] 
    }
    

    More info here.