Skip to content

Instantly share code, notes, and snippets.

@jonatassaraiva
Last active January 19, 2023 13:55
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save jonatassaraiva/4c33dd8225605c02318cd71a55b2335d to your computer and use it in GitHub Desktop.
Save jonatassaraiva/4c33dd8225605c02318cd71a55b2335d to your computer and use it in GitHub Desktop.
service: my-api-gateway
provider:
name: aws
runtime: nodejs6.10
region: sa-east-1
stage: v1
deploymentBucket: ${env:DEPLOYMENT_BUCKET}
iamRoleStatements:
- Effect: Allow
Action:
- cloudwatch:*
- logs:*
- xray:*
- dynamodb:*
Resource: "*"
functions:
get:
name: my-api-gateway-get-${self:provider.stage}
handler: handler.get
description: Function to get
memorySize: 512
timeout: 30
events:
- http:
method: GET
path: service
cors: true
post:
name: my-api-gateway-post-${self:provider.stage}
handler: handler.get
description: Function to post
memorySize: 512
timeout: 30
events:
- http:
method: POST
path: service
cors: true
environment:
MY_ENV: ${env:MY_ENV}
custom:
stage: "${opt:stage, self:provider.stage}"
resources:
Resources:
ApiGatewayRestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: ${self:service}-${self:custom.stage}
#### Gateway Response INIT
GatewayResponseDefault400:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: DEFAULT_4XX
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-4XX-generic\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseDefault500:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: DEFAULT_5XX
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-5XX-generic\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseAccessDeied:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: ACCESS_DENIED
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-403-access-denied\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseApiConfigurationError:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: API_CONFIGURATION_ERROR
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-500-api-configuration-error\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseAuthorizerConfigurationError:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: AUTHORIZER_CONFIGURATION_ERROR
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-500-authorizer-configuration-error\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseAuthorizerFailure:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: AUTHORIZER_FAILURE
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-500-authorizer-failure\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseBadRequestBody:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: BAD_REQUEST_BODY
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-400-bad-request-body\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseBadRequestParameters:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: BAD_REQUEST_PARAMETERS
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-400-bad-request-parameters\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseExpiredToken:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: EXPIRED_TOKEN
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-403-expired-token\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseIntegrationFailure:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: INTEGRATION_FAILURE
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-504-integration-failure\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseIntegrationTimeout:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: INTEGRATION_TIMEOUT
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-504-integration-timeout\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseInvalidApiKey:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: INVALID_API_KEY
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-403-invalid-api-key\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseInvalidSignature:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: INVALID_SIGNATURE
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-403-invalid-signature\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseMissingAuthenticationToken:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: MISSING_AUTHENTICATION_TOKEN
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-403-missing-authentication-token\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseQuotaExceeded:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: QUOTA_EXCEEDED
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-429-quota-exceeded\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseRequestTooLarge:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: REQUEST_TOO_LARGE
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-413-request-too-large\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseResourceNotFound:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: RESOURCE_NOT_FOUND
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-404-resource-not-found\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseThrottled:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: THROTTLED
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-429-throttled\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseUnauthorized:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: UNAUTHORIZED
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-401-unauthorized\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
GatewayResponseUnauthorizedMediType:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
RestApiId:
Ref: 'ApiGatewayRestApi'
ResponseType: UNSUPPORTED_MEDIA_TYPE
ResponseTemplates:
application/json: "{\"error\":{\"code\":\"custom-415-unsupported-media-type\",\"message\":$context.error.messageString},\"requestId\":\"$context.requestId\"}"
#### Gateway Response END
DynamoDbTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: service-db
AttributeDefinitions:
- AttributeName: accessToken
AttributeType: S
KeySchema:
- AttributeName: accessToken
KeyType: HASH
TimeToLiveSpecification:
AttributeName: expires
Enabled: true
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
@jonatassaraiva
Copy link
Author

Sample of serverless configuration to customize:

Name of API Gateway

service-name-v1

Gateway Response:

{
    "error": {
        "code": "custom-401-unauthorized",
        "message": "The request has not been applied because it lacks valid authentication credentials for the target resource."
    },
    "requestId": "30d4cf1e-cf87-41a7-bd5c-7cc24f10345a"
}

DynamoDB TTL

TimeToLiveSpecification

@xflahertyx
Copy link

Have you been able to customize your error message from AUTHORIZER_CONFIGURATION_ERROR for a custom authorizer? I get "message": null with everything I've tried.

@jonatassaraiva
Copy link
Author

Hi @xflahertyx, I'm not using custom authorizer yet. If you find out how it works let me know.

@bmetea
Copy link

bmetea commented Apr 2, 2020

Hi @xflahertyx, did you find an answer to that? I'm struggling with the same problem

@xflahertyx
Copy link

Hi @xflahertyx, did you find an answer to that? I'm struggling with the same problem

No. We only needed the custom authorizer because API Gateway uses the Content-MD5 header for it's own purposes and we needed to pass that header forward as context. Letting that lambda return the http response was simpler than trying to manage it with the authorizer configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment