Unable to configure Firebase authorization to AWS API Gateway - amazon-web-services

I am developing a REST API with AWS Lambda and API Gateway. I am trying to configure Firebase authorization to this. FYI, I have not touched the AWS Web Console, just trying to do everything with the aws-sam.
Below is my code. I have not changed anything below, code is pasted as it is.
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
aws-restapi
Sample SAM Template for aws-restapi
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 5
VpcConfig:
SecurityGroupIds:
- sg-041f2459dcd921e8e
SubnetIds:
- subnet-038025dd
- subnet-c44254cb
Parameters:
FirebaseProjectId:
Type: String
Resources:
AuthGatewayHttpApi:
Type: AWS::Serverless::HttpApi
Properties:
Auth:
Authorizers:
FirebaseAuthorizer:
IdentitySource: $request.header.Authorization
JwtConfiguration:
audience:
- !Ref aws-7e5db
issuer: !Sub https://securetoken.google.com/${aws-7e5db}
DefaultAuthorizer: FirebaseAuthorizer
StageName: "Prod"
AuthFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: aws-restapi/
Handler: source/testfile.lambdaHandler
Runtime: nodejs14.x
Events:
Gateway:
Type: HttpApi
Properties:
ApiId: !Ref AuthGatewayHttpApi
Path: /hello
Method: GET
testfile.js
exports.lambdaHandler = async (event) => {
try {
// If an authenticated request is made to JWT
// Which we expect is what will happen
// So we simply return the claims
const jwt = event.requestContext.authorizer.jwt.claims;
// Let us get the email from the claims
// Note the email will not be available if Sign in via phone
const email = jwt.claims.email;
return {
statusCode: 200,
body: JSON.stringify({ jwt: jwt, email: email }),
};
} catch (err) {
console.error(err);
return {
statusCode: 400,
body: JSON.stringify({ error: "Please check logs" }),
};
}
};
This builds, but cannot deploy. It simply throws the following error.
Error: Failed to create changeset for the stack: aws-restapi, An error occurred (ValidationError) when calling the CreateChangeSet operation: Parameters: [FirebaseProjectId] must have values
What is wrong here? Plus, my firebase auth configuration is correct?

You are defining a parameter but not assigning a value to it.
Parameters:
FirebaseProjectId:
Type: String
Either you delete it, or assign a value

You can avoid this issue also by supplying a default value:
Parameters:
FirebaseProjectId:
Type: String
Default: "1111-2222-3333-44444"

I found the issue for this. I had to pass the parameter. Passing a parameter should be done when you are deploying. Do the following.
sam deploy --guided
Then follow the process, it will ask you for the parameter value. You have to do this whether you have done a deployment before or not.
Then, my code was wrong too. This is how it should be.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
aws-restapi
Sample SAM Template for aws-restapi
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 5
VpcConfig:
SecurityGroupIds:
- sg-041f2459dcd921e8e
SubnetIds:
- subnet-0381asa2d
- subnet-c4dasascb
Parameters:
FirebaseProjectId:
Type: String
Resources:
AuthGatewayHttpApi:
Type: AWS::Serverless::HttpApi
Properties:
Auth:
Authorizers:
FirebaseAuthorizer:
IdentitySource: $request.header.Authorization
JwtConfiguration:
audience:
- !Ref FirebaseProjectId
issuer: !Sub https://securetoken.google.com/${FirebaseProjectId}
DefaultAuthorizer: FirebaseAuthorizer
AuthFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: peresia-restapi/
Handler: source/testfile.lambdaHandler
Runtime: nodejs14.x
Events:
Gateway:
Type: HttpApi
Properties:
ApiId: !Ref AuthGatewayHttpApi
Path: /hello
Method: get

Related

Can anyone provide a working example of an AWS SAM template that has CORS setup in a HttpApi resource?

I have been going round and round trying to get this working. I want to be able to define the CorsConfiguration in the HttpApi resource definition but everything I try simply doesn't work. I can only get CORS working if I defined it globally, but that only works if I don't define the HttpApi resource.
The following is what i have so far based on the documentation.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-app
Sample SAM Template for sam-app
Globals:
Function:
Timeout: 3
Resources:
MainApi:
Type: AWS::Serverless:HttpApi
Properties:
CorsConfiguration:
AllowHeaders:
- "*"
AllowMethods:
- "GET"
AllowOrigins:
- "http://localhost:8000"
ExposeHeaders:
- "*"
DefinitionBody:
openapi: 3.0.1
info:
title: !Ref 'AWS::StackName'
paths: {}
CheckHumanFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
Architectures:
- x86_64
Events:
CheckHuman:
Type: HttpApi
Properties:
ApiId: !Ref MainApi
Path: /human-check
Method: post
Metadata:
DockerTag: nodejs16.x-v1
DockerContext: ./api/human-check
Dockerfile: Dockerfile
Outputs:
MainApi:
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
CheckHumanFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt CheckHumanFunction.Arn
CheckHumanFunctionIamRole:
Description: "Implicit IAM Role created for CheckHuman function"
Value: !GetAtt CheckHumanFunctionIamRole.Arn
The result of this is a 403 on the OPTIONS (preflight) request.
Please can someone provide a working example? But I cannot find an actual working example anywhere and the documentation is infuriating!
Help me Stack Overflow, you're my only hope!
You should add POST and OPTIONS to AllowMethods:
CorsConfiguration
AllowMethods:
- GET
- POST
- OPTIONS
This will cover the preflight request needs.
Note a typo error in your HTTP API resource type definition (has to be AWS::Serverless::HttpApi)
This docs works.
Here is what I am using to configure CORS for my HttpApi (note: I'm using this with a Cognito Authorizer):
Resources:
ApiGatewayApi:
Type: AWS::Serverless::HttpApi
Properties:
StageName: Prod
DefaultRouteSettings:
ThrottlingBurstLimit: 5
ThrottlingRateLimit: 20
Auth:
Authorizers:
GeneralAuth:
AuthorizationScopes:
- email
IdentitySource: "$request.header.Authorization"
JwtConfiguration:
issuer: !Sub https://cognito-idp.${AWS::Region}.amazonaws.com/${UserPoolId}
audience:
- !Ref Audience
CorsConfiguration:
AllowMethods:
- GET
AllowOrigins:
- http://localhost:8080

Error understanding Apigateway and nested stack on AWS cloudformation

I working into decouple a big template with lambdas that use apigateway AWS. I resolve multiple errors about nested stack process, but currently error its not clear. Could you check whats its the problem into definitions?
Main stack show general error from api substack create, but api-substack show next error:
Template error: instance of Fn::Sub references invalid resource attribute CreateCatalogFunctionDev.Arn
Next show a code of templates:
Main Template
SubStackAPIDev:
Type: 'AWS::CloudFormation::Stack'
Properties:
TemplateURL: https://s3.awsroute.com/substack-api.yaml
TimeoutInMinutes: 5
Parameters:
CreateCatalogFunctionDev: !GetAtt CreateCatalogFunctionDev.Outputs.CreateCatalogFunctionDev
SubStackCreateCatalogDev:
Type: 'AWS::CloudFormation::Stack'
Properties:
TemplateURL: https://s3.awsroute.com/substack-create-catalog.yaml
TimeoutInMinutes: 5
Parameters:
APIDev: !GetAtt SubStackAPIDev.Outputs.APIGateway
SubStackCreateCatalogDev
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
SAM template for create catalog
Parameters:
SecretsManagerName:
Type: String
Description: "Secrets Manager Name"
SnsTopicArn:
Type: String
Default: arn:aws:sns:us-west-2:XXXXXX:SNS-errorNotification
Description: "Sns topic error handler email notification"
APIDev:
Type: AWS::Serverless::Api
Resources:
LayerDev:
Type: 'AWS::Serverless::LayerVersion'
Properties:
ContentUri: ../../layer
CompatibleRuntimes:
- python3.6
- python3.7
- python3.8
RetentionPolicy: Delete
CreateCatalogFunctionDev:
Type: AWS::Serverless::Function
Properties:
Description: Recieve api request and and process data.
CodeUri: ../../src/catalog/create_catalog/
Handler: create_catalog.lambda_handler
Runtime: python3.8
FunctionName: CreateCatalogFunctionDev
Role: arn:aws:iam::XXXXXXXX:role/lambda-essential-role
Timeout: 480
Environment:
Variables:
CREATE_CATALOG_SECRET_NAME: !Sub '${SecretsManagerName}'
SNS_ARN: !Sub '${SnsTopicArn}'
Layers:
- arn:aws:lambda:us-west-2:XXXXXXX:layer:requests:1
- arn:aws:lambda:us-west-2:XXXXXXX:layer:requests-oauthlib:1
- !Ref LayerDev
Events:
CreateCatalogApiEvent:
Type: Api
Properties:
Path: /api-channel/products/catalog
Method: POST
RestApiId: !Ref APIDev
SubStack API
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
sub_channels_appi
SAM template for API
Parameters:
SwaggerFile:
Type: String
# TODO dejar URL de S3 de gitla-cicd
Default: "s3://cf-templates-1hurrmgzyzoz3-ap-northeast-1/swagger_dev.yaml"
Description: "This swagger file Amazon S3 path"
SecretsManagerName:
Type: String
Default: "/channels/Dev"
Description: "Secrets Manager Name"
StageName:
Type: String
Default: "${stageVariables.alias}"
Description: "This is the alias to the swagger file"
UsaSupplyApiUrlDev:
Type: String
Default: "https://thecornercloud.com/developers/index.php/"
Description: "Corner Cloud Staging"
SnsTopicArn:
Type: String
Default: arn:aws:sns:us-west-2:000365055762:channels-errorNotification
Description: "Sns topic error handler email notification"
CreateCatalogFunctionDev:
Type: String
Resources:
#######################################
# Serverless LayerVersion
#######################################
LayerDev:
Type: 'AWS::Serverless::LayerVersion'
Properties:
ContentUri: ../../layer
CompatibleRuntimes:
- python3.6
- python3.7
- python3.8
RetentionPolicy: Delete
#######################################
# Serverless API
#######################################
APIDev:
Type: AWS::Serverless::Api
Properties:
Auth:
ApiKeyRequired: true
StageName: dev
EndpointConfiguration: REGIONAL
DefinitionBody:
Fn::Transform:
Name: AWS::Include
Parameters:
Location: !Ref SwaggerFile
Variables:
alias: dev
#######################################
# ApiGateway ApiKey
#######################################
APIKeyDev:
Type: AWS::ApiGateway::ApiKey
Properties:
Name: "APIKeyDev"
Description: "API Key Dev"
Enabled: true
GenerateDistinctId: false
StageKeys:
- RestApiId: !Ref APIDev
StageName: !Ref APIDev.Stage
#######################################
# ApiGateway UsagePlan
#######################################
APIUsagePlanDev:
Type: AWS::ApiGateway::UsagePlan
DependsOn: APIDev
Properties:
ApiStages:
- ApiId: !Ref APIDev
Stage: !Ref APIDev.Stage
Quota:
Limit: 5000
Period: MONTH
Throttle:
BurstLimit: 200
RateLimit: 100
UsagePlanName: APIUsagePlanDev
#######################################
# ApiGateway UsagePlanKey
#######################################
APIUsagePlanKeyDev:
Type: AWS::ApiGateway::UsagePlanKey
Properties:
KeyId: !Ref APIKeyDev
KeyType: API_KEY
UsagePlanId: !Ref APIUsagePlanDev
#######################################
# ApiGateway Deployment
#######################################
DeploymentApiIdDev:
Type: AWS::ApiGateway::Deployment
Properties:
RestApiId: !Ref APIDev
Outputs:
APIGateway:
Description: "API Gateway Reference"
Value: !Ref APIDev
Export:
Name: !Join [":", [!Ref "AWS::StackName", "APIDev"]]
And finally the swagger file (honestly, I didn't define the api with this method and think that I want remove swagger if is possible).
swagger-dev
swagger: "2.0"
info:
version: "1.0.0"
title: "APIDev"
tags:
- name: "Channels"
description: "Manage Channels process."
schemes:
- "https"
x-amazon-apigateway-api-key-source: "HEADER"
securityDefinitions:
APIKey:
type: apiKey
name: X-Api-Key
in: header
paths:
/channels/products/catalog:
post:
tags:
- "Channels"
summary: " products catalog post."
operationId: "ProductsCatalogPostDev"
produces:
- "application/json"
responses:
201:
description: "Successful Operation"
400:
description: "Invalid parameters"
401:
description: "Unauthorized"
405:
description: "Validation exception"
security:
- APIKey: []
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${CreateCatalogFunctionDev.Arn}/invocations
responses:
default:
statusCode: "200"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
contentHandling: "CONVERT_TO_TEXT"
type: "aws_proxy"
Your CreateCatalogFunctionDev is in a different sub-stack then APIDev. You can't reference resources directly across stacks. You either have to export/import their outputs, or pass the references as input parameters.

AWS: Why I am unable to assign a custom domain to the nested stack?

I am trying to integrate a custom domain to the HTTP API I am developing with AWS API Gateway and AWS Lambda. I m using the AWS SAM template. There I have a root stack and nested stacks.
For this question I will use a code piece with a one nested stack. There, this is how I want the URL end points to be
root stack - api.example.com
nested stack - api.example.com/nested
Below is my code
Root stack
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
aws-restapi
Sample SAM Template for aws-restapi
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 5
VpcConfig:
SecurityGroupIds:
- sg-041f24xxxx921e8e
SubnetIds:
- subnet-0xxxxx2d
Parameters:
FirebaseProjectId:
Type: String
#Dont create this domain in the AWS Console manually, so it will fail here
DomainName:
Type: String
Default: api.example.com
Resources:
AuthGatewayHttpApi:
Type: AWS::Serverless::HttpApi
Properties:
Domain:
DomainName: !Ref DomainName
EndpointConfiguration: REGIONAL
CertificateArn: arn:aws:acm:us-east-1:xxxx:certificate/xxxx-420d-xxxx-b40d-xxxx
Route53:
HostedZoneId: xxxxxxxxxxx
Auth:
Authorizers:
FirebaseAuthorizer:
IdentitySource: $request.header.Authorization
JwtConfiguration:
audience:
- !Ref FirebaseProjectId
issuer: !Sub https://securetoken.google.com/${FirebaseProjectId}
DefaultAuthorizer: FirebaseAuthorizer
AuthFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: aws-restapi/
Handler: source/testfile.lambdaHandler
Runtime: nodejs14.x
Events:
Gateway:
Type: HttpApi
Properties:
ApiId: !Ref AuthGatewayHttpApi
Path: /hello
Method: get
NestedStackTwo:
DependsOn: AuthGatewayHttpApi
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: nested_stack.yaml
Parameters:
FirebaseProjectId: !Ref FirebaseProjectId
DomainName: !Ref DomainName
Nested stack
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
aws-restapi
Sample SAM Template for aws-restapi
Globals:
Function:
Timeout: 5
VpcConfig:
SecurityGroupIds:
- sg-xxxxxxxxxxxx
SubnetIds:
- subnet-xxxxxxxxxxx
Parameters:
FirebaseProjectId:
Type: String
DomainName:
Type: String
Resources:
AuthGatewayHttpApi2:
Type: AWS::Serverless::HttpApi
Properties:
Domain:
DomainName: !Ref DomainName
BasePath: two
EndpointConfiguration: REGIONAL
CertificateArn: arn:aws:acm:us-east-1:xxxxx:certificate/xxxxx-xxxx-xxxx-xxxx-xxxx
Route53:
HostedZoneId: xxxxxxxxxxxxx
Auth:
Authorizers:
FirebaseAuthorizer:
IdentitySource: $request.header.Authorization
JwtConfiguration:
audience:
- !Ref FirebaseProjectId
issuer: !Sub https://securetoken.google.com/${FirebaseProjectId}
DefaultAuthorizer: FirebaseAuthorizer
GetAllPromotionsFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: aws-restapi/
Handler: source/promotions/promotions-getall.getAllPromotions
Runtime: nodejs14.x
Events:
GetAllPromotionsAPIEvent:
Type: HttpApi # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /promotions/getall
Method: get
ApiId: !Ref AuthGatewayHttpApi2
However I cant get this to work because the nested stack fails to create. Below is the error
CREATE_FAILED AWS::CloudFormation::Stack NestedStackTwo
Embedded stack arn:aws:cloudformation:us-east-1 xxxxx:stack/aws-restapi-NestedStackTwo-8KBISZRAVYBX/a3fcc010-0ce4-11ec-9c90-0e8a861a6983 was not successfully created:
The following resource(s) failed to create: [ApiGatewayDomainNameV234ac706a57]
I believe this is happening because the root stack creates the domain and the nested stack is trying to re-create it instead of reusing the same.
But, here is the fun fact; if i use the AWS API GATEWAY web console, I can do this in no time.
How can I get this to work in aws-sam ?
UPDATE
Following the advice from the user LRutten, I came up with the following code for the nested stack.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
aws-restapi
Sample SAM Template for aws-restapi
Globals:
Function:
Timeout: 5
VpcConfig:
SecurityGroupIds:
- sg-xxxxxx
SubnetIds:
- subnet-xxxxx
Parameters:
FirebaseProjectId:
Type: String
DomainName:
Type: String
Resources:
AuthGatewayHttpApi2:
Type: AWS::Serverless::HttpApi
Properties:
Auth:
Authorizers:
FirebaseAuthorizer:
IdentitySource: $request.header.Authorization
JwtConfiguration:
audience:
- !Ref FirebaseProjectId
issuer: !Sub https://securetoken.google.com/${FirebaseProjectId}
DefaultAuthorizer: FirebaseAuthorizer
MyApiMapping:
Type: 'AWS::ApiGatewayV2::ApiMapping'
Properties:
DomainName: !Ref DomainName
ApiId: !Ref AuthGatewayHttpApi2
Stage: prod
MyDomainName:
Type: 'AWS::ApiGatewayV2::DomainName'
Properties:
DomainName: !Ref DomainName
DomainNameConfigurations:
- EndpointType: REGIONAL
CertificateArn: arn:aws:acm:us-east-1:716460586643:certificate/bac44716-420d-431b-b40d-01378f20432d
GetAllPromotionsFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: aws-restapi/
Handler: source/promotions/promotions-getall.getAllPromotions
Runtime: nodejs14.x
Events:
GetAllPromotionsAPIEvent:
Type: HttpApi # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /promotions/getall
Method: get
ApiId: !Ref AuthGatewayHttpApi2
This ended up with the following error
Embedded stack arn:aws:cloudformation:us-east-1:716460586643:stack/aws-restapi-NestedStackTwo-14SAYLRO1WD1D/62336020-xx-xx-a04e-x was not successfully created:
The following resource(s) failed to create: [MyDomainName, MyApiMapping].
Indeed SAM always creates the domain when you specify it's name there. It stated in the docs as well.
To get around this, you can omit the whole domain configuration in the AWS::Serverless::HttpApi resource and write the resources created by SAM yourself. So add a section with
Type: AWS::ApiGatewayV2::ApiMapping
Properties:
ApiId: String
ApiMappingKey: String
DomainName: String
Stage: String
Docs
Make sure the Stage property in the ApiMapping is also present in the StageName property of the API.
And a
Type: AWS::ApiGatewayV2::DomainName
Properties:
DomainName: String
DomainNameConfigurations:
- DomainNameConfiguration
MutualTlsAuthentication:
MutualTlsAuthentication
Tags: Json
Docs
Manually adding these without having the domain itself defined twice should do the trick.
Edit: woops wasn't really thinking straight. You should of course only have the mapping, not the domain name itself again :P.

Pass a referance to API Gateway to Lambda

I'm using the Serverless framework and one of my lambda functions needs to know the API gateway id. I tried setting an envierment varable like the following.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Runtime: nodejs6.10
Environment:
Variables:
API_GATEWAY: !Ref ApiGatewayRestApi
Resources:
Test:
Type: AWS::Serverless::Function
Properties:
Handler: LeadLambda.test
CodeUri: ./Lead
Events:
GetResource:
Type: Api
Properties:
Path: /
Method: get
But when I try and deploy I get a circular dependency error.
Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state Status: FAILED. Reason: Circular dependency between resources: [TestGetResourcePermissionProd, ServerlessRestApi, Test, TestGetResourcePermissionTest, ServerlessRestApiDeploymentb5240aa4ca, ServerlessRestApiProdStage]
The solution I ended up using was to hard code the integration uri in the API instead of referencing the Lambda.
Globals:
Function:
Runtime: nodejs6.10
Environment:
Variables:
API: !Sub https://${Api}.execute-api.${AWS::Region}.amazonaws.com/prod
Resources:
Entry:
Type: AWS::Serverless::Function
Properties:
FunctionName: prompt-stack-Entry
Handler: LeadLambda.entry
CodeUri: s3://ddg-prompt/LeadLambda.zip
Role: !GetAtt LeadRole.Arn
Events:
GetResource:
Type: Api
Properties:
Path: /lead
Method: POST
RestApiId: !Ref Api
Api:
Type: AWS::Serverless::Api
Properties:
StageName: prod
DefinitionBody:
swagger: 2.0
info:
title:
Ref: AWS::StackName
paths:
/lead:
post:
responses:
'200':
description: Successful operation
responseTemplates:
application/json: ""
x-amazon-apigateway-integration:
httpMethod: POST
type: aws
uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:prompt-stack-Entry/invocations
responses:
default:
statusCode: '200'
responseTemplates:
application/json: ''

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.