> ## Documentation Index
> Fetch the complete documentation index at: https://docs-dev-actions-triggers-prototype.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Step 2 of Amazon API Gateway Tutorial

# AWS API Gateway Tutorial Step 2

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

<Warning>
  This feature uses delegation. By default, delegation is disabled for tenants without an add-on in use as of 8 June 2017. Legacy tenants who currently use an add-on that requires delegation may continue to use this feature. If delegation functionality is changed or removed from service at some point, customers who currently use it will be notified beforehand and given ample time to migrate. In addition, note that delegation does not support the use of custom domains so any features depending on it may not be fully functional alongside a custom domain.
</Warning>

## Step 2 - Secure and Deploy the Amazon API Gateway

Now that you have your API running, you need to add security. In this step, you will:

* Secure the update API to limit access to authenticated users with a specific AWS IAM role;
* Configure Auth0 delegation to use AWS IAM federation capabilities;
* Obtain an AWS <Tooltip tip="Access Token: Authorization credential, in the form of an opaque string or JWT, used to access an API." cta="View Glossary" href="/docs/glossary?term=Access+Token">Access Token</Tooltip> that uses the AWS IAM role.

Once your API is secure, you'll build a serverless, single-page application (SPA). The SPA will rely on federating identity to determine which users are allowed access. By combining AWS IAM Integration for AWS Gateway API, AWS IAM Identity Federation for <Tooltip tip="Security Assertion Markup Language (SAML): Standardized protocol allowing two parties to exchange authentication information without a password." cta="View Glossary" href="/docs/glossary?term=SAML">SAML</Tooltip>, and Auth0 Delegation for AWS, you can enable users from many different sources, including Social Providers or enterprise connections, to access your APIs. The following diagram illustrates a sample flow using a SAML-based <Tooltip tip="Identity Provider (IdP): Service that stores and manages digital identities." cta="View Glossary" href="/docs/glossary?term=Identity+Provider">Identity Provider</Tooltip> and Auth0 SAML Federation and Delegation for AWS.

You will see two ways of implementing this flow:

1. Using Auth0 Delegation with AWS IAM;
2. Adding an identity token to flow identity to the Lambda function.

Delegation makes it easy for you to obtain tokens from AWS to access AWS services in your application.

### Ways to Secure the Amazon API Gateway

AWS API Gateway provides several different methods to secure your APIs:

1. API keys;
2. IAM;
3. [Amazon Cognito](/docs/customize/integrations/aws/aws-api-gateway-cognito).

Using API keys is typically appropriate for a service-to-service interaction, as illustrated below. However, there are several downsides to this approach:

* Placing a secret with a long lifetime on the application is risky (applications are easier to compromise);
* Creating a framework to issue and manage API keys requires a secure implementation that can be challenging to develop.

This section of the tutorial will utilize IAM roles and policies to secure your API in API Gateway, but you can also choose to do so using user pools in Amazon Cognito. To review detailed instructions on securing your AWS API, read [Secure AWS API Gateway Using Cognito](/docs/customize/integrations/aws/aws-api-gateway-cognito). For more information on using IAM roles and policies, read the Amazon article, [Control access to an API with IAM permissions](http://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html). To read more about user pools in Cognito, visit [Amazon Cognit user pool](http://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html).

### Step 1. Configure IAM and Auth0 for SAML Integration with the API Gateway

You can specify an AWS IAM role for the SAML token you exchange for an AWS token. Depending on the permissions granted to that IAM role (which are set using your identity provider), the received token possesses those same permissions. By issuing different SAML tokens, each with its own AWS IAM role, you can control the levels of access for your users.

For example, the IDP could specify the IAM role based on group membership (for example, an administrator in Active Directory) or authentication source (for example, a database connection or a social provider like Facebook). This approach lets you differentiate user access to your Amazon API Gateway methods when secured using AWS IAM.

#### Configure Auth0

Log in to your Auth0 account. You will be brought to the Management Dashboard. Click on **+ New Application**, which is located in the top right corner of the page.

Name your new application AWS API Gateway, and indicate that this Application is going to be a Single-Page Application. Click **Create**.

Navigate to the Addons tab for your newly-created Application. Using the appropriate slide, enable Amazon Web Services. This turns on AWS Delegation.

#### Configure AWS

Follow the [How to Set Up AWS for Delegated Authentication](/docs/customize/integrations/aws/how-to-set-up-aws-for-delegated-authentication) tutorial to configure AWS for delegated access, which uses SAML. Some caveats:

* Follow the [instructions below](#setting-the-permissions-policy-on-your-iws-iam-role) for attaching the permissions policy to your role instead of the one for the linked tutorial;
* Name the SAML provider you create `auth0`;
* Name the AWS IAM role `auth0-api-role`.

##### Set the Permissions Policy on Your IWS IAM Role

Once you have configured the AWS IAM role, you will add a policy to `auth0-api-role` that lets you execute your API Gateway methods. For more information on this process, please see [User Access Permissions for Amazon API Gateway](http://docs.aws.amazon.com/apigateway/latest/developerguide/permissions.html).

#### Getting the Gateway API ARN

Before you begin, you will need the ARN for your Gateway API:

1. Navigate to [Amazon API Gateway Console](https://console.aws.amazon.com/apigateway) and log in.
2. Select the appropriate API.
3. Click on any of the Methods associated with the API to bring up the Method Execution page.
4. On the Method Execution page, the Method Request box in the top left corner displays the **ARN** for the API, though it includes the Method name:

`arn:aws:execute-api:us-east-2:484857107747:97i1dwv0j4/*/POST/`

You'll strip the method name to get the base ARN for the API:

`arn:aws:execute-api:us-east-2:484857107747:97i1dwv0j4/*`

The wildcard (`*`) in the ARN above enables permissions to your API for all stages, but you can deploy different stages individually (for example, development, then test, then production).

Select the `auth0-api-role` role you just created to open its Summary page.

Expand **Inline Policies**, and click **click here**.

Select **Custom Policy** and click **Select**.

Edit your policy document. You can set the **Policy Name** to whatever you would like, but we suggest something like `api-gateway-policy`. To enable access to the API methods for this role, apply the following policy after updating the ARN with the one for your API.

```json lines theme={null}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "execute-api:*"
            ],
            "Resource": [
                "arn:[{yourArn}]"
            ]
        }
    ]
}
```

Click **Apply Policy**.

Since the API Gateway will assume this role on behalf of the user, the trust policy needs to permit this action. To do so, edit the role's Trust Relationships by navigating to this tab on the role's Summary page.

The final trust relationship should look similar to the following:

export const codeExample = `{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "auth0",
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::012345670:saml-provider/auth0-api"
      },
      "Action": "sts:AssumeRoleWithSAML",
      "Condition": {
        "StringEquals": {
          "SAML:iss": "urn:{yourDomain}"
        }
      }
    },
    {
      "Sid": "gateway",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}`;

<AuthCodeBlock children={codeExample} language="json" />

At this point, you will need to set the Authorization Settings on the [API Gateway](https://console.aws.amazon.com/apigateway).

In the **Resources** view, select the POST method under `/pets`.

Click the **Method Request** link.

Click the edit icon beside the **Authorization Type**, and select AWS\_IAM. Now click the **Check Button** beside the field to save the setting.

### Step 2. Set Up CORS and Deploy the API

Our Single-Page Application (SPA) will access web API methods from a domain different from that of the page. The Cross-Origin Resource Sharing setting needs to explicitly permit this action for the browser to allow access to the AWS API Gateway. Typically, the browser will first issue an `OPTIONS` request to see what actions the site will permit.

Select `/pets` under Resources, and click **Create Method**. In the drop-down, select **OPTIONS**, and click the **checkmark** to save the setting.

The Options method is used by the browser to get the necessary HTTP headers, but the function needs further instructions on what to do. Under the `OPTIONS` Setup screen, set the following variables/parameters:

* **Integration Type**: Lambda Function;
* **Use Lambda Proxy Integration**: leave unchecked;
* **Lambda Region**: select your region;
* **Lambda Function**: NoOp.

Click **Save**. On the next pop-up screen, grant your Lambda function the permissions it needs.

You will then be auto-directed to the `OPTIONS` Method Execution page. Open the Method Response page.

Expand the **200** section located under the HTTP Status bar and add the following response headers:

* Access-Control-Allow-Headers;
* Access-Control-Allow-Methods;
* Access-Control-Allow-Origin.

Next, map the appropriate values to each of the response headers. After returning to the Method Execution page, click on **Integration Response**. After expanding the row associated with the **200** method response status, expand the **Header Mappings**, and apply the following mappings:

* Access-Control-Allow-Headers: `'Content-Type,X-Amz-Date,Authorization,x-api-key,x-amz-security-token'`;
* Access-Control-Allow-Origin: `'*'`
* Access-Control-Allow-Methods: `'POST, GET, OPTIONS'`

Finally, repeat the above steps to enable CORS for the POST and GET methods. However, for these two methods, you will add one header, Access-Control-Allow-Origin, and its value should be set to `'*'`.

### Deploy the API

Return to the **Resources** view for your API. Click on **Actions**, and select **DEPLOY API**.

Select **New Stage** for Deploy State, and name the stage `Test`. Click the **Deploy** button.

On the result page, navigate to **SDK Generation**. Select JavaScript as the **Platform**. Click the **Generate SDK** button.

Save the downloaded zip file for later use.
