Amazon Cognitoでソーシャルサインインする度に、アカウントのemail_verifiedがfalseになってしまう問題

はじめに

ソフトウェアエンジニアの谷藤です。

今日は、開発中に私が直面したタイトルに記載の問題について解説します。

Amazon Cognitoは公式ドキュメントやまとめ記事などが少ない(特に日本語の記事)ため、問題が発生すると解決までに多くの時間を消費してしまいます。

同じ問題に直面した方の手助けになれば幸いです。

※ 動作が確認できているのはAppleを選択した場合のみですが、FacebookAmazonを選択した場合でも発生すると思われます。Googleの場合は発生しませんが、その理由については下の「原因」で説明します。

この問題について説明しているissueはこちらになります。 github.com

問題の整理

f:id:HiroTanifuji:20210908180520p:plain

上記のようなApple経由でサインインしたemail_verifiedがtrueのアカウントで再びサインインすると、以下のようのemail_verifiedがfalseに変更されてしまいます。

f:id:HiroTanifuji:20210908180500p:plain

原因

Cognitoは、毎サインイン時に、IDプロバイダーから受け取らなかったアカウントの属性にデフォルト値をセットします。

故に、Congnitoに「メアド認証済かのフラグ」を渡していないIDプロバイダー経由でサインインすると、email_verifiedがfalse(デフォルト値)になります。

Googleの場合は、そのフラグを渡しているため(マッピングする必要あり)、常にemail_verifiedがtrueになっているというわけです。

Googleのemail_verified属性とCognitoのEmail Verifiedをマッピングしている f:id:HiroTanifuji:20210908184216p:plain

Appleには、メアド認証に関する属性がない f:id:HiroTanifuji:20210908184223p:plain

解決方法

現状、ユーザープールやIDプロバイダー側の設定の変更で解決することはできません。

ソーシャルサインインの場合のみアカウントのemail_verifiedを強制的にtrueに変更するLambdaの関数を用意して、それを毎サインイン時に呼び出すようにユーザープールに設定する必要があります。

詳しい手順は以下になります。

1. ソーシャルサインインの場合のみemail_verifiedを強制的にtrueに変更するLambdaの関数を用意

const AWS = require('aws-sdk');

AWS.config.update({
    accessKeyId: process.env.ACCESS_KEY,
    secretAccessKey: process.env.SECRET_ACCESS_KEY,
    region: process.env.COGNITO_REGION,
});

const cognito = new AWS.CognitoIdentityServiceProvider({
    apiVersion: '2016-04-18',
});

exports.handler = async (event, context, callback) => {
    if (!!event.request.userAttributes.email) {
        // ソーシャルサインアップした場合、statusが "EXTERNAL_PROVIDER"になるので、これで判別する
        if (event.request.userAttributes['cognito:user_status'] === 'EXTERNAL_PROVIDER') {
            const params = {
                UserAttributes: [
                    {
                        Name: 'email_verified',
                        Value: 'true',
                    },
                ],
                UserPoolId: event.userPoolId,
                Username: event.userName,
            };

            try {
                await cognito.adminUpdateUserAttributes(params).promise();
                callback(null, event);
            } catch (e) {
                callback(null, event);
            }
        } else {
            callback(null, event);
        }
    } else {
        callback(null, event);
    }
};

2. 適当な名前を付けてデプロイ

3. 2でデプロイしたLambda関数を「認証後トリガー」に設定する

f:id:HiroTanifuji:20210908185322p:plain

4. ソーシャルサインイン後でもemail_verifiedがtrueになっていることを確認する

f:id:HiroTanifuji:20210908180515p:plain

さいごに

今回は、ソーシャルサインインする度にアカウントのemail_verifiedがfalseになってしまう問題について解説しました。

少しでも参考になったら嬉しいです。

質問やご指摘などがありましたら、コメントにお願いします。

読んでいただきありがとうございました。