AWS SAM API with Cognito User Pools authorizer

Viewed 7205

How can I create an API with AWS SAM that does authorization using Cognito User Pools authorizer?

Theres AWS::ApiGateway::Authorizer. But ...

{
  "Type" : "AWS::ApiGateway::Authorizer",
  "Properties" : {
    "AuthorizerCredentials" : String,
    "AuthorizerResultTtlInSeconds" : Integer,
    "AuthorizerUri" : String,
    "IdentitySource" : String,
    "IdentityValidationExpression" : String,
    "Name" : String,
    "ProviderARNs" : [ String, ... ],
    "RestApiId" : String,
    "Type" : String
  }
}

it looks like RestApiId refers to the API which uses this authorizer? But with AWS SAM, my APIs are defined like

Resources:
  Ec2Index:
    Type: AWS::Serverless::Function
    Properties:
      Handler: ec2/index.handler
      Runtime: nodejs6.10
      CodeUri: ./src
      FunctionName: 'ApiEc2IndexHandler'
      Description: 'List EC2 resources'
      Timeout: 30
      Role: 'arn:aws:iam::598545985414:role/awsmanagement-lambda-management'
      Events:
        Ec2Index:
          Type: Api
          Properties:
            Path: /ec2
            Method: get

I dont get how do I associate them together?

5 Answers

You can now reference the implicitly created api gateway with 'ServerlessRestApi'. So in your SAM template add this piece of regular Cloudformation and everything will work fine

ApiCognitoAuthorizer:          
  Type: AWS::ApiGateway::Authorizer
  Properties:
    IdentitySource: 'method.request.header.Authorization'
    Name: ApiCognitoAuthorizer
    ProviderARNs:
      - 'arn:aws:cognito-idp:{region}:{userpoolIdentifier}'
    RestApiId: !Ref ServerlessRestApi
    Type: COGNITO_USER_POOLS

Since AWS SAM v1.8.0, you can do it using the following syntax. You can refer to this article for more information.

In short, define a Cognito Authorizer for your API using API Authorizer Object. Then, set the Auth of your lambda function to refers to this API.

MyApi:
  Type: AWS::Serverless::Api
  Properties:
    StageName: Prod
    Auth:
      DefaultAuthorizer: MyCognitoAuth # OPTIONAL
      Authorizers:
        MyCognitoAuth:
          # Can also accept an array
          UserPoolArn: !GetAtt MyCognitoUserPool.Arn 
          Identity: # OPTIONAL
            # OPTIONAL; Default: 'Authorization'
            Header: MyAuthorizationHeader 
            # OPTIONAL
            ValidationExpression: myAuthValidationExp
MyFunction:
  Type: AWS::Serverless::Function
  Properties:
    FunctionName: MyFunction
    ...
    Events:
      Post:
        Type: Api
        Properties:
          Path: /compute
          Method: POST
          RestApiId: !Ref MyApi
          Auth:
            Authorizer: MyCognitoAuth

As @simones mentioned, the following will create the Cognito User Pool authorizer (CF template).

ApiCognitoAuthorizer:          
 Type: AWS::ApiGateway::Authorizer
 Properties:
  IdentitySource: 'method.request.header.Authorization'
  Name: ApiCognitoAuthorizer
  ProviderARNs:
   - 'arn:aws:cognito-idp:{region}:{userpoolIdentifier}'
  RestApiId: !Ref ServerlessRestApi
  Type: COGNITO_USER_POOLS

To attach it to a resource method, the following works (in Swagger file):

 securityDefinitions:
  ApiCognitoAuthorizer:
    type: apiKey
    name: Authorization
    in: header
    x-amazon-apigateway-authtype: cognito_user_pools
    x-amazon-apigateway-authorizer:
      type: cognito_user_pools
      providerARNs:
        - arn:aws:cognito-idp:{region}:{userpoolIdentifier}

Then, add to specific methods (in Swagger file):

    security:
    - ApiCognitoAuthorizer: []

You can add your Cognito User Authorizer directly to your SAM AWS::Serverless::Api.

  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Cors: "'*'"
      Auth:
        DefaultAuthorizer: MyCognitoAuthorizer
        Authorizers:
          MyCognitoAuthorizer:
            UserPoolArn: 'arn:aws:cognito-.....' # YOUR COGNITO USER POOL ARN

and on your AWS::Serverless::Function you can add a function authorizer if you have not set the default one. Or you can deactivate it using Authorizer: 'NONE'.

Auth:
  Authorizer: MyCognitoAuthorizer

see also documentation.

Related