AWS Cognito ユーザプールでユーザ属性(カスタム属性)をIDトークンに含める

CognitoのLambdaトリガーを使ってみようと思い検証をしていたところ、定義したカスタム属性がIDトークンに含まれていなかったので対処法を調べました。特に大したことない内容ですが忘れないように記述します。

Lambdaトリガーを試す

以下の記事を参考にLambdaトリガーを試してみようと思いやってみました。

こちらの記事では、サインインの追加条件としてカスタム属性を検証しています。

dev.classmethod.jp

AWSコンソールからユーザプールに作成したユーザに、カスタム属性が設定されているか確認しておきます。

custom attribute

実際にログインしてみる

参考にさせて頂いた記事では「initiate-auth」コマンドを使用してログインしていますが、以前の記事を執筆した際にReactで作成したサンプルクライアントがあったため今回はこれを使用してログインを実行しました。

Lambdaトリガーを使ってみた結果

ログイン実行後、CloudWatchのロググループを確認します。

「cognitoSampleTrigger」という名前でLambdaを作成したのでロググループに「/aws/lambda/cognitoSambleTrigger」にログが出力されていました。

ログを確認すると、問題なくLambdaは実行できていることが確認できます。

2023-08-23T07:56:28.996Z 530619b9-5d37-463c-aaab-55ceb95a0de1    INFO    {
  version: '1',
  region: 'ap-northeast-1',
  userPoolId: 'ap-northeast-1_xxxxxxxxx',
  userName: 'ito',
  callerContext: {
    awsSdkVersion: 'aws-sdk-unknown-unknown',
    clientId: 'xxxxxxxxxxxxxxxxxxxx'
  },
  triggerSource: 'PreAuthentication_Authentication',
  request: {
    userAttributes: {
      'cognito:token_nbf': 'xxxxxxxxxxxxxx',
      sub: 'xxxxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx',
      'cognito:user_status': 'CONFIRMED',
      email_verified: 'true',
      name: 'xxxx',
      'custom:hoge1': '1',
      'custom:hoge2': '1',
      email: 'xxxxxx@linkode.co.jp'
    },
    validationData: null,
    userNotFound: false
  },
  response: {}
}

IDトークンを確認

Lambdaで確認できたカスタム属性「custom:hoge1': '1'」「custom:hoge2': '1'」がIDトークンにも含まれているか、サンプルクライアントに出力処理を入れてChromeデベロッパーツールで確認してみましたが当然のように含まれていませんでした...

payload: 
  at_hash: "xxxxxxxxxxxxxxxxxxxxxxx"
  aud: "xxxxxxxxxxxxxxxxxxxxxxx"
  auth_time: xxxxxxxxx
  cognito:username: "ito"
  email: "xxxxxxxxxx@linkode.co.jp"
  email_verified: true
  event_id: "xxxxxxxxxxxxxxxxxxxxxx"
  exp: 1692785563
  iat: 1692781963
  iss: "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxxxxxxxx"
  jti: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  name: "xxxxx"
  origin_jti: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  sub: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  token_use: "id"

ユーザプールの設定を確認する

今回の場合、以下の記事から2つ設定が足りていないことがわかりました。 また「Hosted UI」を使用しているので、こちらにもOIDCのスコープを追加する必要がありました。

以下、手順をまとめます。

  1. アプリケーションクライアントの設定で、「属性の読み取りおよび書き込み許可」で該当項目をチェックする
  2. サンプルクライアントのAmplifyの設定でOAuthの「scope」の設定に「profile」を追加する
  3. 「Hosted UI」の「OpenID Connectのスコープ」にprofileを追加する

stackoverflow.com

「属性の読み取りおよび書き込み許可」で該当項目をチェックする

「ユーザプール」→任意の「ユーザプール名」→「アプリケーションの統合」タブ→任意の「クライアントアプリケーション名」を選択して、「属性の読み取りおよび書き込み許可」の項目をで編集ボタンを押下し、該当のカスタム属性の読み取りにチェックを入れる

auth

サンプルクライアントのAmplifyの設定を修正する
const configuration = {
  region: 'ap-northeast-1',
  userPoolWebClientId: process.env.REACT_APP_CLIENT_ID ?? '',
  userPoolId: 'ap-northeast-1_xxxxxxxxxxxxx',
  identityPoolId: process.env.REACT_APP_IDENTITY_POOL_ID ?? '',
  oauth: {
    domain: `${congitoDomain}`,
    scope: ['email', 'openid', 'phone', 'profile'], ★profileを追加
    redirectSignIn: 'http://localhost:3000',
    redirectSignOut: 'http://localhost:3000',
    responseType: 'code',
  },
}
「Hosted UI」の「OpenID Connectのスコープ」にprofileを追加する

「ユーザプール」→任意の「ユーザプール名」→「アプリケーションの統合」タブ→任意の「クライアントアプリケーション名」を選択して、「ホストされたUI」の項目で編集ボタンを押下してprofileを追加する

hosted ui

もう一度ログインを試してみる

以上の設定を確認したら、サンプルクライアントから再度ログインしてIDトークンを確認してみます。

payload: 
  at_hash: "xxxxxxxxxxxxxxxxxxxxxxx"
  aud: "xxxxxxxxxxxxxxxxxxxxxxx"
  auth_time: xxxxxxxxx
  cognito:username: "ito"
  custom:hoge1: "1" ★ カスタム属性がIDトークンに含まれていることを確認!
  custom:hoge2: "1" ★
  email: "xxxxxxxxxx@linkode.co.jp"
  email_verified: true
  event_id: "xxxxxxxxxxxxxxxxxxxxxx"
  exp: 1692785563
  iat: 1692781963
  iss: "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxxxxxxxx"
  jti: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  name: "xxxxx"
  origin_jti: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  sub: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  token_use: "id"

ちなみに作成したカスタム属性「hoge1」「hoge2」のどちらかまたは両方を0に設定するとLambdaで実装したエラーが「Hosted UI」に表示されます。

error