export const meta = {
  title: `Override Amplify-generated API Gateway resources`,
  description: `The "amplify override api" command generates a developer-configurable "overrides" TypeScript file which provides Amplify-generated API Gateway resources as CDK constructs. For example, developers can configure a custom description or the minimum compression size of their REST API.`,
};

```bash
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](https://docs.aws.amazon.com/cdk/latest/guide/home.html).

Apply all the overrides in the `override(...)` function. For example:

```ts
// This file is used to override the REST API resources configuration
import { 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\>]`:

```ts
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:

<div class="table-wrapper" markdown="block">

|Amplify-generated resource|Description|
|-|-|
|[restApi](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html)|The Amazon API Gateway REST API created by `amplify add api`|
|[deploymentResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-deployment.html)|The deployment resource that deploys the REST API above to a stage.|
|[policies](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|User pool group-related IAM policy. Example: `resources.policies["/items"].groups["Admin"]`


</div>

## 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:

```ts
// Replace the following with your Auth resource name
const authResourceName = "<your-auth-resource-name>";
const userPoolArnParameter = "AuthCognitoUserPoolArn";

// Add a parameter to your Cloud Formation Template for the User Pool's ID
resources.addCfnParameter({
    type: "String",
    description: "The ARN of an existing Cognito User Pool to authorize requests",
    default: "NONE",
  },
  userPoolArnParameter,
  { "Fn::GetAtt": [`auth${authResourceName}`, "Outputs.UserPoolArn"], }
);
```

<Callout warning>

Make sure to replace `<your-auth-resource-name>` with the name of your auth resource.
This is the name of the folder in `amplify/backend/auth` that was created when
you added an Auth resource to your Amplify project.

</Callout>

Now, define a REST API authorizer with Cognito User Pools using the OpenAPI extension, [`x-amazon-apigateway-authorizer`](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-authorizer.html). This change will be applied by modifying the security definition of your REST API:

```ts
// Create the authorizer using the AuthCognitoUserPoolArn parameter defined above
resources.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. 

```ts
// For every path in your REST API
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 Cognito User Pool authorizer for security
  resources.restApi.addPropertyOverride(
    `Body.paths.${path}.x-amazon-apigateway-any-method.security`,
    [ { Cognito: [], }, ]
  );
}
```

<Callout>

Note that you can add more advanced logic to only use the Cognito User Pool authorizer
with some paths or methods.

</Callout>

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.

