Cognito user pool authorizer With Serverless Framework - amazon-web-services

I need to authorize my API end point using aws cognito userpool. I can do it manually, but I need to automate the authorization part with the serverless framework.
Does the Serverless framework have support for aws cognito?
If so, how do we setup an aws-userpool with serverless?

Yes . Serverless (v1.5) support to Cognito user pool authorizer.
If you use previous version of serverless you have to update v1.5 or later.
For the user-pool authorization of api end point you have to specify pool arn.
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
integration: lambda
authorizer:
name: authorizer
arn: arn:aws:cognito-idp:us-east-1:123456789:userpool/us-east-1_XXXXXX
More details read this article.

If you want to set the authorizer to a Cognito User Pool you have declared in your resources you must use CloudFormation to create the authorizer as well.
functions:
functionName:
# ...
events:
- http:
# ...
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: ApiGatewayAuthorizer
resources:
Resources:
ApiGatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: CognitoUserPool
Type: COGNITO_USER_POOLS
IdentitySource: method.request.header.Authorization
RestApiId:
Ref: ApiGatewayRestApi
ProviderARNs:
- Fn::GetAtt:
- UserPool
- Arn
UserPool:
Type: AWS::Cognito::UserPool

Serverless 1.35.1
In case someone stumbles across this how I did. Here is my working solution.
Wherever you create the user pool, you can go ahead and add ApiGatewayAuthorizer
# create a user pool as normal
CognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
# Generate an app client name based on the stage
ClientName: ${self:custom.stage}-user-pool-client
UserPoolId:
Ref: CognitoUserPool
ExplicitAuthFlows:
- ADMIN_NO_SRP_AUTH
GenerateSecret: true
# then add an authorizer you can reference later
ApiGatewayAuthorizer:
DependsOn:
# this is pre-defined by serverless
- ApiGatewayRestApi
Type: AWS::ApiGateway::Authorizer
Properties:
Name: cognito_auth
# apparently ApiGatewayRestApi is a global string
RestApiId: { "Ref" : "ApiGatewayRestApi" }
IdentitySource: method.request.header.Authorization
Type: COGNITO_USER_POOLS
ProviderARNs:
- Fn::GetAtt: [CognitoUserPool, Arn]
Then when you define your functions
graphql:
handler: src/app.graphqlHandler
events:
- http:
path: /
method: post
cors: true
integration: lambda
# add this and just reference the authorizer
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: ApiGatewayAuthorizer

Related

Serverless Framework How to Get Access, Id and Refresh Tokens from AWS Cognito

I am trying to secure my serverless NodeJS apis using AWS Cognito User Pools.
Below is a sample of my serverless framework configuration:
service: hello-world
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs14.x
environment:
user_pool_id: { Ref: UserPool }
client_id: { Ref: UserClient }
iam:
role:
statements:
- Effect: Allow
Action:
- cognito-idp:AdminInitiateAuth
- cognito-idp:AdminCreateUser
- cognito-idp:AdminSetUserPassword
Resource: "*"
functions:
loginUser:
handler: ./auth/login.handler
events:
- http:
path: auth/login
method: post
cors: true
signupUser:
handler: ./auth/signup.handler
events:
- http:
path: auth/signup
method: post
cors: true
list:
handler: ./users/users.handler
events:
- http:
path: users/list
method: get
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: ApiGatewayAuthorizer
resources:
Resources:
ApiGatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: CognitoUserPool
Type: COGNITO_USER_POOLS
IdentitySource: method.request.header.Authorization
RestApiId:
Ref: ApiGatewayRestApi
ProviderARNs:
- Fn::GetAtt:
- UserPool
- Arn
UserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: serverless-auth-pool
Schema:
- Name: email
Required: true
Mutable: true
Policies:
PasswordPolicy:
MinimumLength: 6
AutoVerifiedAttributes: ["email"]
UserClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: user-pool-ui
GenerateSecret: false
UserPoolId: { Ref: UserPool }
AccessTokenValidity: 1
IdTokenValidity: 1
ExplicitAuthFlows:
- "ADMIN_NO_SRP_AUTH"
I can successfully can call the signup and login endpoints to get a token and then use this token as an Authorization header to call my /users/list endpoint to get a list of users.
My problem is that I was expecting the login endpoint to return 3 tokens - an id token, an access token and a refresh token.
The login endpoint currently only returns one token that has a claim of:
"token_use": "id"
If I pass this token to the /users/list api then it is successfully validated, but I thought that the api would need the access token instead of the id token for authentication.
Does anyone know if my assumption is correct and how to fix the issue or have I misunderstood how the auth flow works ?

Cognito User Pool Authorizer defined in openapi without hardcoded values

I have a API Gateway Rest Api resource defined with this template:
AWSTemplateFormatVersion: '2010-09-09'
Description: "Api gateway"
Resources:
ApiGateway:
Type: "AWS::ApiGateway::RestApi"
Properties:
BodyS3Location: "./openapi-spec.yaml"
And the contents of openapi-spec.yaml (based on this example) being:
openapi: "3.0.2"
info:
title: SampleApi
paths:
/test:
get:
summary: Test
responses:
"200":
description: Ok
security:
- UserPool: [ ]
x-amazon-apigateway-integration:
# ....
components:
securitySchemes:
UserPool:
type: apiKey
name: Authorization
in: header
x-amazon-apigateway-authtype: cognito_user_pools
x-amazon-apigateway-authorizer:
type: cognito_user_pools
providerARNs:
### THIS VALUE ###
- "arn:aws:cognito-idp:eu-west-1:123456789012:userpool/eu-west-1_abcd12345"
I'd like to be able to deploy this template in multiple environments/account and having this hardcoded providerARN is limiting that. So my questions are:
How can values for the providerARNs field be passed in dynamically?
If that can't be done, then are there any workarounds to this so that I don't have to hardcode the providerArns here?
Note: Already tried to use stage variables and they don't seem to work here.
If you don't have an existing Cognito user pool then you would have to define one using AWS::Cognito::UserPool in CloudFormation, then you can simply reference the arn of this user pool using !GetAtt.
But if you have an existing Cognito user pool then you can also import it to a stack using CloudFormation following these steps.
Here's an example:
template.yaml
Resources:
ApiGateway:
Type: "AWS::ApiGateway::RestApi"
Properties:
BodyS3Location: "./openapi-spec.yaml"
CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
# ....
openapi-spec.yaml
openapi: "3.0.2"
# ....
components:
securitySchemes:
UserPool:
type: apiKey
name: Authorization
in: header
x-amazon-apigateway-authtype: cognito_user_pools
x-amazon-apigateway-authorizer:
type: cognito_user_pools
providerARNs:
- !GetAtt CognitoUserPool.Arn

How to create a resourse of API-Gatway authorizer, in serverless

I using a cognito authorizer im my API, and using serverless to configure the api. For add a autorizer to a funcitions, i found this code (How to configure my Serverless YML to use my API Gateway Authorizer?):
teste:
handler: handler.teste
memorySize: 128
events:
- http:
path: teste
method: get
authorizer:
name: api-authorizer
arn: arn:aws:cognito-idp:XXXXXXXXX:XXXXXXXXXX:userpool/XXXXXXX_XXXXXXX
type: token
this code works very nice, but i need repeat a same authorizer in multiple functions, and using this code, for each function a new authorizer is create.... this is a waste of resourse and generete a mess in AWS console
For resolve this problem i try this:
teste:
handler: handler.teste
memorySize: 128
events:
- http:
path: teste
method: get
authorizer: myAuthorizer
resources:
Resources:
myAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: "testing"
arn: arn:aws:cognito-idp:XXXXXXXXX:XXXXXXXXXX:userpool/XXXXXXX_XXXXXXX
authorizerId:
Ref: api-authorizer
But don't have success, and i didn't found documentations or guides for this.
In my opinion, it's not big of a deal to have the authorizer section repeated. In my case, it makes sense to have it repeated since we are using scopes.
listItems:
handler: handler.listItems
events:
- http:
method: get
path: /list-items
authorizer:
arn: ${self:custom.vars.${self:custom.vars.stage}.userPoolArn}
scopes:
- transactions/read
writeItem:
handler: handler.writeItem
events:
- http:
method: post
path: /write-item
authorizer:
arn: ${self:custom.vars.${self:custom.vars.stage}.userPoolArn}
scopes:
- transactions/write
But if you would like to share an authorizer it's here.
resources:
Resources:
ApiGatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
AuthorizerResultTtlInSeconds: 300
IdentitySource: method.request.header.Authorization
Name: Cognito
RestApiId:
Ref: YourApiGatewayName
Type: COGNITO_USER_POOLS
ProviderARNs:
- arn:aws:cognito-idp:${self:provider.region}:xxxxxx:userpool/abcdef
functions:
deleteUser:
...
events:
- http:
path: /users/{userId}
...
# Provide both type and authorizerId
type: COGNITO_USER_POOLS # TOKEN or REQUEST or COGNITO_USER_POOLS, same as AWS Cloudformation documentation
authorizerId:
Ref: ApiGatewayAuthorizer # or hard-code Authorizer ID
Reference:
https://serverless.com/framework/docs/providers/aws/events/apigateway/#share-authorizer
What you are looking for is a certain type of API Gateway Authorizer, a Cognito Authorizer. These are specifically for authenticating users from a Cognito User Pool.
To use a Cognito Authorizer with serverless your serverless.yml could look something like this:
teste:
handler: handler.teste
memorySize: 128
events:
- http:
path: teste
method: get
authorizer:
arn: arn:aws:cognito-idp:XXXXXXXXX:XXXXXXXXXX:userpool/XXXXXXX_XXXXXXX
You aren't required to send the authorizer name or type when using a Cogntio Authorizer. Additionally, the arn should be pointing to your Cognito User Pool, which the one in your example appears to be.
Checkout the serverless documentation topic on custom authorizers if you want any more information or examples.

Shared Lambda authorizer setup in Serverless Framework

I am trying to create a custom Lambda authorizer that will be shared between a few different services/serverless stacks. If I understand the documentation here https://serverless.com/framework/docs/providers/aws/events/apigateway/#note-while-using-authorizers-with-shared-api-gateway, that means that I need to create a shared authorizer resource in a “common resources” service/serverless stack, and then refer to that shared authorizer from my other services. First of all: Is my understanding correct?
If my understanding is correct, my next question becomes: How do I do this? The documentation doesn’t provide a clear example for lambda authorizers, so here’s how I tried to customize it:
functions:
authorizerFunc:
handler: authorizer/authorizer.handler
runtime: nodejs8.10
resources:
Resources:
authorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
AuthorizerResultTtlInSeconds: 0
Name: Authorizer
Type: REQUEST
AuthorizerUri: ???
RestApiId:
Fn::ImportValue: myRestApiId
I don’t understand what the syntax for AuthorizerUri is supposed to be. I’ve tried “Ref: authorizerFunc”, “Fn::GetAtt: [authorizerFunc, Arn]” etc. to no avail.
When I get the authorizerUri working, do I just add an Output for my authorizer resource, then Fn::ImportValue it from the services containing my API Lambdas?
Link to my question on the Serverless forum for posterity: https://forum.serverless.com/t/shared-lambda-authorizer/6447
EDIT: Apparently my answer is now outdated. For newer versions of serverless, see the other answers. I don't know which answer is best/most up-to-date, but if someone lets me know I'll change which answer is accepted to that one.
I eventually got it to work, so here's how I set up my autherizer's serverless.yml:
service: user-admin-authorizer
custom:
region: ${file(serverless.env.yml):${opt:stage}.REGION}
provider:
name: aws
region: ${self:custom.region}
functions:
authorizer:
handler: src/authorizer.handler
runtime: nodejs8.10
resources:
Resources:
Authorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: Authorizer
Type: REQUEST
AuthorizerUri:
Fn::Join: [ "",
[
"arn:aws:apigateway:",
"${self:custom.region}",
":lambda:path/",
"2015-03-31/functions/",
Fn::GetAtt: ["AuthorizerLambdaFunction", "Arn" ],
"/invocations"
]]
RestApiId:
Fn::ImportValue: api-gateway:${opt:stage}:rest-api-id
apiGatewayLambdaPermissions:
Type: AWS::Lambda::Permission
Properties:
FunctionName:
Fn::GetAtt: [ AuthorizerLambdaFunction, Arn]
Action: lambda:InvokeFunction
Principal:
Fn::Join: [ "",
[
"apigateway.",
Ref: AWS::URLSuffix
]]
Outputs:
AuthorizerRef:
Value:
Ref: Authorizer
Export:
Name: authorizer-ref:${opt:stage}
Things to note: Even though the authorizer function is called "authorizer", you need to capitalize the first letter and append "LambdaFunction" to its name when using it with GetAtt, so "authorizer" becomes "AuthorizerLambdaFunction" for some reason. I also had to add the lambda permission resource.
The API gateway resource also needs two outputs, its API ID and its API root resource ID. Here's how my API gateway's serverless.yml is set up:
resources:
Resources:
ApiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
Name: ApiGateway
Outputs:
ApiGatewayRestApiId:
Value:
Ref: ApiGateway
Export:
Name: api-gateway:${opt:stage}:rest-api-id
ApiGatewayRestApiRootResourceId:
Value:
Fn::GetAtt:
- ApiGateway
- RootResourceId
Export:
Name: api-gateway:${opt:stage}:root-resource-id
Now you just need to specify to your other services that they should use this API gateway (the imported values are the outputs of the API gateway):
provider:
name: aws
apiGateway:
restApiId:
Fn::ImportValue: api-gateway:${opt:stage}:rest-api-id
restApiRootResourceId:
Fn::ImportValue: api-gateway:${opt:stage}:root-resource-id
After that, the authorizer can be added to individual functions in this service like so:
authorizer:
type: CUSTOM
authorizerId:
Fn::ImportValue: authorizer-ref:${opt:stage}
I had the same issue that you describe. Or at least I think so. And I managed to get it solved by following the documentation on links you provided.
The serverless documentation states for the authorizer format to be
authorizer:
# Provide both type and authorizerId
type: COGNITO_USER_POOLS # TOKEN or COGNITO_USER_POOLS, same as AWS Cloudformation documentation
authorizerId:
Ref: ApiGatewayAuthorizer # or hard-code Authorizer ID
Per my understanding, my solution (provide below) follows the hard-coded authorizer ID approach.
In the service that has the shared authorizer, it is declared in the serverless.yml in normal fashion, i.e.
functions:
myCustomAuthorizer:
handler: path/to/authorizer.handler
name: my-shared-custom-authorizer
Then in the service that wishes to use this shared authorizer, the function in servlerless.yml is declared as
functions:
foo:
# some properties ...
events:
- http:
# ... other properties ...
authorizer:
name: authorize
arn:
Fn::Join:
- ""
- - "arn:aws:lambda"
# References to values such as region, account id, stage, etc
# Can be done with Pseudo Parameter Reference
- ":"
- "function:myCustomAuthorizer"
It was crucial to add the name property. It would not work without it, at least at the moment.
For details see
ARN naming conventions
Pseudo Parameter Reference
Fn::Join
Unfortunately I cannot say whether this approach has some limitations compared to your suggestion of defining authorizer as a resource. In fact, that might make it easier to re-use the same authorizer in multiple functions within same service.
Serverless 1.35.1
For people stumbling across this thread, here is the new way
Wherever you create the user pool, you can go ahead and add ApiGatewayAuthorizer
# create a user pool as normal
CognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
# Generate an app client name based on the stage
ClientName: ${self:custom.stage}-user-pool-client
UserPoolId:
Ref: CognitoUserPool
ExplicitAuthFlows:
- ADMIN_NO_SRP_AUTH
GenerateSecret: true
# then add an authorizer you can reference later
ApiGatewayAuthorizer:
DependsOn:
# this is pre-defined by serverless
- ApiGatewayRestApi
Type: AWS::ApiGateway::Authorizer
Properties:
Name: cognito_auth
# apparently ApiGatewayRestApi is a global string
RestApiId: { "Ref" : "ApiGatewayRestApi" }
IdentitySource: method.request.header.Authorization
Type: COGNITO_USER_POOLS
ProviderARNs:
- Fn::GetAtt: [CognitoUserPool, Arn]
Then when you define your functions
graphql:
handler: src/app.graphqlHandler
events:
- http:
path: /
method: post
cors: true
integration: lambda
# add this and just reference the authorizer
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: ApiGatewayAuthorizer
This is how I did my set up since the answer posted above didn't worked for me. May be it could be helpful for someone.
resources:
Resources:
ApiGatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
AuthorizerResultTtlInSeconds: 0
IdentitySource: method.request.header.Authorization
AuthorizerUri:
Fn::Join: ["",
[
"arn:aws:apigateway:",
"${self:custom.region}",
":lambda:path/",
"2015-03-31/functions/",
Fn::GetAtt: ["YourFunctionNameLambdaFunction", "Arn" ],
"/invocations"
]]
RestApiId:
Fn::ImportValue: ${self:custom.stage}-ApiGatewayRestApiId
Name: api-${self:custom.stage}-authorizer
Type: REQUEST
ApiGatewayAuthorizerPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName:
Fn::GetAtt: ["YourFunctionNameLambdaFunction", "Arn"]
Action: lambda:InvokeFunction
Principal:
Fn::Join: ["",["apigateway.", { Ref: "AWS::URLSuffix"}]]
Outputs:
AuthorizerRef:
Value:
Ref: ApiGatewayAuthorizer
Export:
Name: authorizer-ref:${self:custom.stage}
I hope you know how to add an API gateway and import it here like
RestApiId:
Fn::ImportValue: ${self:custom.stage}-ApiGatewayRestApiId
, since it's already specified in the accepted answer
And In my case I passed value in the event header as Authorization
type to get it in the authorizer lambda function and my type is
REQUEST
Changing to a shared custom API Gateway Lambda Authorizer was straightforward once it was working as part of the service. At that point it was just add an arn: to a deployed lambda (authorizer) and remove the "authorizer" definition from the service to a separate deployable service.
myLambdaName:
handler: handler.someNodeFunction
name: something-someNodeFunction
events:
- http:
path: /path/to/resource
method: get
cors: true
authorizer:
name: myCustomAuthorizer
# forwarding lambda proxy event stuff to the custom authorizer
IdentitySource: method.request.header.Authorization, context.path
type: request
arn: 'arn:aws:lambda:region:##:function:something-else-myCustomAuthorizer'
Then the other "service" just has some custom authorizers shared by multiple deployed microservices.
functions:
myCustomAuthorizer:
name: something-else-myCustomAuthorizer
handler: handler.myCustomAuthorizer
Side note:
If you'd want a token type authorizer, which does forward the "authorization: bearer xyzsddfsf" as a simple event:
{
"type": "TOKEN",
"methodArn": "arn:aws:execute-api:region:####:apigwIdHere/dev/GET/path/to/resource",
"authorizationToken": "Bearer ...."
}
authorizer:
arn: 'arn:aws:lambda:region:##:function:something-else-myCustomAuthorizer'

AWS SAM API with Cognito User Pools authorizer

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?
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
I'm not certain you can specify an authorizer in SAM but you can embed Swagger in SAM files which can do this. It's a new feature as of Feb. 17 [ref].
I'm definitely not an expert on Swagger or SAM but it seems like you would want something like:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Simple API Endpoint configured using Swagger specified inline and backed by a Lambda function
Resources:
Ec2Index:
Type: AWS::Serverless::Api
Properties:
StageName: <stage>
DefinitionBody:
swagger: 2.0
info:
title:
Ref: AWS::StackName
securityDefinitions:
cognitoUserPool:
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:${AWS::Region}:{AWS::AccountId}:userpool/<user_pool_id>
paths:
"/ec2":
get:
security:
- cognitoUserPool: []
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Ec2IndexLamb.Arn}/invocations
responses: {}
swagger: '2.0'
Ec2IndexLamb:
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
References:
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html#apigateway-enable-cognito-user-pool
https://github.com/awslabs/serverless-application-model/blob/master/examples/2016-10-31/inline_swagger/template.yaml
Edit: Fixed Swagger 2.0 syntax for the 'security' section, it should be a list.
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.