

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# JSON ウェブトークンの検証
<a name="amazon-cognito-user-pools-using-tokens-verifying-a-jwt"></a>

JSON ウェブトークン (JWT)は、簡単にデコード、読み取り、変更ができます。アクセストークンが変更されると、権限エスカレーションのリスクが発生します。ID トークンを変更すると、偽装リスクが発生します。アプリケーションはユーザープールをトークン発行者として信頼していますが、ユーザーが転送中のトークンを妨害した場合はどうなりますか？ アプリケーションが Amazon Cognito が発行したトークンと同じトークンを受信していることを確認する必要があります。

Amazon Cognito は、OpenID Connect (OIDC) 仕様の整合性と機密性の一部を使用するトークンを発行します。ユーザープールトークンは、有効期限、発行者、デジタル署名などのオブジェクトの有効性を示します。`.` 区切りの JWT の 3 番目で最後のセグメントである署名は、トークン検証の主要なコンポーネントです。悪意のあるユーザーがトークンを変更することがありますが、アプリケーションがパブリックキーを取得して署名を比較すれば、トークンは一致しなくなります。OIDC 認証から JWT を処理するアプリケーションは、サインインごとにこの検証オペレーションを実行する必要があります。

このページでは、一般的かつ特定的な JWT の認証を推奨します。アプリケーション開発は、さまざまなプログラミング言語とプラットフォームに及びます。Amazon Cognito は OIDC をパブリック仕様に十分近い方法で実装するため、任意のデベロッパー環境の信頼できる JWT ライブラリで検証要件を処理できます。

これらのステップでは、ユーザープール JSON Web トークン (JWT) の検証を説明します。

**Topics**
+ [前提条件](#amazon-cognito-user-pools-using-tokens-prerequisites)
+ [aws-jwt-verify によるトークンの検証](#amazon-cognito-user-pools-using-tokens-aws-jwt-verify)
+ [トークンの理解と検査](#amazon-cognito-user-pools-using-tokens-manually-inspect)

## 前提条件
<a name="amazon-cognito-user-pools-using-tokens-prerequisites"></a>

このセクションのタスクは、ライブラリ、SDK、またはソフトウェアフレームワークで既に処理されている可能性があります。 AWS SDKsは、アプリで Amazon Cognito ユーザープールトークンの処理と管理のためのツールを提供します。 AWS Amplify には、Amazon Cognito トークンを取得および更新する関数が含まれています。

詳細については、次のページを参照してください。
+ [Amazon Cognito の認証と認可を、ウェブアプリケーションとモバイルアプリケーションに統合する](cognito-integrate-apps.md)
+ [SDK を使用した Amazon Cognito ID プロバイダーのコード例 AWS SDKs](https://docs.aws.amazon.com/cognito/latest/developerguide/service_code_examples.html)
+ *Amplify Dev Center* の[高度なワークフロー](https://docs.amplify.aws/lib/auth/advanced/q/platform/js/#retrieve-jwt-tokens)

JSON ウェブトークン (JWT) のデコードと検証用として、多数のライブラリが用意されています。サーバー側の API 処理用にトークンを手動で処理する場合、または他のプログラミング言語を使用している場合は、これらのライブラリが役に立ちます。「[OpenID foundation の JWT トークンでの作業のためのライブラリのリスト](http://openid.net/developers/jwt/)」を参照してください。

## aws-jwt-verify によるトークンの検証
<a name="amazon-cognito-user-pools-using-tokens-aws-jwt-verify"></a>

Node.js アプリでは、 は、ユーザーがアプリに渡すトークンのパラメータを検証するために[aws-jwt-verifyライブラリ](https://github.com/awslabs/aws-jwt-verify) AWS を推奨します。`aws-jwt-verify` を使用すると、1 つ以上のユーザープールについて検証したいクレーム値を `CognitoJwtVerifier` に入力できます。確認できる値には次のものがあります。
+ アクセストークンや ID トークンの形式が不正ではなく、期限切れでもなく、有効な署名が付いているもの。
+ アクセストークンが、[正しいユーザープールとアプリクライアント](https://github.com/awslabs/aws-jwt-verify#verifying-jwts-from-amazon-cognito)から取得されたもの。
+ アクセストークンクレームに、[正しい OAuth 2.0 スコープ](https://github.com/awslabs/aws-jwt-verify#checking-scope)が含まれているもの。
+ アクセストークンと ID トークンに署名したキーが、[ユーザープールの *JWKS URI* の `kid` 署名キーと一致していること](https://github.com/awslabs/aws-jwt-verify#the-jwks-cache)。

  JWKS URI には、ユーザーのトークンに署名した秘密鍵に関する公開情報が含まれています。ユーザープールの JWKS URI は、`https://cognito-idp.{{<Region>}}.amazonaws.com/{{<userPoolId>}}/.well-known/jwks.json` で確認できます。

Node.js アプリや AWS Lambda オーソライザーで使用できる詳細とサンプルコードについては、GitHub の [https://github.com/awslabs/aws-jwt-verify](https://github.com/awslabs/aws-jwt-verify) を参照してください。

## トークンの理解と検査
<a name="amazon-cognito-user-pools-using-tokens-manually-inspect"></a>

トークン検査をアプリに統合する前に、Amazon Cognito が JWT を組み立てる方法を検討してください。ユーザープールからサンプルトークンを取得します。それらをデコードして詳細に調べて特性を理解し、何をいつ検証するかを決定します。例えば、あるシナリオではグループメンバーシップを検証し、別のシナリオではスコープを調べたい可能性があります。

以下のセクションでは、アプリを準備するときに Amazon Cognito JWT を手動で検査するプロセスについて説明します。

### JWT の構造を確認します
<a name="amazon-cognito-user-pools-using-tokens-step-1"></a>

JSON ウェブトークン (JWT) は、間に `.` (ドット) 区切り文字がある 3 つのセクションで構成されます。

**ヘッダー**  
Amazon Cognito がトークンの署名に使用したキー ID、`kid`、および RSA アルゴリズム、`alg`。Amazon Cognito は `RS256` の `alg` でトークン署名します。`kid` は、ユーザープールが保持する 2048 ビット RSA プライベート署名キーへの切り捨てられたリファレンスです。

**ペイロード**  
トークンクレーム。ID トークンでは、クレームには、ユーザー属性とユーザープール、`iss`、およびアプリクライアント、`aud` に関する情報が含まれます。アクセストークンのペイロードには、スコープ、グループメンバーシップ、ユーザープールが `iss` として含まれ、アプリクライアントは `client_id` として含まれます。

**Signature**  
署名は、ヘッダーやペイロードのように base64url でデコードできません。JWKS URI で確認できる署名キーとパラメータから派生した RSA256 識別子です。

ヘッダーとペイロードは base64url でエンコードされた JSON です。開始文字 `{` にデコードされる最初の文字 `eyJ` で識別できます。ユーザーが base64url でエンコードした JWT をアプリケーションに提示した形式が `[JSON Header].[JSON Payload].[Signature]` になっていない場合、これは有効な Amazon Cognito トークンではないため、破棄できます。

次のサンプルアプリケーションでは、`aws-jwt-verify` を使用してユーザープールのトークンを検証します。

```
// cognito-verify.js
// Usage example: node cognito-verify.js eyJra789ghiEXAMPLE

const { CognitoJwtVerifier } = require('aws-jwt-verify');

// Replace with your Amazon Cognito user pool ID
const userPoolId = '{{us-west-2_EXAMPLE}}';

async function verifyJWT(token) {
  try {
    const verifier = CognitoJwtVerifier.create({
      userPoolId,
      tokenUse: '{{access}}', // or 'id' for ID tokens
      clientId: '{{1example23456789}}', // Optional, only if you need to verify the token audience
    });

    const payload = await verifier.verify(token);
    console.log('Decoded JWT:', payload);
  } catch (err) {
    console.error('Error verifying JWT:', err);
  }
}

// Example usage
if (process.argv.length < 3) {
  console.error('Please provide a JWT token as an argument.');
  process.exit(1);
}

const MyToken = process.argv[2];
verifyJWT(MyToken);
```

### JWT を検証
<a name="amazon-cognito-user-pools-using-tokens-step-2"></a>

JWT 署名は、ヘッダーとペイロードのハッシュされた組み合わせです。Amazon Cognito は、ユーザープールごとに 2 組の RSA 暗号化キーを生成します。1 つの秘密鍵がアクセストークンに署名し、もう 1 つが ID トークンに署名します。

**JWT トークンの署名を検証する**

1. ID トークンを復号化します。

   OpenID Foundation では、[JWT トークンでの作業のためのライブラリのリストも維持されています](http://openid.net/developers/jwt/)。

    AWS Lambda を使用してユーザープール JWTsデコードすることもできます。詳細については、[「 を使用した Amazon Cognito JWT トークンのデコードと検証 AWS Lambda](https://github.com/awslabs/aws-support-tools/tree/master/Cognito/decode-verify-jwt)」を参照してください。

1. ローカルキー ID (`kid`) とパブリック `kid` を比較します。

   1. ユーザープール用に、対応するパブリック JSON Web キー (JWK) をダウンロードして保存します。これは、JSON Web キーセット (JWKS) の一部として提供されており、環境に合わせて次のように `jwks_uri` URL を構築することで、その場所を特定できます。

      ```
      https://cognito-idp.{{<Region>}}.amazonaws.com/{{<userPoolId>}}/.well-known/jwks.json
      ```

      JWK と JWK セットの詳細については、「[JSON Web Key (JWK)](https://tools.ietf.org/html/rfc7517)」を参照してください。
**注記**  
Amazon Cognito は、ユーザープール内で署名キーをローテーションする可能性があります。ベストプラクティスとして、`kid` をキャッシュキーとして使用して、アプリに公開鍵をキャッシュし、定期的にキャッシュを更新してください。アプリが受け取るトークンの `kid` をキャッシュと比較します。  
正しい発行者で `kid` が異なるトークンを受け取った場合、Amazon Cognito が署名キーをローテーションした可能性があります。ユーザープール `jwks_uri` エンドポイントのキャッシュを更新します。

      以下は、サンプル `jwks.json` ファイルです。

      ```
      {
      	"keys": [{
      		"kid": "1234example=",
      		"alg": "RS256",
      		"kty": "RSA",
      		"e": "AQAB",
      		"n": "1234567890",
      		"use": "sig"
      	}, {
      		"kid": "5678example=",
      		"alg": "RS256",
      		"kty": "RSA",
      		"e": "AQAB",
      		"n": "987654321",
      		"use": "sig"
      	}]
      }
      ```  
**Key ID (`kid`)**  
`kid` は、トークンの JSON ウェブ署名 (JWS) をセキュア化するために使用されたキーを示すヒントです。  
**Algorithm (`alg`)**  
`alg` ヘッダーパラメータは、ID トークンをセキュア化するために使用される暗号化アルゴリズムを表します。ユーザープールは、SHA-256 による RSA 署名である RS256 暗号化アルゴリズムを使用します。RSA の詳細については、「[RSA cryptography](https://tools.ietf.org/html/rfc3447)」を参照してください。  
**Key type (`kty`)**  
`kty` パラメータは、この例の「RSA」など、キーで使用される暗号化アルゴリズムファミリーを特定します。  
**RSA exponent (`e`)**  
`e` パラメータには、RSA パブリックキーの指数値が含まれます。これは、Base64urlUInt でエンコードされた値として表されます。  
**RSA modulus (`n`)**  
`n` パラメータには、RSA パブリックキーのモジュラス値が含まれます。これは、Base64urlUInt でエンコードされた値として表されます。  
**Use (`use`)**  
`use` パラメータは、パブリックキーの用途を表します。この例では、`use` 値の `sig` が署名を表しています。

   1. JWT の `kid` に一致する `kid` のパブリック JSON ウェブキーを検索します。

### クレームを検証する
<a name="amazon-cognito-user-pools-using-tokens-step-3"></a>

**JWT クレームを検証する**

1. 次のいずれかの方法で、トークンの有効期限が切れていないことを確認します。

   1. トークンをデコードし、`exp` クレームを現在の時刻と比較します。

   1. アクセストークンに `aws.cognito.signin.user.admin` クレームが含まれている場合は、[GetUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUser.html) などの API にリクエストを送信します。[アクセストークンで承認](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pools-API-operations.html#user-pool-apis-auth-unauth)する API リクエストは、トークンの有効期限が切れているとエラーを返します。

   1. [userInfo エンドポイント](userinfo-endpoint.md) へのリクエストでアクセストークンを提示します。トークンの有効期限が切れている場合、リクエストはエラーを返します。

1. ID トークンの `aud` クレームとアクセストークンの `client_id` クレームは、Amazon Cognito ユーザープールで作成されたアプリクライアント ID と一致する必要があります。

1. 発行者 (`iss`) のクレームは、ユーザープールと一致する必要があります。例えば、`us-east-1` リージョンで作成されたユーザープールには、以下の `iss` 値があります。

   `https://cognito-idp.us-east-1.amazonaws.com/{{<userpoolID>}}`.

1. `token_use` クレームをチェックします。
   + Web API オペレーションでアクセストークンのみを受け入れている場合は、その値を `access` にする必要があります。
   + ID トークンのみを使用している場合、その値は `id` にする必要があります。
   + ID とアクセストークンのいずれも使用している場合、`token_use` クレームは、`id` または `access` になります。

これで、トークン内のクレームを信頼できるようになりました。