🤩

Cognitoユーザープールのアクセストークンカスタマイズ機能がリリースされたので試してみる

2024/02/19に公開

Cognitoユーザープールでアクセストークンのカスタマイズが可能に!

Cognitoってアクセストークンカスタマイズできないの辛いなーと思っていたところ、たまたまアクセストークンのカスタマイズ機能をリリースしたよというAWSのリリース記事を見つけたので試してみます。

2023年12月出たばかりの機能のようです。

https://aws.amazon.com/jp/about-aws/whats-new/2023/12/amazon-cognito-user-pools-customize-access-tokens/

前提条件

  • Cognitoに認証リクエストするクライアントを構築済み
  • Cognitoユーザープールを構築と諸々の設定済み
  • ユーザープールに今回のデモに使うユーザーを追加済み
  • ユーザープールのAdvanced securityを有効にしている

advanced security enabled

デフォルトのアクセストークンを見てみる

アクセストークンをカスタマイズする前に、デフォルトをアクセストークンを確認してみます。
ReactのSPAアプリケーションをCognitoに認証リクエストを送信するクライアントとして作成しました。
取得したアクセストークンをjwt.ioでデコードしてみました。
ペイロードは以下のようになっていました。
一部XXXXXXXXXXXXXXXXXで一応マスクしています。

scopeaws.cognito.signin.user.adminになっていることだけ覚えておいてください。

default-access-token.json
{
  "sub": "XXXXXXXXXXXXXXXXX",
  "iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/XXXXXXXXXXXXXXXXX",
  "client_id": "XXXXXXXXXXXXXXXXX",
  "origin_jti": "2e556ef6-50ff-41a4-8a17-f072033eda42",
  "event_id": "XXXXXXXXXXXXXXXXX",
  "token_use": "access",
  "scope": "aws.cognito.signin.user.admin",
  "auth_time": 1708065484,
  "exp": 1708266461,
  "iat": 1708262861,
  "jti": "a94cc197-05ed-43d2-94e7-aa8a8599220a",
  "username": "XXXXXXXXXXXXXXXXX"
}

アクセストークンをカスタマイズする

ドキュメントに従い、実装していきます。
やることとしては、この2つです。

  1. アクセストークンをカスタマイズするLambdaを作成する
  2. Pre token generation triggerとしてユーザープールに紐づける

https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-token-generation.html

要件

デフォルトのアクセストークンの"scope":"aws.cognito.signin.user.admin"をカスタマイズしたいと仮定してカスタマイズしていきます。
仮定した要件は以下です。

  • aws.cognito.signin.user.adminは持たせたくない(消したい)
  • ROLE_ZENNROLE_QIITAを持たせたい

1. アクセストークンをカスタマイズするLambdaを作成する

以下のようにLambdaを作成します。
SAMテンプレートを使って作成しました。

今回のデモでの要件を踏まえると、要点はこの2つです。
accessTokenGenerationに追加したいスコープを定義すると追加できる
scopesToSuppressに消したいスコープを定義すると削除できる

requestresponseは様々なパラメタを持っているので、もっといろんなカスタマイズが可能です。
イベントのrequestresponseこちらに定義されているので、詳しくは割愛します。

app.mjs
export const lambdaHandler = (event, context) => {
    event.response = {
        "claimsAndScopeOverrideDetails": {
            "accessTokenGeneration": {
                // 追加したいスコープをここに定義
                "scopesToAdd": [
                    "ROLE_ZENN",
                    "ROLE_QIITA",
                ],
                // 消したいスコープをここに定義
                "scopesToSuppress": [
                    "aws.cognito.signin.user.admin"
                ]
            }
        }
    };

    context.done(null, event);
};

今回のデモではアクセストークンのカスタマイズをとりあげるため割愛しますが、IDトークンのカスタマイズも同様に可能です。(IDトークンのカスタマイズは前々から可能でした。)

2. Lambdaをユーザープールに紐づける

ユーザープール -> User pool properties -> Lambda triggersAdd Lambda triggerを選択。

Trigger TypeAuthentication
AuthenticationPre token generation trigger
Trigger event versionBasic features + access token customization - Recommended
を選択し、作成したLambdaを選択して紐づける。

link lambda with user pool

カスタマイズしたアクセストークンを見てみる

これでカスタマイズされたアクセストークンが発行されるはずなので、リフレッシュトークンを使ってトークンをリフレッシュします。
リフレッシュしたアクセストークンを再度jwt.ioでデコードしてみます。
得られたペイロードはこのようになりました。
同様に一部XXXXXXXXXXXXXXXXXでマスクしています。

scopeを見てみると、仕様通りにROLE_ZENN ROLE_QIITAが追加され、さっきまであったaws.cognito.signin.user.adminが消えていることが確認できます。

customized-access-token.json
{
  "sub": "XXXXXXXXXXXXXXXXX",
  "iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/XXXXXXXXXXXXXXXXX",
  "client_id": "XXXXXXXXXXXXXXXXX",
  "origin_jti": "3e242c26-6308-4188-8abf-09f018efc4d7",
  "event_id": "XXXXXXXXXXXXXXXXX",
  "token_use": "access",
  "scope": "ROLE_ZENN ROLE_QIITA",
  "auth_time": 1708220975,
  "exp": 1708275688,
  "iat": 1708272089,
  "jti": "2ae3c331-38fc-48ff-81e5-61b02811b549",
  "username": "XXXXXXXXXXXXXXXXX"
}

おわりに

Cognitoユーザープールの新機能であるアクセストークンのカスタマイズを試してみました。
今回設定したLambdaは固定値をscopeに設定しましたが、DBにアクセスしてロールを動的に決定し、アクセストークンに渡すという使い方もできそうです。

参考

Discussion