Amazon CognitoのフェデレーションLambdaトリガーでGoogle認証した時の属性をカスタマイズしてみる
はじめに
Amazon Cognitoユーザープールは特定のイベント処理をカスタマイズできる、Lambdaトリガーという機能があります。
先日のアップデートで新しいトリガータイプ「フェデレーション」が追加されました。詳しくは、弊社のブログを御覧ください。
このフェデレーションLambdaトリガーを実際に使って、Googleから取得できる属性を確認し、カスタマイズしてみようと思います。
フェデレーション Lambda トリガーとは
外部IdP(SAMLまたはOIDC)からの認証レスポンスを受け取った後、ユーザープールに属性を保存する前にLambda関数を実行できる機能です。
外部IdPから受け取った属性から不要な情報を削除したり、加工したりすることが可能です。

※画像引用:Inbound federation Lambda trigger - Amazon Cognito
やってみた
実際にフェデレーションLambdaトリガーを設定して動作を確認してみます。
前提
- Cognitoユーザープールが作成済み
- 外部IdP(今回はGoogle)との連携が設定済み
- フェデレーショントリガー用のLambdaとして「inbound-federation-lambda」を作成、トリガーとして設定済み
- Amplify.js(Reactアプリケーション)でマネージドログインを利用した認証を実装済み
CognitoとGoogleの認証連携の設定については、次のブログを参照してください。
Amplify.jsでマネージドログインを利用した認証のサンプルについては、こちらのブログを参照してください。
1. Googleから連携される情報を確認する
フェデレーショントリガー用のLambdaとして、次のコードのLambdaをセットしておきます。
このLambdaは受け取ったデータをログに全部表示するだけで、受け取ったものをそのまま何も処理せず返しています。
これを使ってどんな形のデータが流れてくるか確認します。
- 関数名:
inbound-federation-lambda - ランタイム:Node.js 24.x
- アーキテクチャ:arm64
exports.handler = async (event) => {
console.log(JSON.stringify(event, null, 2));
return event;
};
その後に、Reactアプリケーションを立ち上げて、マネージドログインページを開きます。

Googleを外部IdPとして設定していると、マネージドログイン画面に「Sign in with Google」のボタンが追加されるので、クリックしてGoogleにログインします。

Googleのログイン処理が終わると、Cognitoのマネージドログイン画面にリダイレクトされ、続けて自分のReactアプリケーションにリダイレクトされて処理が返ってきます。ここまでくれば、ログインは完了しています。

このとき、トリガーで実行されたLambdaのCloudWatchLogsを見ると、ログを出力しており実行されていることが確認できます。

ログからIDトークンにどういう情報が入っているかわかったので、これをカスタマイズしてみましょう。

2. Googleから連携される情報をカスタマイズする
フェデレーションLambdaトリガーが受け取るパラメーターは、次のような形のJSONになっています。
JSONの全貌
{
"version": "string",
"triggerSource": "InboundFederation_ExternalProvider",
"region": AWSRegion,
"userPoolId": "string",
"userName": "string",
"callerContext": {
"awsSdkVersion": "string",
"clientId": "string"
},
"request": {
"providerName": "string",
"providerType": "string",
"attributes": {
"tokenResponse": {
"access_token": "string",
"token_type": "string",
"expires_in": "string"
},
"idToken": {
"sub": "string",
"email": "string",
"email_verified": "string"
},
"userInfo": {
"email": "string",
"given_name": "string",
"family_name": "string"
},
"samlResponse": {
"string": "string"
}
}
},
"response": {
"userAttributesToMap": {
"string": "string"
}
}
}
このJSONの、 response.userAttributesToMap にデータを渡すことで、Cognito側にデータを受け渡すことができます。
重要な注意点として、 userAttributesToMap が {}(空オブジェクト) だった場合は、デフォルト値がCognitoに渡されています。
カスタマイズする場合、このデフォルト値が渡されなくなります。そのため、明示的に必要な情報を含める必要があります。
例えば、Googleの属性マッピングとして以下のように設定していたとします。
| ユーザープール属性 | Google属性 |
|---|---|
| username | sub |
その場合、 userAttributesToMap にも、 email と sub の項目を次のような形で設定しておかないと、属性マッピングがうまくいきません。
{
"userAttributesToMap": {
"email": "<<何らかのE-mail>>",
"sub": "<<何らかのsub的な文字列>>"
}
}
最低限の情報として、このように設定します。
exports.handler = async (event) => {
console.log(JSON.stringify(event, null, 2));
const { providerType, attributes } = event.request;
+ event.response = {
+ userAttributesToMap: {
+ sub: attributes.idToken.sub,
+ email: attributes.idToken.email,
+ }
+ }
return event;
}
今回は、これに追加してE-mailのドメイン部分だけ抽出して属性に追加してみます。
先ほどのコードに email_domain の属性を追加します。
exports.handler = async (event) => {
console.log(JSON.stringify(event, null, 2));
const { providerType, attributes } = event.request;
event.response = {
userAttributesToMap: {
sub: attributes.idToken.sub,
email: attributes.idToken.email,
+ email_domain: attributes.idToken.email.split("@")[1],
}
}
return event;
}
Lambdaをデプロイした後、Cognitoの ソーシャルプロバイダーと外部プロバイダー > IDプロバイダー Google の属性マッピング の編集を開き、
ユーザープール属性に custom:mycustom1 というCognito側のカスタム属性、とGoogle属性にLambdaトリガーで追加した email_domain をそれぞれ追加します。

これで、Cognitoのユーザープール属性 custom:mycustom1 に Lambdaトリガーで抽出したE-mailのドメイン名がマッピングされます。
この設定をした後、Googleログインしてみると、トリガーが動き、ユーザー属性に custom:mycustom1 に gmail.com とドメイン名が連携できることが確認できました。

まとめ
フェデレーションLambdaトリガーを使うことで、外部IdPからの属性を柔軟にカスタマイズできるようになりました。
外部IdPと連携した情報を加工したい場合に役立ちそうです。






