【问题标题】:email_verified = false in ID token from Googleemail_verified = 来自 Google 的 ID 令牌中的 false
【发布时间】:2017-04-11 21:48:47
【问题描述】:

我使用Google ID tokens 让用户登录我的网络服务。作为验证从 Google 收到的令牌的一部分,网络服务会检查令牌负载中的 email_verified = true。

我的一些用户 signed up for a Google-account 使用他们的非 Gmail、非 Google Apps 电子邮件地址。他们确实在注册后点击了 Google 发送给他们的电子邮件中的链接,以验证他们的电子邮件地址。

当这些用户尝试登录我的网络服务时,我在令牌的有效负载中得到 email_verified = false。

这是什么意思,在验证令牌时我可以/应该忽略它吗?

【问题讨论】:

  • 如果您正在验证用户是否拥有有效的帐户/电子邮件地址,那么您可能不应该忽略它。你是如何实现这个登录的?我还没有尝试过,但如果 email_verified 作为配置文件范围的一部分返回并且相关用户没有 Google+ 帐户,我想知道它是否还会返回。
  • 如果用户验证了电子邮件,那么我们应该在该声明中返回 true。我们需要对此进行调查。如果可能的话,您能否通过我的 G+ 个人资料将用户的电子邮件地址发送给我?
  • @nvnagr 我已经通过 G+ 向您发送了两个示例

标签: jwt google-authentication google-oauth


【解决方案1】:

有几个不同的ways,您可以在其中验证服务器端 ID 令牌的完整性:

  1. “手动”——不断下载谷歌的公钥,验证签名,然后是每一个字段,包括iss;我在这里看到的主要优势(尽管在我看来很小)是您可以最大限度地减少发送给 Google 的请求数量。
  2. “自动” - 在 Google 的端点上执行 GET 以验证此令牌 https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}
  3. 使用 Google API 客户端库 - 例如 official one。

这可能是这样的:

private const string GoogleApiTokenInfoUrl = "https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}";

public ProviderUserDetails GetUserDetails(string providerToken)
{
    var httpClient = new MonitoredHttpClient();
    var requestUri = new Uri(string.Format(GoogleApiTokenInfoUrl, providerToken));

    HttpResponseMessage httpResponseMessage;
    try
    {
        httpResponseMessage = httpClient.GetAsync(requestUri).Result;
    }
    catch (Exception ex)
    {
        return null;
    }

    if (httpResponseMessage.StatusCode != HttpStatusCode.OK)
    {
        return null;
    }

    var response = httpResponseMessage.Content.ReadAsStringAsync().Result;
    var googleApiTokenInfo = JsonConvert.DeserializeObject<GoogleApiTokenInfo>(response);

    if (!SupportedClientsIds.Contains(googleApiTokenInfo.aud))
    {
        Log.WarnFormat("Google API Token Info aud field ({0}) not containing the required client id", googleApiTokenInfo.aud);
        return null;
    }

    return new ProviderUserDetails
    {
        Email = googleApiTokenInfo.email,
        FirstName = googleApiTokenInfo.given_name,
        LastName = googleApiTokenInfo.family_name,
        Locale = googleApiTokenInfo.locale,
        Name = googleApiTokenInfo.name,
        ProviderUserId = googleApiTokenInfo.sub
    };
}

【讨论】:

  • 我不知道第二个选项,这是一个很棒的提示!我有第一个选择。但这并不能解决问题:因为 email_verified 在 JWT Google 问题中仍然是错误的,我的问题是我是否应该接受这一点
  • 您好 Alexandru,tokeninfo 端点可以帮助调试。创建 id_token 是为了方便服务器验证它,而无需进行会增加延迟的网络调用。您的建议会产生安全问题。 id 令牌验证的非常重要的部分是验证令牌是否适用于您的服务器(受众字段)。通过调用 tokeninfo,您只会知道它是一个有效的 id_token,但除非您检查受众,否则您将产生安全问题。最好的选择是使用库。应避免使用 tokeninfo 端点。
  • 嗨@nvnagr,关于aud 字段的验证,如果您仔细观察,您可以在该页面上看到Google 也清楚地说明了这一点 - 我也在提供的代码示例中这样做.
  • @Rob 除非您可以证明即使未验证电子邮件(错误),tokeinfo 端点也会以 HttpStatusCode 200 OK 响应,否则我认为没有任何问题
猜你喜欢
  • 2020-10-13
  • 2020-02-02
  • 2016-06-26
  • 1970-01-01
  • 1970-01-01
  • 2014-02-12
  • 2016-12-27
  • 2020-11-12
  • 2018-01-09
相关资源
最近更新 更多