Cognito Federated SignUp set “email_verified” to true

2021-05-02 AWS

前陣子在規劃有關於 Cognito 需要整合 Federated Login 的案子,其中有一個需求是希望當使用者從 Facebook/Google 等 Social Login 登入時,可以將對應的 User Profile 資訊回填到 Cognito User Pool Attribute (Specifying Identity Provider Attribute Mappings for Your User Pool)

但事與願違,通常和 Third Party 串接總有一些意外,這一篇就是要講這個意外 …

由於 Cognito 的 Scheme 中至少有一項 email 或 phone number 必須被 verified 過,使用者要 “忘記密碼” 或 “重設密碼” 時才可以透過當時設定的 email / phone number 接收驗證訊息,所以這兩個值至少要一個能用,而在這個案例中採用的是 email 作為驗證。

一般來說 Facebook/Google 等都會至少進行 email verified 過,所以從這些 Social Provider 登入時基本上是可以信任 email 是可用的,但這些資訊要回填到 Cognito User Pool 時通常會參照從 Social Provider 拿回來的 User Profile 作為參考

Google OpenID 為例,從 OAuth 2.0 拿回來的 User Profile 就會有 email_verified 欄位 mapping 回 Cognito User Pool Attribute。但 Facebook 在某一版 User Profile APIemail_verified 給拔掉了,也就是沒有對應的值可以回填到 Cognito。

Cognito 本身有提供 Pre Sign-up 時觸發 Lambda 將 autoVerifyEmail, autoVerifyPhone 值回給 Cognito 自動驗證的功能,但在 Federated sign up doesn’t set email_verified to true #5117 有講到 Federated Sign-up 時無法使用 Pre Sign-up autoVerify 的功能,但因為是執行 Lambda 所以 … 可以直接跑 SDK 修改 User Attributes

var aws = require('aws-sdk');
aws.config.update({region: 'eu-central-1'});
exports.handler = (event, context, callback) => {
    if (event.request.userAttributes.email) {
        if (event.request.userAttributes["cognito:user_status"] === "EXTERNAL_PROVIDER") {
            const cognitoIdServiceProvider = new aws.CognitoIdentityServiceProvider({
                apiVersion: '2016-04-18',
                region: 'eu-central-1'
            });
            var params =  {
                UserAttributes: [
                  {
                      Name: "email_verified",
                      Value: "true"
                  }
                ],
                UserPoolId: event.userPoolId,
                Username: event.userName
            }
   
            cognitoIdServiceProvider.adminUpdateUserAttributes(params, function(err, data) {
              if (err) {
                    callback(null, event);
              } else {
                    callback(null, event);
              }
            });
        } else {
            callback(null, event);
        }
    } else {
        callback(null, event);
    }
};

這算是一個不漂亮,但很有效的 Workaround 解決方式。

給 Mr. 沙先生一點建議

彙整

分類

展開全部 | 收合全部

License

訂閱 Mr. 沙先生 的文章

輸入你的 email 用於訂閱