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
Related
I am trying to define an authorizer and use it in a method using Open API Specification. For some reason the authorizer does not appear in the API Gateway Console after I deploy the template. Here's my template shortened:
Type: AWS::Serverless::Api
Properties:
Name: !Sub "API Gateway"
EndpointConfiguration:
Type: REGIONAL
DefinitionBody:
openapi: 3.0.3
info:
title: 'APIs'
version: 1.0.0
paths:
/callHistoryAsync:
post:
parameters:
- name: 'xxxxx'
in: 'query'
required: true
schema:
type: 'string'
x-amazon-apigateway-integration:
type: aws
requestParameters:
integration.request.header.X-Amz-Invocation-Type: '''Event'''
integration.request.querystring.store_id: "method.request.querystring.xxxxx"
httpMethod: POST
uri: !Sub 'arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Function.Arn}/invocations'
responses:
'202':
statusCode: '202'
selectionPattern: ""
responses:
'202':
description: successfully saved
security:
- Authorizer: []
components:
securitySchemes:
Authorizer:
type: 'request'
name: 'Authorization'
in: 'header'
x-amazon-apigateway-authorizer:
authorizerUri: !FindInMap [ !Ref StageName, !Ref "AWS::Region", AuthArn ]
identitySource: 'method.request.header.X-Authorization,method.request.header.X-Date'
type: 'request'
I defined the authorizer in components under securitySchemes and I am using it in the POST method specified under security.
But the authorizer does not appear in the console and neither does it appear under the method. What am I doing wrong?
I figured this out using the export property of the stage tab in API Gateway. I used an existing API Gateway that was defined using CloudFormation and exported it using Export as Swagger + API Gateway Extensions. This basically shows you all the syntax you want.
Here's the screenshot where is this option in the console.
From that export I could see that I need to change my securitySchemes to this:
components:
securitySchemes:
Authorizer:
type: "apiKey"
name: "Unused"
in: "header"
x-amazon-apigateway-authtype: "custom"
x-amazon-apigateway-authorizer:
authorizerUri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:xxxxxx:function:xxxxxxx/invocations"
authorizerResultTtlInSeconds: 300
identitySource: "method.request.header.Authorization, method.request.header.Date"
type: "request"
I have a problem with AWS SAM and provisioning API Gateway configurations. I am trying to do a few things:
Configure the API gateway to require api-key in the headers
Create my own stage as defined in my config files.
The API gateway model defined in my file is not being created
Currently, the API gateway gets provisioned and linked to my lambda function but it fails in the two requirements above. Below are my files: template.yaml and swagger.yaml.
Template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-nfeed-s3
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 60
Api:
EndpointConfiguration: REGIONAL
Resources:
SAMnfeedS3API:
Type: AWS::Serverless::Api
Properties:
StageName: alpha
DefinitionUri: ./swagger.yaml
Resources:
SAMnfeedS3Lambda:
Type: AWS::Serverless::Function
Properties:
CodeUri: test-function-sam/
Handler: nfeed_vdp_clusters.lambda_handler
Runtime: python3.6
Role: arn:aws:iam::XXXXXXX:role/Lambda
Events:
SAMnfeedS3API:
Type: Api
Properties:
Path: /vdp_clusters
Method: GET
Environment:
Variables:
TEST: test
Outputs:
SAMnfeedS3API:
Description: "API Gateway endpoint URL for Staging env"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Staging/vdp_clusters"
SAMnfeedS3Lambda:
Description: "Lambda Function ARN"
Value: !GetAtt SAMnfeedS3Lambda.Arn
Swagger.yaml
---
swagger: '2.0'
info:
title: !Ref AWS::StackName
basePath: "/alpha"
schemes:
- "https"
x-amazon-apigateway-api-key-source : "HEADER"
paths:
"/vdp_clusters":
get:
consumes:
- application/json
produces:
- application/json
parameters:
- name: x-api-key
in: header
required: true
type: string
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
x-amazon-apigateway-integration:
uri: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:XXXXXXXXX:function:${SAMnfeedS3Lambda.Arn}/invocations
responses:
default:
statusCode: "200"
httpMethod: "POST"
type: aws_proxy
security:
- api_key: []
securityDefinitions:
api_key:
type: "apiKey"
name: "x-api-key"
in: "header"
definitions:
Empty:
type: "object"
title: "Empty Schema"
$schema: "http://json-schema.org/draft-04/schema#"
As defined in my swagger and template files, "alpha" stage should be created for the gateway but nothing appears. The "Empty" model and api-key requirement also do not appear. Any help, would be appreciated.
The problem is you have duplicated the Resources key in the template.
I recommend always using the yamllint utility on your SAM templates, because it detects YAML formatting issues that sam validate can't always detect. Here is what I got:
▶ yamllint sam-app/template.yaml
sam-app/template.yaml
...
18:1 error duplication of key "Resources" in mapping (key-duplicates)
If you then look in the packaged.yml file that is created by the sam build step, you'll notice that the API you defined will be missing. That's because it's impossible for a dict in Python to contain duplicate keys. The second Resources block you specified just overwrites the first one when the Python YAML library reads the file in.
SAM then generates the implicit API SAMnfeedS3API based on the API you specified in Events using its own generated Swagger rather than the one you (thought you) provided.
Note also that, after you fix up the duplicate key issue, you will also need to reference your API from the Events with a line like:
Events:
SAMnfeedS3API:
Type: Api
Properties:
Path: /vdp_clusters
Method: GET
RestApiId: !Ref SAMnfeedS3API ## ADD THIS LINE
See also my earlier answer here.
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'
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.
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