Override Amplify-generated API Gateway resources
amplify override api
Run the command above to override Amplify-generated Amazon API Gateway resources.
The command creates a new overrides.ts
file under amplify/backend/api/<resource-name>/
which provides you the Amplify-generated resources as CDK constructs.
Apply all the overrides in the override(...)
function. For example:
// This file is used to override the REST API resources configurationimport { AmplifyApiRestResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';
export function override(resources: AmplifyApiRestResourceStackTemplate) { resources.restApi.description = "Custom description"; resources.restApi.minimumCompressionSize = 1024;}
To change a field on a particular path, use resources.restApi.body.paths[\<route-path\>]
:
export function override(resources: AmplifyApiRestResourceStackTemplate) { // Change the default CORS response header Access-Control-Allow-Origin from "'*'" to the API's domain resources.restApi.body.paths['/items'].options['x-amazon-apigateway-integration'].responses.default.responseParameters['method.response.header.Access-Control-Allow-Origin'] = { 'Fn::Sub': "'https://${ApiId}.execute-api.${AWS::Region}.amazonaws.com'" };}
You can override the following REST API resources that Amplify generates:
Amplify-generated resource | Description |
---|---|
restApi | The Amazon API Gateway REST API created by amplify add api |
deploymentResource | The deployment resource that deploys the REST API above to a stage. |
policies | User pool group-related IAM policy. Example: resources.policies["/items"].groups["Admin"] |
Authorize API requests with Cognito User Pools
Amazon Cognito User Pools is a common service to use alongside API Gateway when adding user Sign-Up and Sign-In to your application. If your application needs to interact with other AWS services such as S3 on behalf of the user who invoked an endpoint, you will need to use IAM credentials with Cognito Identity Pools.
Amplify CLI does not support Cognito User Pool authorizers out-of-the-box. To
implement this functionality, you must override your REST API and add a Cognito
User Pool authorizer yourself by adding the following code into the
override(...)
function, in order.
First, assuming the Cognito User Pool you would like to use as an authorizer is the Auth resource configured with your Amplify Project, create a parameter that resolves to its User Pool ARN:
// Replace the following with your Auth resource nameconst authResourceName = "<your-auth-resource-name>";const userPoolArnParameter = "AuthCognitoUserPoolArn";
// Add a parameter to your Cloud Formation Template for the User Pool's IDresources.addCfnParameter({ type: "String", description: "The ARN of an existing Cognito User Pool to authorize requests", default: "NONE", }, userPoolArnParameter, { "Fn::GetAtt": [`auth${authResourceName}`, "Outputs.UserPoolArn"], });
Now, define a REST API authorizer with Cognito User Pools using the OpenAPI extension, x-amazon-apigateway-authorizer
. This change will be applied by modifying the security definition of your REST API:
// Create the authorizer using the AuthCognitoUserPoolArn parameter defined aboveresources.restApi.addPropertyOverride("Body.securityDefinitions", { Cognito: { type: "apiKey", name: "Authorization", in: "header", "x-amazon-apigateway-authtype": "cognito_user_pools", "x-amazon-apigateway-authorizer": { type: "cognito_user_pools", providerARNs: [ { 'Fn::Join': ['', [{ Ref: userPoolArnParameter }]], }, ], }, },});
Finally, update the security methods for all of the paths in your REST API to
use this new Cognito User Pool authorizer. You also add the Authorization
header
as a parameter on incoming requests for these paths as a place for users to provide
their Cognito User ID Tokens.
// For every path in your REST APIfor (const path in resources.restApi.body.paths) { // Add the Authorization header as a parameter to requests resources.restApi.addPropertyOverride( `Body.paths.${path}.x-amazon-apigateway-any-method.parameters`, [ ...resources.restApi.body.paths[path]["x-amazon-apigateway-any-method"] .parameters, { name: "Authorization", in: "header", required: false, type: "string", }, ] ); // Use your new Cognito User Pool authorizer for security resources.restApi.addPropertyOverride( `Body.paths.${path}.x-amazon-apigateway-any-method.security`, [ { Cognito: [], }, ] );}
When performing requests to your REST API, make sure to add the Authorization
header with an ID Token provided by Cognito.
Requests to endpoints are now populated with information from Cognito about the user who is invoking the endpoint, and you can reuse the verified ID Token in your endpoint resolvers to assume the identity of the user for accessing other services like AWS AppSync or S3.
Authorize API requests with Lambda authorizer
While Amplify CLI does not support Lambda authorizers natively out-of-box, you can implement this functionality by overriding your REST API resources. The following steps will walk you through how to create token-based Lambda authorizer.
First, you need to have a Lambda authorizer function with required authorization logic in your Amplify project to use it as an authorizer. Refer to the steps to set up a function using amplify add function
After running amplify override api
, add the following code to override(...)
function.
Initially, create a parameter that resolves to Lambda Function ARN
// Replace the following with your Function resource nameconst functionResourcename = "<your-function-resource-name>";const functionArnParameter = "FunctionArn";
// Adding parameter to your Cloud Formation Template for Authorizer function arnresources.addCfnParameter( { type: "String", description: "The ARN of an existing Lambda Function to authorize requests", default: "NONE", }, functionArnParameter, { "Fn::GetAtt": [`function${functionResourcename}`, "Outputs.Arn"], });
Next, define the Lambda authorizer using the OpenAPI extension, x-amazon-apigateway-authorizer
. This change will be applied by modifying the security definition of your REST API:
// Create the authorizer using the functionArnParameter parameter defined aboveresources.restApi.addPropertyOverride("Body.securityDefinitions", { Lambda: { type: "apiKey", name: "Authorization", in: "header", "x-amazon-apigateway-authtype": "oauth2", "x-amazon-apigateway-authorizer": { type: "token", authorizerUri: { 'Fn::Join': [ '', [ "arn:aws:apigateway:", { Ref: 'AWS::Region' }, ":lambda:path/2015-03-31/functions/", { Ref: functionArnParameter }, "/invocations" ] ], }, authorizerResultTtlInSeconds: 0 }, },});
As API Gateway needs permission to invoke the Authorizer lambda function, add resource based policy to the function using following code:
// Adding Resource Based policy to Lambda authorizer functionresources.addCfnResource( { type: "AWS::Lambda::Permission", properties: { Action: "lambda:InvokeFunction", FunctionName: {Ref: functionArnParameter}, Principal: "apigateway.amazonaws.com", SourceArn:{ "Fn::Join": [ "", [ "arn:aws:execute-api:", { "Ref": "AWS::Region" }, ":", { "Ref": "AWS::AccountId" }, ":", { "Ref": "<your-API-resource-name>" }, "/*/*" ] ] } } }, "LambdaAuthorizerResourceBasedPolicy");
Finally, update the security methods for all of the paths in your REST API to use this new Lambda authorizer. You can also add the Authorization header as a parameter on incoming requests for these paths as a place for users to provide their Auth token.
for (const path in resources.restApi.body.paths) { // Add the Authorization header as a parameter to requests resources.restApi.addPropertyOverride( `Body.paths.${path}.x-amazon-apigateway-any-method.parameters`, [ ...resources.restApi.body.paths[path]["x-amazon-apigateway-any-method"] .parameters, { name: "Authorization", in: "header", required: false, type: "string", }, ] ); // Use your new Lambda authorizer for security resources.restApi.addPropertyOverride( `Body.paths.${path}.x-amazon-apigateway-any-method.security`, [ { Lambda: [], }, ] );}
When performing requests to your REST API, make sure to add the Authorization header with an token required by Lambda authorizer function.