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

# AWS API Gatewayチュートリアルの手順5

> Amazon API Gatewayチュートリアルの手順5

<Warning>
  この機能は委任を使用します。2017年6月8日より、アドオンを使用していないテナントでは、デフォルトで委任が無効になります。委任を必要とするアドオンを使用中のレガシーテナントは、引き続きこの機能を使用できます。今後、委任機能が変更されるか、サービスから削除されることがあれば、使用中のお客様が余裕を持って移行できるよう、あらかじめお知らせします。また、委任はカスタムドメインの使用をサポートしていないため、委任に依存する機能をカスタムドメインと共に使うとうまく機能しない可能性があります。
</Warning>

## 手順5 - IDフローにIDトークンを使用する

この最後の手順では以下を行います。

* <Tooltip data-tooltip-id="react-containers-DefinitionTooltip-0" href="/docs/ja-jp/glossary?term=openid" tip="OpenID: アプリケーションがログイン情報を収集および保存することなくにユーザーのIDを検証できるようにする認証用のオープン標準。" cta="用語集の表示">OpenID</Tooltip>の<Tooltip data-tooltip-id="react-containers-DefinitionTooltip-2" href="/docs/ja-jp/glossary?term=json-web-token" tip="JSON Web Token（JWT）: 二者間のクレームを安全に表現するために使用される標準IDトークン形式（および多くの場合、アクセストークン形式）。" cta="用語集の表示">JSON Web Token</Tooltip>（JWT）を渡して、サービスへIDを送る
* トークンを検証する
* プロファイル情報を抽出して、ペットの購入者を割り当てる

## IDトークンを使用する

ユーザーに関する情報の処理や取得には、Lambda関数を使用することができます。たとえば、購入トランザクション中に、IDトークンで返されたプロファイルからユーザー名を取得したとします。その際に、JSON Web Token（JWT）であるID自体に埋め込まれたユーザーの情報も取得することができます。

JWTの使用する利点は、以下を行えることです。

1. JWTの真正性を検証する
2. 呼び出しを行っているユーザーが認証されることを確実にする（改ざんの可能性があるプレーンテキストのパラメーターに依存しない）

その他にも、認可にJWTを使用して、Amazon API GatewayとのIAM統合を迂回することができます。認可にAPI Gatewayを使用すると、Lambda関数を呼び出す前にAPIの呼び出しを止められることに注意してください。

### JWTに情報を追加する

JWTにユーザー情報を追加するには、いくつかの方法があります。以下の例では、ユーザーのメールアドレスをJWTに追加していますが、概念は他のユーザーのデータポイントについても同じです。

#### ルールを使用する

ユーザーのメールアドレスをJWTに追加する方法の1つが、[ルール](/docs/ja-jp/rules)です。この方法は、値がユーザー認証用のJWTで常に利用可能なことを確実にしたい場合には適切です。

`login.js`では、`auth.signin`に渡されるパラメーターにこのスコープが指定されているのを確認できます。

```javascript lines theme={null}
$scope.login = function() {
    var params = {
        authParams: {
          scope: 'openid email'
        }
      };

    auth.signin(params, function(profile, token) {
      ...
    }
  }
```

JWTにはユーザーのプロファイル全体を含めることもできますが、JWTは通常すべての要求で渡されるため、必要なものだけを含めるようにします。

## JWTトークンを検証する

AWS Lambdaコンソールは、ブラウザーコンソールでNode.jsコードを入力する際に、限られた数のノードモジュールにのみアクセスするため、IDトークンを処理するパッケージとして追加でモジュールをインクルードして、Lambda関数をアップロードする必要があります。

詳細については、「[Node.jsを使って導入パッケージを作成する](http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html)」と「[導入パッケージをアップロードしてテストする](http://docs.aws.amazon.com/lambda/latest/dg/walkthrough-s3-events-adminuser-create-test-function-upload-zip-test.html)」をご覧ください。

以下のシードプロジェクトには、更新されたAWS Lambda関数に必要なコードが含まれています。

シードプロジェクト内には、以下の2つのカスタムJavaScriptファイルがあります。

* `index.js`：メインコードが含まれています。
* `auth0-variables`：更新する必要のあるコードが含まれています。

カスタムファイルに加えて、Node.jsに標準の`package.json`ファイルがあります。

コードは、JWTから情報を抽出して、JWTを検証するために機能性を追加します。Auth0はデフォルトで対称キーを使用しますが、非対称キーの使用を選ぶこともできます（サードパーティがトークンを検証可能にする必要がある場合には、非対称キーを使用して、公開鍵だけを共有します）。

トークン検証の詳細については、「[Auth0が対応しているIDプロトコル](/docs/ja-jp/authenticate/protocols)」をご覧ください。

秘密鍵で`auth0-variables.js`を更新します。秘密鍵は、<Tooltip data-tooltip-id="react-containers-DefinitionTooltip-0" href="/docs/ja-jp/glossary?term=auth0-dashboard" tip="Auth0 Dashboard: サービスを構成するためのAuth0の主製品。" cta="用語集の表示">Auth0 Dashboard</Tooltip>にある［Application（アプリケーション）］の［Settings（設定）］タブに表示されます。

```javascript lines theme={null}
var env={};
env.AUTH0_SECRET='{yourAuth0Secret}';
module.exports = env;
```

ファイルのあるディレクトリから **npm install** を実行して、内容をZIP形式で圧縮し（`index.js`は必ずZIPのルート）、Lambda関数の`PurchasePet`が使えるようにアップロードします。これをテストすると、JWTがメッセージの本文にないため、認証が失敗します。

`index.js`でロジックを確認します。60行目辺りのロジックではトークンが検証して解読され、購入ロジックで使われるID情報が含まれた、デコードされた情報が抽出されています。

```javascript lines theme={null}
if(event.authToken) {
     jwt.verify(event.authToken, secret, function(err, decoded) {
         if(err) {
           console.log('failed jwt verify: ', err, 'auth: ', event.authToken);
           context.done('authorization failure', null);
         } else if(!decoded.email)
         {
           console.log('err, email missing in jwt', 'jwt: ', decoded);
           context.done('authorization failure', null);
         } else {
           userEmail = decoded.email;
           console.log('authorized, petId', petId, 'userEmail:', userEmail);
           dynamo.getItem({TableName:"Pets", Key:{username:"default"}}, readcb);
         }
     });
  } else {
     console.log('invalid authorization token', event.authToken);
     context.done('authorization failure', null);
  }
    ...
```

### プロファイル情報を抽出して購入者を割り当てる

最後の手順では、JWTをブラウザーのクライアントが使用するメソッドに渡します。

標準のメソッドには`Authorization`ヘッダーがBearerトークンとして含まれており、このメソッドを使用するには、IAM認証を無効にして、認証にOpenIDのトークンだけを使用する必要があります（AWS Lambda関数に渡すイベントデータにAuthorizationヘッダーをマッピングすることも必要です）。

ところが、IAMを使用している場合、AWS API Gatewayは`Authorization`ヘッダーにメッセージの署名を含んでいるため、このヘッダーにJWTを書き込むと認証が破壊されます。これは以下のいずれかの方法で対処します。

* JWTのためにカスタムヘッダーを追加する
* メッセージの本文にカスタムヘッダーを入れる

カスタムヘッダーの使用を選んだ場合には、`pets/purchase`のPOSTメソッドの統合要求に何らかのマッピングを行う必要があります。

検証プロセスを続けるために、AWS Lambda関数へのPOSTの本文でJWTを渡します。これを行うには、以下のように、本文から`userName`を削除して、`authToken`を追加することで、`home.js`で`buyPet`メソッドを更新します。

```javascript lines theme={null}
function buyPet(user, id) {
    var apigClient = getSecureApiClient();
    var body = {
      petId:id,
      authToken: store.get('token')
    };

    apigClient.petsPurchasePost({}, body)
      .then(function(response) {
        console.log(response);
        $scope.pets = response.data;
        $scope.$apply();
      }).catch(function (response) {
        alert('buy pets failed');
        showError(response);
    });
}
```

S3のバケットにコードをアップロードして、ペットを購入しようとしてみてください。出力のメッセージに購入者のメールアドレスが表示されているはずです。

エラーがあった場合には、秘密鍵を正しく設定したことを確認してください。トークンのデコードの問題を確認する便利なツールの1つが、[jwt.io](http://jwt.io/)です。

## Summary（概要）

このチュートリアルでは、以下について説明されています。

* AWS Lamdba関数を用いたメソッドなど、AWS API Gatewayを使ってAPIを作成する
* IAMロールを使ってAPIへのアクセスを保護する
* APIへのアクセスをユーザーベースと結び付けて、<Tooltip data-tooltip-id="react-containers-DefinitionTooltip-1" href="/docs/ja-jp/glossary?term=security-assertion-markup-language" tip="Security Assertion Markup Language（SAML）: パスワードなしに二者間で認証情報を交換できる標準化プロトコル。" cta="用語集の表示">SAML</Tooltip> IDプロバイダーとIAMを統合する
* ユーザーがデータベース接続か、ソーシャル接続かを基にして、異なるレベルのアクセスを提供する
* Auth0を使ってロールの割り当てを強制する
* JWTを使ってより細かな認証コンテキストを提供し、ID情報を適切なLambda関数に渡す
