没有从 firebase 获取“电子邮件”使用 google 登录验证 id 令牌

dur*_*jaa 7 javascript python firebase firebase-authentication google-signin

在我的网络应用程序中,我使用 firebase google 登录来验证用户身份,流程如下

  1. 在前端让用户使用 firebase sdk 登录,获取用户的 idtoken 将其发送到服务器
  2. 服务器使用 idtoken 验证用户并从 idtoken 获取电子邮件

我正在使用 python 后端,并使用 google.oauth2.id_token 模块来验证令牌并解码令牌

问题是对于少数用户来说,解码的令牌不包含电子邮件字段

在前端,我尝试添加 userinfo.email 范围,但它仍然不起作用

我像这样添加了范围

googleProvider = new firebase.auth.GoogleAuthProvider(); googleProvider.addScope('https://www.googleapis.com/auth/userinfo.email')
Run Code Online (Sandbox Code Playgroud)

在后端我正在像这样解码令牌

decoded_token = google.oauth2.id_token.verify_firebase_token(auth_token, google.auth.transport.requests.Request())
Run Code Online (Sandbox Code Playgroud)

这是少数用户的解码令牌包含的内容(我已将实际值更改为“sometext”)

{
    "picture": "somtext",
    "sub": "somtext",
    "user_id": "somtext",
    "name": "somtext",
    "iss": "https://securetoken.google.com/somtext",
    "firebase": {
      "sign_in_provider": "google.com",
      "identities": {
        "google.com": [
          "somtext"
        ]
      }
    },
    "exp": 1557566434,
    "auth_time": 1557562833,
    "iat": 1557562834,
    "aud": "somtext"
  }
Run Code Online (Sandbox Code Playgroud)

解码的令牌中缺少电子邮件字段

对于少数用户,电子邮件字段存在 对于少数用户,电子邮件字段不存在

我不知道我错过了什么,我想在所有用户的解码令牌中包含电子邮件字段

小智 5

您可以使用 user.providerData[0]!.email! 如果您使用“允许使用同一电子邮件地址创建多个帐户”,则获取电子邮件:

  let bearerTokenID = req.cookies.BearerTokenID;
  let decodedToken = await admin.auth().verifyIdToken(bearerTokenID);
  let user = await admin.auth().getUser(decodedToken.uid);
  let email = user.providerData[0]!.email!;
  console.log("Email:", email);
Run Code Online (Sandbox Code Playgroud)


dur*_*jaa 3

我没有找到我所要求的确切解决方案,但我改变了我的流程,我发布此内容是因为我觉得它可能对某人有帮助

未收到电子邮件的原因是 Firebase 登录流程中的“允许使用同一电子邮件地址创建多个帐户”设置。此选项的作用是创建一个没有电子邮件地址的帐户,并且其 UID 与具有相同电子邮件地址的其他帐户不同

我需要的是允许用户使用多个登录提供商(在我的例子中是 facebook、google)来登录

如果某个用户在 2 个不同的登录提供商中使用相同的电子邮件,并在不同时间使用不同的提供商(使用相同的电子邮件)登录,则该用户应链接到单个帐户

下面解释了我如何实现该要求

在 Firebase 登录流程中,我将设置更改为“每个电子邮件地址一个帐户”,

为了实现这个要求,我必须处理以下情况

情况1:

User sign-in for the 1st time(no user account is there for the user) using a sign-in-provider
Run Code Online (Sandbox Code Playgroud)

案例2:

User sign-in (not 1st time user account is created already) using the same sign-in-provider
Run Code Online (Sandbox Code Playgroud)

案例3:

User sign-in (not 1st time user account is created already) using a different sign-in-provider (with same email)
Run Code Online (Sandbox Code Playgroud)

处理案例1和案例2

在前端,当用户登录时,前端将 idtoken 和电子邮件(使用 email.scope 获取电子邮件)发送到后端

后端验证 idtoken 并获取该令牌的 firebase user_id,然后检查数据库中是否有与 firebase user_id 关联的帐户

如果它找不到与 firebase user_id 关联的帐户,它会使用该 firebase user_id 作为密钥创建一个新帐户,并将电子邮件存储在该帐户中,并将所需的详细信息发送到前端。如果它找到一个帐户,它会发送与该帐户相关的详细信息

处理案例3

由于“每个电子邮件地址一个帐户”设置,当用户尝试使用新的登录提供程序使用现有电子邮件登录时,Firebase 将抛出“auth/account-exists-with- different-credential”异常

通过按照此处的说明处理此异常https://firebase.google.com/docs/auth/web/google-signin#handling-account-exists-with- Different-credential-errors 带有此新登录提供程序的电子邮件将链接到现有的 firebase user_id

那么流程就像case2一样