Closed bitforth closed 1 year ago
Hi @alanchavez88,
Currently configuring a custom authorizer isn't supported when running locally with SAM Local.
I'll leave this issue open as a feature request for our backlog.
Thanks
Thanks @PaulMaddox for the response!
If I understand the model correctly, it shouldn't matter if my custom authorizer does not run locally, right? In AWS, only authorized requests can trigger the lambda function, correct?
Yes, an authorization request should trigger the Lambda in AWS cloud
I'm wondering how I may use a Cognito Authorizer, is there sample for that? I've gone through all the 5 samples of SAM template.ymls on the internet and am not able to see how I may do so.
Should I just rely on the swagger export? I am migrating an existing hand-build API Gateway to SAM. Thanks for help!
I'm also looking for examples of how to integrate a Cognito Authorizer with lambdas made via SAM templates.
This is a good to have feature in SAM Local, so we can test the authorization functions before deploying
Hi is there a resolution yet for including Custom Authoriser lambda over SAM template itself or is this still a feature request AWS SAM Team is working on?
My database url will not work as it contains '=' and other special characters, int he env variables. How would I get around this? This is a reliant to my company
Interested in this feature as well. Attempting to use sam-local to auth with Cognito before making subsequent requests.
Same here. Anyone knows the timeline to support SAM local custom authorizer ?
@alanchavez88 did you ever figure out how to configure an authorizer, I notice that the question was never answered. It went off on a tangent about Sam local.
@margic no, I never figured it out. I ended up assuming that it worked and moved on :( If you find a way to do it please post it here.
Hi, I wrote a small tutorial about how I use custom authorizers. While this does not work when running locally, it does work when being deployed. Hope it helps.
ApiGateway - AWS::Serverless::Api - The API definition
ApiGatewayAuthorizerRole - AWS::IAM::Role - Role for API Gateway to be able to invoke our custom authorizer function
CustomAuthorizerFunction - AWS::Serverless::Function - The Authorizer function
CustomAuthorizerFunctionRole - AWS::IAM::Role - Role of the custom authorizer function to be able to be invoked and access needed resources
ApiGateway invokes CustomAuthorizerFunction which returns a policy that will allow or deny the further invocation of your path function. For more details see Introducing custom authorizers in Amazon API Gateway
ApiGateway:
Type: AWS::Serverless::Api
Properties:
StageName: prod
DefinitionBody:
swagger: "2.0"
info:
title:
Ref: AWS::StackName
description: My API that uses custom authorizer
version: 1.0.0
securityDefinitions:
...
paths:
...
securityDefinitions:
CustomAuthorizer:
type: apiKey
name: Authorization
in: header
x-amazon-apigateway-authtype: custom
x-amazon-apigateway-authorizer:
type: token
authorizerUri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${CustomAuthorizerFunction.Arn}/invocations
authorizerCredentials:
Fn::Sub: ${ApiGatewayAuthorizerRole.Arn}
authorizerResultTtlInSeconds: 60
paths:
...
"/somepath":
post:
security:
- CustomAuthorizer: []
...
CustomAuthorizerFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs6.10
Handler: index.handler
...
Role:
Fn::Sub: ${CustomAuthorizerFunctionRole.Arn}
ApiGatewayAuthorizerRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "apigateway.amazonaws.com"
Action:
- sts:AssumeRole
Policies:
-
PolicyName: "InvokeAuthorizerFunction"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- lambda:InvokeAsync
- lambda:InvokeFunction
Resource:
Fn::Sub: ${CustomAuthorizerFunction.Arn}
CustomAuthorizerFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
...
Is there any example for cognito authorizer?
@kind3r This is an excellent tutorial. Something a lot of people will find it very useful. Will you be interested in submitting this as a pull request to the SAM Repo docs please? https://github.com/awslabs/serverless-application-model/tree/develop/docs
given that the swagger support is for version 2 and not OpenAPI 3 i would expect this feature to come out in the next release. seems like a HUGE oversight in terms of API definition to not allow authorisation in SAM templates.
have spent the last two days trying to get the version 2 swagger def to work in SAM, long story short. i may as well write a full cloudformation stack.
i will definitely be looking into other services soon if this feature isn't implemented.
Got this working - thanks!
I can't find a simple example of using a Cognito authorizer in an Api event event of a lambda function
None of the examples given here worked for me. I finally followed this https://github.com/awslabs/serverless-application-model/blob/master/examples/2016-10-31/api_lambda_request_auth/template.yaml and i got it working.
My custom authorizer cloud formation definition:
RestApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Auth:
DefaultAuthorizer: ApiAuthorizer
Authorizers:
ApiAuthorizer:
FunctionPayloadType: TOKEN
FunctionArn: !GetAtt CustomAuthorizerFunction.Arn
FunctionInvokeRole: !GetAtt CustomAuthorizerFunctionRole.Arn
Identity:
Headers:
- Authorization
ReauthorizeEvery: 300
For those playing at home, this relies on the idtoken which cannot be explicitly invalidated. If you never want to log a user out by invalidating the token then it’s a great fit. But if you’re needing to invalidate a token on behalf of a user then you should implement a custom authoriser that checks the access token
Does anyone know if we can harcode function arn in FunctionArn?
Not sure why you would want to do that.. are you defining an authoriser in the same Sam template as the inline swagger markup?
FWIW I found the best way to manage a custom authoriser was to make a separate cloudformation or Sam stack with that function on its own and then output the ARN. Then reference it in the Sam templates that have swagger definitions for authorisation
@nk2580 thanks for replying. Sorry that was pure for testing purpose. I have a separate sam stack for custom authoriser which gets deployed and then a separate stack for functions. But somehow it was not working and was unable to find any example. So decided to give a try with hardcode one.
custom autoriser sam template.yml
AWSTemplateFormatVersion: "2010-09-09"
Transform: "AWS::Serverless-2016-10-31"
Description: >-
A custom authoriser to verify JWT token.
Globals:
Function:
Runtime: nodejs8.10
Resources:
Authoriser:
Type: "AWS::Serverless::Function"
Properties:
FunctionName: test-authoriser
CodeUri: src/
Handler: index.handler
Outputs:
AuthoriserArn:
Description: The Arn of the created autoriser
Value: !GetAtt Authoriser.Arn
and below is my another stack where I want to reference the custom authoriser
AWSTemplateFormatVersion: "2010-09-09"
Transform: "AWS::Serverless-2016-10-31"
Globals:
Function:
Runtime: nodejs8.10
Api:
Cors:
AllowMethods: "'*'"
AllowHeaders: "'*'"
AllowOrigin: "'*'"
Resources:
TestApi:
Type: AWS::Serverless::Api
Properties:
StageName: dev
Auth:
DefaultAuthorizer: Test-Authorizer
Authorizers:
Test-Authorizer:
FunctionArn: arn:aws:lambda:region:account-number:function:function-name
Identity:
Header: Authorizer
ValidationExpression: ^Bearer [-0-9a-zA-Z\._]*$
ReauthorizeEvery: 30 # seconds
Test:
Type: "AWS::Serverless::Function"
Properties:
FunctionName: test-function
CodeUri: src/test
Handler: index.test
Events:
EndPoint:
Type: Api
Properties:
RestApiId: !Ref TestApi
Path: /test
Method: get
Auth:
Authorizer: Test-Authorizer
And this where i have very limited knowledge how to achieve this. Any help would be highly appreciated. Thanks
I’ve basically done the same but I’ve used swagger to define my api gateway resources.. it’s a little easier than using cloudformation and it reduces the size of your files
Could someone please tell me whether configuring a custom authorizer when running locally with SAM Local is supported?
@mgrissa I'm running into this issue and I'm assuming running it locally is not supported. It completely bypasses the authorizer and hits your function which is not ideal when your api is user focussed
Worse still there’s no way to have the data passed through cognito back to the lambda after authorisation. Basically it’s an unsuitable solution for API security
@nk2580 I'm working around it by starting my local api with an environment variable. If I see that environment variable in my lambda then I use the email I pass into the request otherwise I use whats in the event.requestContext.authorizer
object
event.requestContext.authorizer
is populated by the cognito authorizer when it's deployed and you're calling the api gateway endpoint through a client
@joeythomaschaske I would recommend using the Serverless Offline plugin of the Serverless Framework. I am able to run an API Gateway with a Lambda Authorizer and a Lambda Proxy locally thanks to this plugin.
@mgrissa I'm not using Serverless Framework. I want to use 1st party tooling if it's available and this is a viable work around.
Any update on this? Best I can grok from the docs, this should be working.
MyServerlessAPI:
Type: AWS::Serverless::Api
Properties:
StageName: Dev
Auth:
DefaultAuthorizer: VerifyIAMAuthorizer
Authorizers:
VerifyIAMAuthorizer:
FunctionArn: !GetAtt IamAuthorizerFunction.Arn
IamAuthorizerFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./cmd/authorizer
TestFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./cmd/test
Events:
APIRequest:
Type: Api
Properties:
RestApiId: !Ref MyServerlessAPI
Path: /
Method: get
I'm just looking for the minimal configuration to make it work for PoC.
So far the only way I can get the authoriser to take effect is to use the inline swagger feature of SAM. It’s actually not as cumbersome as I originally thought but it does end up making your template.yml file bloated.
@nk2580 - Would you mind sharing a working example?
Any update on this? When local custom authorizers will be supported?
Ditto ^
I have a hard time figuring out what doesn't work with sam local, for example custom authorizers, is there any place where one can read the current known limitations?
I contacted AWS support (Business support) regarding this issue and received a reply stating that testing the authorizers for API resources locally is not available currently. I was told it's a known issue open with the SAM team and the SAM team will be working on it based on the priority they assigned it - no ETA on when this will be available. I've attached a very slimmed down version of the code to this reply.
So far the only way I can get the authoriser to take effect is to use the inline swagger feature of SAM. It’s actually not as cumbersome as I originally thought but it does end up making your template.yml file bloated.
@nk2580 Hey, do you have an example you'd be open to sharing?
Here is a patch that supports swagger based Authorizers right now... aws-sam-cli-feature-jwt.patch.txt
Any update on getting this to work locally? I'm surprised after 3 years it wasn't implemented
SAM doesn't support custom authorizers when you run locally now (SAM version 0.48). So you can't test it by using "sam local start-api".
But it supports in SAM YAML template and you can use SAM CLI to build and deploy custom authorizers to you AWS cloud Api Gateway. It can work well if your YAML setup is correct.
As per @joeythomaschaske recommended, you can make it work by running Serverless Offline
plugin using Serverless Framework.
The current highly decorated response to this open feature request from 2017 is unrelated and clearly states it does not work locally.
Can an AWS employee please comment on the main obstacles faced in implementing this core functionality? Perhaps if more was shared besides that it is not currently supported we could get the community to help with a PR.
Relying on a 3rd party's framework to be able to test code locally is surprising. As it stands now, if one is using a Lambda Custom Authorizer (I'd venture to guess a large portion of the community does) any local test of anything related to authorization is impossible using AWS provided tools to my knowledge. The current "in ecosystem" solution is to deploy to a dev/test environment which massively slows down the development process.
Edit 1: A quick idea:
Perhaps a simpler local implementation could rely on a local json file with mocked policy objects passed to start-api command? Maybe something like --policy-ref (similar to how --env-vars functions). Then perhaps a header can be passed with requests to the local header with a reference to which policy document/mocked authorizer response the _request_handler should "authorize" against?
While this won't imitate the actual flow (in fact is not hitting the custom authorizer at all) it at least allows app specific logic to be tested locally during development.
Edit 2:
If we do as proposed in Edit 1 above perhaps the underlying implementation could rely on the main AWS CLI's test-invoke-authorizer (https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigateway/test-invoke-authorizer.html)?
In this way two sets of similar code will not need to be maintained and a real authorizer can be hit and passed to the context in _request_handler pre-lambda call.
opened this issue on 24 Sep 2017
3 years and stil no luck.... no comment.
FWIW I ended up moving all my compute to GCP’s Cloud Run because at least in that product I can test everything locally with extreme ease.
@nk2580 Can you point me to GCP documentation for how to test REST API's locally? I'm curious
@aidan-plenert-macdonald Cloud run is a serverless docker container runtime so you test your API locally the same way you would any non serverless application. The only caveat to the platform is that the application needs to be stateless as there’s no guarantee of the same instance serving all HTTP traffic.
To run your application locally you just run ‘docker run’ using the dockerfile for your application
+1
I'm new to SAM and I've been stuck for quite a long stressful time testing Authorizer locally and finally found this opened issue. Surprisingly, this has been opened since 2017 and there is no even work-around solution? 😳
The only workaround is to deploy and test in a dev account
I'm using the tool to spin up locally an API gateway and run my lambda functions. However, I don't know how to configure an authorizer in
template.yml
In my
template.yml
file, I have the following configuration:If I understand the authorizers documentation correctly, I should be able to add the following configurations in order to configure my authorizer
Everything up until that point works fine. If I run
sam validate
the output isValid!
sam local start-api
executes without a problem.However, I don't know how to configure the custom authorizer in my lambda functions. I've read the AWS::Serverless::Function documentation but I couldn't find anything relevant to my issue. Furthermore, there are two issues about adding support for AuthorizationType to the API but it's unclear whether this support will ever be added, or if it has been added already.
Any help pointing in the right direction is greatly appreciated!