I am trying to test authorization of a Lambda function using Cognito, Serverless framework & Serverless-Offline plugin.
When I run my stack locally using serverless offline, all requests by default are authorized and I can execute them without a problem.
The command is serverless offline
What I cant do is test unauthorized requests locally, when I use the argument --noAuth the request is still authorized by default, which means I can't test scenarios of unauthorized access.
Using serverless offline --noAuth
When I am developing locally, how can I test requests against my handler that are unauthorized?
Here is my yml:
service: apples
provider:
name: aws
runtime: nodejs8.10
stage: ${opt:stage, 'dev'}
region: ap-southeast-2
profile: personal
plugins:
- serverless-offline
functions:
hello:
handler: handler.hello
events:
- http:
path: users
method: get
cors: true
authorizer:
arn: ${cf:apples-auth-dev.CognitoUserPoolArn}
Related
I used the serverless framework to setup some POST apis and then wrote a crude NextJs app to try to authenticate with Cognito and then use the apis protected by the authorizer.
I validated the api and it works without the authorizer. (Tested in Postman)
I am printing to the console the access_token and the id_token received from cognito.
The id_token passes the UI based Authorizer test on aws
My requests both on the front-end app and Postman fail however despite including the Authorization header with the token (tried both tokens).
I also tried to manually enable CORS on the Aws UI but still no luck.
I also looked at this article (https://www.serverless.com/blog/cors-api-gateway-survival-guide/) but no luck and at this point I don't know what to do.
Part of my serverless.yml:
custom:
allowedHeaders:
- Accept
- Content-Type
- Content-Length
- Authorization
- X-Amz-Date
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- app_user_id
- app_user_name
...
createResource:
handler: api/${name}.handler
description: POST /${name}
events:
- http:
path: api/${name}
method: post
authorizer:
type: COGNITO_USER_POOLS
authorizerId:
Ref: ApiGatewayCognitoAuthorizer
scopes:
- email
cors:
origin: '*'
headers: ${self:custom.allowedHeaders}
reqValidatorName: ${name}RequestValidator
integration: lambda
request:
template:
application/json: ${file(api/resource/mappingTemplates/${name}RequestMappingTemplate.vm)}
passThrough: WHEN_NO_MATCH
...
ApiGatewayCognitoAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: CognitoUserPool-${self:provider.environment.VERSION}
Type: COGNITO_USER_POOLS
IdentitySource: method.request.header.Authorization
RestApiId:
Ref: ApiGatewayRestApi
ProviderARNs:
- ${self:custom.settings.cognitoARN-${env:ENV_NAME}}
I solved the issue after a bunch of attempts. I found this article that is very similar:stackoverflow.com/questions/46345005/… The solution that worked for me was to add 'openid' to the api's oauth scopes instead of just 'email'. Then I tried access_token as opposed to id_token on both Postman and the browser and hallelujah
The Serverless framework has made it very easy for developers to create an API gateway connected to a lambda function. like this
hello:
name: hello-handler
description: blablabla
handler: /lambda-functions/hello-handler.handler
role: HelloRole
package:
include:
- lambda-functions/hello-handler.js
events:
- http: GET hello
My question is how can I change the name of the API gateway that is going to be created?
Based on the doc, this should do the trick.
provider:
...
apiName: custom-api-name # Use a custom name for the API Gateway API
I'm working on a web service in which one Lambda function serves requests from a web browser. This request handling kicks off some slow work that can be completed asynchronously, so I have a separate Lambda function that I want to invoke asynchronously to handle the slow work.
This is being deployed as a Serverless project. The serverless.yml file looks like this:
service: AsyncService
frameworkVersion: '=1.54.0'
provider:
name: aws
runtime: go1.x
package:
exclude:
- ./**
include:
- ./bin/**
functions:
FrontEnd:
handler: bin/FrontEnd
events:
- http:
path: processData
method: post
environment:
AsyncWorkerARN: ???
AsyncWorker:
handler: bin/AsyncWorker
The question is how can I get the ARN of the AsyncWorker Lambda function into an environment variable of the FrontEnd Lambda function without hardcoding it? I need it there to be able to invoke the AsyncWorker Lambda.
I think the best way is to use the serverless-pseudo-parameters plugin and then do something like: arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:AsyncService-dev-AsyncWorker
I am deploying a project with the Serverless framework that includes different resources (a lambda function, cognito user pool, cognito identity pool, etc...)
For a previous project, we created from the console (so manually) the configuration for a second Api Gateway (in addition to the one that we configured with Serverless on the lambda) to just be the proxy for our s3 bucket, so we were able to add and get files from the bucket without using the lambda.
Now, I want to make the exact thing to this new project, but instead making the second Api Gateway manually from the console, there is a way to declare this proxy directly from Serverless configuration?
I searched for different solutions, but I didn't find any guide for this.
What I'm trying to make in the configuration is what this amazon guide explains.
You can use this plugin that allows setting up API Gateway service proxies very easily (I'm one of the collaborators).
serverless.yml example:
service: s3-proxy
provider:
name: aws
runtime: nodejs10.x
plugins:
- serverless-apigateway-service-proxy
custom:
apiGatewayServiceProxies:
- s3:
path: /s3/{key}
method: post
action: PutObject
bucket:
Ref: S3Bucket
key:
pathParam: key
cors: true
resources:
Resources:
S3Bucket:
Type: 'AWS::S3::Bucket'
When api specification of serverless.yml is described in swagger format in resources instead of functions , API can not be executed locally.
API specification of serverless.yml is described in swagger format in resources
serverless.yml is below.
functions:
test:
handler: test.test
resources:
Resources:
RestApi :
Type : AWS::ApiGateway::RestApi
Properties :
Body : ${file(./swagger.yaml)}
The result of sls offline does not have routes for test API.
Serverless: Starting Offline: dev/ap-northeast-1.
Serverless: Routes for test:
Serverless: (none)
Serverless: Offline listening on http://localhost:3000
API specification of serverless.yml is described in swagger format in functions
serverless.yml is below.
functions:
test:
handler: test.test
events:
- http: GET test
#resources:
# Resources:
# RestApi :
# Type : AWS::ApiGateway::RestApi
# Properties :
# Body : ${file(./swagger.yaml)}
The result of sls offline have routes for test API.
Serverless: Starting Offline: dev/ap-northeast-1.
Serverless: Routes for test:
Serverless: GET /test
Serverless: Offline listening on http://localhost:3000
I want to run the API locally by describing specifications in swagger format in resources. Is there a way to achieve this?
The serverless-offline plugin understands the serverless landscape, but does not understand custom AWS resources. Its also unlikely to in the future as serverless is an abstraction layer.
Perhaps aws-sam-cli would be a better fit for your application. It seems to support swagger docs and a local environment.