アプリケーションの認証方法として Amazon Cognito ユーザープールを使用したいと考えています。クライアントからアプリケーションに送信された ID とアクセストークンを検証する安全な方法は何ですか?
簡単な説明
クライアントがユーザープールを使用してアプリケーションを認証すると、Amazon Cognito は ID トークンを送信します。以下のような場合は、この ID トークンを手動で検証できます。
- ウェブアプリケーションを作成済みであり、Amazon Cognito ユーザープールを認証に使用する場合。
- 認証には Amazon Cognito ユーザープールを使用し、AWS Security Token Service (AWS STS) の一時的な認証情報を取得するには Amazon Cognito ID プールを使用します。この認証情報を使用して AWS Lambda が呼び出されますが、Lambda にはユーザープールを使用して最初に認証したユーザーに関する情報がありません。
Amazon Cognito JSON Web Token (JWT) に含まれている Amazon Cognito ユーザーの詳細を取得するために、トークンを復号して署名を検証できます。
解決方法
AWS は JWT の検証に使用できる次のライブラリをリリースしました: https://github.com/awslabs/aws-jwt-verify
import { CognitoJwtVerifier } from "aws-jwt-verify";
// Verifier that expects valid access tokens:
const verifier = CognitoJwtVerifier.create({
userPoolId: "<user_pool_id>",
tokenUse: "access",
clientId: "<client_id>",
});
try {
const payload = await verifier.verify(
"eyJraWQeyJhdF9oYXNoIjoidk..." // the JWT as string
);
console.log("Token is valid. Payload:", payload);
} catch {
console.log("Token not valid!");
}
ユーザーがログインすると、Amazon Cognito ユーザープールは JWT を返します。JWT は、base64url でエンコードされた JSON 文字列 (「クレーム」) で、ユーザーに関する情報が含まれます。Amazon Cognito は、ID トークン、アクセストークン、リフレッシュトークンの 3 つのトークンを返します。ID トークンには、Amazon Cognito ユーザープールで定義されたユーザーフィールドが含まれます。
トークンには、ヘッダー、ペイロード、および署名の 3 つのセクションが含まれます。
以下は、サンプル ID トークンのヘッダーです。ヘッダーには、キー ID (「kid」) と、トークンの署名に使用されるアルゴリズム (「alg」) が含まれます。この例ではアルゴリズムは「RS256」で、これは SHA-256 を持つ RSA 署名です。
{
"kid": "abcdefghijklmnopqrsexample=",
"alg": "RS256"
}
次に、ペイロードの例を示します。ペイロードには、ユーザーに関する情報と、トークンの作成と有効期限のタイムスタンプがあります。
{
"sub": "aaaaaaaa-bbbb-cccc-dddd-example",
"aud": "xxxxxxxxxxxxexample",
"email_verified": true,
"token_use": "id",
"auth_time": 1500009400,
"iss": "https://cognito-idp.ap-southeast-2.amazonaws.com/ap-southeast-2_example",
"cognito:username": "anaya",
"exp": 1500013000,
"given_name": "Anaya",
"iat": 1500009400,
"email": "anaya@example.com"
}
最後のセクションは署名です。署名は、ヘッダーとペイロードのハッシュ化および暗号化された組み合わせです。
Amazon Cognito は、ユーザープールごとに 2 つの RSA キーペアを生成します。各ペアのシークレットキーは、それぞれの IDトークンまたはアクセストークンに署名するために使用します。パブリックキーあは、次の形式のアドレスで利用できるようになります。
https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
JSON ファイル (jwks.json) は、次の形式で構成されています。
{
"keys": [{
"alg": "RS256",
"e": "AQAB",
"kid": "abcdefghijklmnopqrsexample=",
"kty": "RSA",
"n": "lsjhglskjhgslkjgh43lj5h34lkjh34lkjht3example",
"use": "sig"
}, {
"alg":
"RS256",
"e": "AQAB",
"kid": "fgjhlkhjlkhexample=",
"kty": "RSA",
"n": "sgjhlk6jp98ugp98up34hpexample",
"use": "sig"
}]
}
Amazon Cognito JWT の署名を検証するには、まず、トークンのヘッダーにあるキー ID と一致するキー ID を持つパブリックキーを検索します。その後、aws-jwt-verify または jwt.io や OpenID Foundation で推奨されるライブラリを使用して、トークンの署名を検証し、有効期限やユーザー名などの値を抽出できます。
署名とは別に、次を確認することもベストプラクティスです。
- トークンは期限切れではありません。
- ペイロードに指定された対象者 (「aud」) が、Amazon Cognito ユーザープールで作成されたアプリクライアント ID と一致していること。
aws-jwt-verify ライブラリには、お客様のためのこれらのチェックが含まれます。Lambda を使用して Amazon Cognito JWT をデコードして検証する方法のさらなるコード例については、「Decode and verify Amazon Cognito JWT tokens」(Amazon Cognito JWT トークンをデコードして検証する) を参照してください。
関連情報
JSON ウェブトークンの検証
ユーザープールでのトークンの使用