Auth0 カスタムオーソライザーを使用してAWS API Gateway Endpointへセキュアにアクセスする (2/2)

###パート1(1/2)は[こちら](https://qiita.com/furuth/items/a36650c35e9540be7d84)
このブログは、Auth0のSecure [AWS API Gateway Endpoints Using Custom Authorizer](https://auth0.com/docs/integrations/aws-api-gateway/custom-authorizers)を日本語化したものです(英語版のPart 3 およびPart 4の内容です)。
本ブログは２部構成になっています。パート１をまだ読んでいない方は、はじめに[パート１](https://qiita.com/furuth/items/a36650c35e9540be7d84)を読んでいただくことをお薦めいたします。

##3. カスタムオーソライザーを作成する

チュートリアルの1章では、Auth0をAPI Gatewayと連携するための設定方法を説明しました。２章ではAmazon Web Services (AWS) API Gatewayを使用してAPIをインポート、テスト、およびデプロイする方法を紹介しました。3章では、適切な権限を持つユーザーのみがAPIのバックエンドにアクセスできるように、このAPIを保護する方法を説明します。


これを実行するために、API Gatewayのカスタム [リクエスト] オーソライザーを使用します。これによりOAuth 2.0やSAMLなどbearerトークン認可戦略を用いてAPI認可を行うことが可能になります。リクエストを受信するたびに、以下の処理が行われます：

1. API Gatewayは適切に構成されたカスタムオーソライザーを確認します。
2. API GatewayはAuthorizationトークンを使用して(Lambda関数の機能により)カスタムオーソライザーを呼び出します。
3. Authorizationトークンが正当な場合、カスタムオーソライザーは適切なAWS Identity and Access Management (IAM) ポリシーを返します。
4. API Gateway はリクエストを認可するために手順3で返されたポリシーを使用します。

## カスタムオーソライザーを準備する

Auth0が発行したトークンをサポートする[サンプル カスタムオーソライザーをダウンロード](https://github.com/auth0-samples/jwt-rsa-aws-custom-authorizer)します。その後、あなたの環境でカスタムオーソライザーが動作するためにファイルをカスタマイズする必要があります。

1. 指定したフォルダにダウンロードされたサンプルファイルを解凍し、コマンドラインを使用して該当フォルダに移動します。

2. サンプルフォルダの中で、デプロイに必要なNode.jsパッケージをインストールするために、`npm install`を実行します。後の手順でAWSにアップロードをしますが、AWSはバンドルされているファイルを含めた、これらのファイルを必要とします。

3. `.env`ファイルにローカル環境変数を定義します。`cp .env.sample .env`を実行することで、`.env.sample`ファイルを`.env`ファイルへコピー(すると同時にリネーム)することができます。以下の変更を行います:

|パラメーター|値|
|:---:|:---|
| **`TOKEN_ISSUER`** | トークンの発行者。Auth0がトークンの発行者の場合、`https://${account.namespace}/`を定義します。|
| **`JWKS_URI`** | JWKSエンドポイントのURL。Auth0がトークンの発行者の場合、`https://${account.namespace}/.well-known/jwks.json`を定義します。|
| **`AUDIENCE`** | 第１章で作成されたAPIの**Audience**の値|

※ ${account.namespace}は、あなたのAuth0ドメインです。

例えば、定義が完了すると.envファイルは以下のようなテキストになります:

```text
JWKS_URI=https://hfurutaau.au.auth0.com/.well-known/jwks.json
AUDIENCE=hVG7...3QA1q
TOKEN_ISSUER=https://hfurutaau.au.auth0.com/
```


4. ローカルでカスタムオーソライザーをテストします。

a. はじめに、正当なJWT Access Tokenを取得します。JWT Access Tokenを取得する方法は複数あり、選択する方法はクライアントのタイプ、信頼レベル、または全体的なエンドユーザーエクスペリエンスによって異なります。 
API用のテスト トークンはAuth0 [ダッシュボード](${manage_url}/#/apis)の **APIs　> 作成したAPI > Test** から入手できます。詳細については [Access Tokenの入手方法](/tokens/access-token#how-to-get-an-access-token)を参照してください。

b. ローカルにトークン情報を含んだ`event.json`ファイルを作成します。サンプルファイルからコピーすることができます(コマンドラインから `cp event.json.sample event.json` を実行)。 `ACCESS_TOKEN`に手順a.で入手したJWTトークン, `methodArn`に　APIの`GET`メソッドにある適切なARNの値で置き換えてください。

`methodArn`の値を入手するには:

1. AWS API Gatewayコンソールで、**PetStore** APIを開きます。
2. 左側のナビゲーションパネルにある、**リソース** をクリックします。
3. 中央の **リソース** パネルで、 リソースツリーを展開し、`/pets`の下にある**GET**をクリックします。
4. **メソッドリクエスト**ボックスの中に、**ARN**があるのを確認できます。

c. `npm test`を実行してテストを行います。ここでは[lambda-local](https://www.npmjs.com/package/lambda-local)パッケージを使用して、カスタムオーソライザーのテストします。テストが成功した場合は、次のような文字列が出力されます:

```text
Message
------
{
    "principalId": "C8npTEMVnBrILsBTI91MOh6dfuZbPVAU@clients",
    "policyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "execute-api:Invoke",
                "Effect": "Allow",
                "Resource": "arn:aws:execute-api:us-east-1:1234567890:apiId/stage/method/resourcePath"
            }
        ]
    },
    "context": {
        "scope": "FULL_LIST_OF_SCOPES"
    }
}
```

`Effect`の値が`Allow`の場合、カスタムオーソライザーはAPI Gatewayを呼び出すことが許可されます。

## IAMロールの作成

IAMロールには、Lambda関数を呼び出すために必要な権限があります。カスタムオーソライザーを実行する前に、API Gatewayがアクセスリクエストを受け取るたびにカスタムオーソライザーを呼び出すことができるIAMロールを作成する必要があります。

1.AWSにログインし、[IAM Console](https://console.aws.amazon.com/iam)にアクセスし、画面左側のナビゲーションバーから**ロール**をクリックします。

2.**ロールの作成**をクリックします。

![スクリーンショット 2018-03-01 23.13.05.png](https://qiita-image-store.s3.amazonaws.com/0/189613/14c966b6-47cd-a717-200c-c28ae434aa52.png)

3.**AWS サービス**　ロールを選択し、その下にある、**AWS Lambda** をクリックしたのち、画面下にある **次のステップ：アクセス権限**ボタンをクリックします。

4.**アクセス権限ポリシーをアタッチする** 画面で、**AWSLambdaRole**を選択します (たくさんのポリシーが表示されているのでフィルターを使用して検索することをお勧めします)。**AWSLambdaRole**の左側にあるチェックボックスをOnにしてから **次のステップ:確認**をクリックします。

![スクリーンショット 2018-03-01 23.20.41.png](https://qiita-image-store.s3.amazonaws.com/0/189613/eb59f28b-12e3-8208-b18b-0143898d9b65.png)

5.**ロールの作成：確認**画面で、**ロール名**を入力します（ 例えば `Auth0Integration` )。その他の項目はそのままにして、**ロールの作成**をクリックします。

![スクリーンショット 2018-03-01 23.22.43.png](https://qiita-image-store.s3.amazonaws.com/0/189613/0d63989f-16bb-519a-3801-a96527c3ac43.png)

6.AWSがロールの作成を完了すると、IAMの**ロール**ページにリダイレクトされます。作成されたロールをクリックしてください。

![スクリーンショット 2018-03-01 23.24.06.png](https://qiita-image-store.s3.amazonaws.com/0/189613/13b99a17-f2e7-9417-a5ff-2af4488f59b2.png)

7.作成したロールの**概要**ページで、**信頼関係**タブをクリックします。

![スクリーンショット 2018-03-01 23.26.02.png](https://qiita-image-store.s3.amazonaws.com/0/189613/b0e09d57-53f2-39c3-ad34-36668709f152.png)

8.**信頼関係の編集**をクリックし、**ポリシードキュメント**フィールドに以下のJSON snippetを追加してください。:

    ```json
    {
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Principal": {
            "Service": [
            "apigateway.amazonaws.com",
            "lambda.amazonaws.com"
            ]
        },
        "Action": "sts:AssumeRole"
        }
    ]
    }
    ```

  ![スクリーンショット 2018-03-01 23.28.12.png](https://qiita-image-store.s3.amazonaws.com/0/189613/f7ee2811-02a1-77ba-9051-28e9f0fefddd.png)


**信頼ポリシーの更新**をクリックします。

9 ロールの**概要**ページにリダイレクトされます。後ほど使用するので、画面上に記載されている**ロールARN**の値をコピーしておいてください。

![スクリーンショット 2018-03-01 23.30.53.png](https://qiita-image-store.s3.amazonaws.com/0/189613/fbbe0f3a-e666-9409-385d-ed30be355e00.png)

## Lambda関数の作成 および カスタムオーソライザーのデプロイ

これまでカスタムオーソライザーをあなたの環境用に構成し、テストを通して動作することを確認してきました。つづいてAWSにカスタムオーソライザーをデプロイします。

1.はじめに、コマンドラインから`npm run bundle`を実行してAWSにアップロードするためのバンドルを作成する必要があります。このコマンドを実行すると、AWS Lambdaに必要なソース、構成ファイル、node modulesを含んだ`custom-authorizer.zip'が生成されます。

2.[Lambdaコンソール](https://console.aws.amazon.com/lambda)に移動し、**関数の作成**をクリックします。

![スクリーンショット 2018-03-01 23.41.11.png](https://qiita-image-store.s3.amazonaws.com/0/189613/350051b7-50d0-0026-9f68-b33c33a90e1b.png)

3.**関数の作成** ページで、**一から作成**　をクリックします。

4.**一から作成** オプション画面で、Lambda関数の作成に必要な以下の情報を登録します(Lambda関数設定画面の**基本設定**に記載される内容です)。登録が完了したら**関数の作成**をクリックします:

| **Parameter** | **Value** |
|:---|:---|
| **名前** | Lambda関数の名前。例えば `jwtRsaCustomAuthorizer` |
| **ランタイム** | `Node.js 4.3`を選択 |
| **ロール** | `既存のロールを選択`を選択 |
| **既存のロール** | さきに作ったロールを選択 `Auth0Integration` |

![スクリーンショット 2018-03-01 23.44.12.png](https://qiita-image-store.s3.amazonaws.com/0/189613/3b4b7ea2-bf83-6359-bcb8-46d4328ab045.png)

a. つづいて、関数コードを登録します。**コードエントリ タイプ**から**.ZIPファイルをアップロード**を選択し、**アップロード**をクリックします。ファイル選択画面が表示されるので、先ほど作成した`custom-authorizer.zip`バンドルを選択します。

b. それから、以下の３つの内容を**環境変数**に登録します。これらの内容は`.env`ファイルに記載した内容と同一のものを登録します：

| **Parameter** | **Value** |
|:---|:---|
| **`TOKEN_ISSUER`** | トークンの発行者。Auth0がトークンの発行者の場合、`https://${account.namespace}/`を定義します。 |
| **`JWKS_URI`** | JWKSエンドポイントのURL。Auth0がトークンの発行者の場合、`https://${account.namespace}/.well-known/jwks.json`を定義します。|
| **`AUDIENCE`** | 第１章で作成されたAPIの**Audience**の値 |

c. **関数コードのハンドラ** および **実行ロール**には以下の値を設定します:

| **パラメーター** | **値** |
|:---|:---|
| **ハンドラ** | `index.handler` |
| **実行ロール** | `既存のロールを選択` |
| **Existing role** | さきに作ったロールを選択 `Auth0Integration`  |  

d. **基本設定** で、**タイムアウト**　を**30**秒に設定します。

上記の内容の登録が完了しましたら、**保存**をクリックします。

AWSが関数の作成を完了すると、以下のような画面が表示されます。

![スクリーンショット 2018-03-01 23.59.50.png](https://qiita-image-store.s3.amazonaws.com/0/189613/0fffc0f2-4c90-561a-4177-cbde9907b969.png)

6.作成したLambda関数をテストします。画面右上にある**テスト**をクリックします。

7.`event.json`ファイルの内容を、JSON形式で**テストイベントの設定**画面にコピーします。 

![スクリーンショット 2018-03-02 0.29.53.png](https://qiita-image-store.s3.amazonaws.com/0/189613/f594588a-174a-294d-20b7-939007d71ff8.png)

**保存 (もしくは作成)**をクリックして**テスト＊＊をクリックします。 テストが成功した場合には、以下のような画面が表示されます。

![スクリーンショット 2018-03-02 0.27.19.png](https://qiita-image-store.s3.amazonaws.com/0/189613/2a3afe04-66dc-2701-7503-54b6edd2683b.png)

詳細情報を開くと、ローカルテストで成功した時と同様のメッセージが表示されているのが確認できます。

![スクリーンショット 2018-03-02 0.30.53.png](https://qiita-image-store.s3.amazonaws.com/0/189613/5adb208a-95aa-5057-bc30-f1c31eb03aa6.png)

## API Gatewayカスタムオーソライザーの構成

API Gatewayコンソールに戻ります。

![スクリーンショット 2018-03-02 0.32.25.png](https://qiita-image-store.s3.amazonaws.com/0/189613/5f5a373e-fb90-1c8c-d1b2-8511663b5110.png)

まえに作成した**PetStore**を開きます。

![スクリーンショット 2018-03-02 0.34.07.png](https://qiita-image-store.s3.amazonaws.com/0/189613/9ca34ca5-bfe1-d565-fc63-880c4710d5f0.png)

画面左のナビゲーションバーから**オーソライザー**を開きます。初めてオーソライザーを作成した場合、デフォルトで**オーソライザーの作成**設定画面が表示されます。そうでない場合には、画面中央の**新しいオーソライザーの作成**をクリックして、この画面を表示することができます。

![](/media/articles/integrations/aws-api-gateway-2/part-2/pt2-23.png)

以下のパラメーターを定義してください:

| **パラメーター** | **値** |
|:---|:---|
| **Lambda リージョン** | 以前作成したLambda関数のリージョンを指定します |
| **Lambda 関数** | `jwtRsaCustomAuthorizer` |
| **名前** | `jwt-rsa-custom-authorizer` |
| **Lambda 実行ロール** | 先にコピーしたIAMロールのARN|
| **トークンのソース** | `Authorization` |
| **トークンの検証** | `^Bearer [-0-9a-zA-z\.]*$` |
| **TTL (seconds)** | `3600` |

![スクリーンショット 2018-03-02 0.39.08.png](https://qiita-image-store.s3.amazonaws.com/0/189613/b36ae779-f055-b47b-de63-0822a6b07483.png)

 **作成**をクリックします。

AWSがオーソライザーを作成し、ページが更新されると、オーソライザー画面の一番下に**テスト**が表示されます。**テスト**をクリックすると、**認証トークン**を入力するポップアップが表示されます。以前に使用したAuth0トークン (`Bearer ey... `)を入力し、**テスト**をクリックすることで、オーソライザーのテストをすることができます。

![スクリーンショット 2018-03-02 0.43.58.png](https://qiita-image-store.s3.amazonaws.com/0/189613/1d8aa293-1940-0fbd-4083-18c172ae17d4.png)

テストが成功した場合、以下のようなレスポンスが表示されます。

![スクリーンショット 2018-03-02 0.44.41.png](https://qiita-image-store.s3.amazonaws.com/0/189613/b84aba2e-f195-4c83-92d7-8bad2700165e.png)

## まとめ

API Gatewayチュートリアル　第3章では、アクセス要求を処理するカスタムオーソライザーの構成を行いました。これを行うには、次のようにします：

1. Auth0サンプルを使用して、Lambda関数によって使用されるコードを含むバンドルを準備します
2. Lambda関数を呼びだるIAMロールを作成します
3. 手順1で作成したカスタムバンドルを使用するLambda関数を作成します
4. 手順3で作成したLambda関数を使用するAPI Gatewayカスタムオーソライザーを作成します

第4章では、作成したカスタムオーソライザーを実際に使ってみます。

# 4: カスタムオーソライザーを使用してAPIを保護する

第１章ではAPI Gatewayで使用するAuth0の構成をしました。第２章ではAPI Gatewayを使用してAPIを構成しました。第３章ではAPIがアクセスリクエストを受け取った際に、適切なポリシーを検索できるようにカスタムオーソライザーを構成しました。本章ではどのようにAPIエンドポイントを保護するためのカスタムオーソライザーの使用方法を説明します。

## カスタムオーソライザーを使用するためにAPI Gatewayリソースを構成する

AWSにログインし、[API Gatewayコンソール](http://console.aws.amazon.com/apigateway)に移動します。

![スクリーンショット 2018-03-02 1.05.55.png](https://qiita-image-store.s3.amazonaws.com/0/189613/44532e1c-3b70-ec43-9c29-45aa1602e63b.png)

`注意:
カスタムオーソライザーは、メソッドごとにメソッドに設定されます。１つのオーソライザーで複数のメソッドを保護したい場合は、各メソッドに対して次の手順を繰り返す必要があります。
`

２章で作成した**PetStore** APIを開きます。画面中央の**リソース** ツリーから、`/pets`リソースの**GET**メソッドを選択します。

![スクリーンショット 2018-03-02 1.07.38.png](https://qiita-image-store.s3.amazonaws.com/0/189613/ac5f3351-d2f2-e6dd-94a3-3cba8d55c1d2.png)

**メソッドリクエスト**を選択します。

![スクリーンショット 2018-03-02 1.08.32.png](https://qiita-image-store.s3.amazonaws.com/0/189613/2804500d-285c-e509-5eb5-44cb43ce3471.png)

**設定**画面で、**認証**の右側にある**ペン**アイコンをクリックし、３章で作成したカスタムオーソライザー`jwt-rsa-custom-authorizer`を選択します。

![スクリーンショット 2018-03-02 1.09.52.png](https://qiita-image-store.s3.amazonaws.com/0/189613/7413c784-77c4-0cb3-0924-28e26a05f17d.png)

選択したカスタムオーソライザーの横にある、**チェックマーク**をクリックして保存します。**APIキーの必要性**は、確実に`false`になっていることを確認してください。

![スクリーンショット 2018-03-02 1.10.52.png](https://qiita-image-store.s3.amazonaws.com/0/189613/6261b839-f4af-0bea-9a69-8aed413c8373.png)


## APIのデプロイ

変更内容を公開するには、２章で行った**APIのデプロイ**をする必要があります。

デプロイが成功すると、**Testステージエディター**にリダイレクトされます。画面一番上の青いバナーに**URLの呼び出し**が記載されているので、URLの情報をコピーしておいてください。デプロイしたAPIのテストをする際に必要となります。

![スクリーンショット 2018-03-02 1.12.28.png](https://qiita-image-store.s3.amazonaws.com/0/189613/b26f3807-217a-2f50-6170-af491942285c.png)

## デプロイしたAPIのテスト

上記手順でコピーした、GETコールにある**URLの呼び出し**を使用して、デプロイしたAPIのテストができます。

```text
curl --request GET \
  --url https://your_invoke_url/pets
```

## まとめ

このチュートリアルで、以下のことを学習いたしました。

1. API Gatewayを使用するためにAuth0を構成
2. API Gatewayを使用するためにAPIをインポート
3. AWS IAMおよびLambdaと一緒に動作することが必要なAPIエンドポイントをセキュアにするためのカスタムオーソライザーの作成
4. カスタムオーソライザーを使用してAPIを保護