Google 登录:使用 google-auth Python 包时“未找到密钥 ID xxxx 的证书”

2024-02-23

我正在维护一个网站及其移动应用程序(iOS 和 Android)。对于移动应用程序中的 Google 登录,我正在使用google-auth Python 包 https://github.com/googleapis/google-auth-library-python在服务器端。

从大约一个月前开始,我开始从服务器端收到与Google登录相关的错误报告。错误消息如下所示:

找不到密钥 ID 728f4016652079b9ed99861bb09bafc5a45baa86 的证书。

服务器端 Google Sign-In 身份验证后端如下这个文件 https://developers.google.com/identity/sign-in/android/backend-auth:

from google.oauth2 import id_token
from google.auth.transport import requests

# ...

try:
    # The following line may raise ValueError with message:
    # Certificate for key id xxxx not found.
    id_info = id_token.verify_oauth2_token(google_id_token, requests.Request())

    if id_info['aud'] not in VALID_CLIENT_IDS:
        logger.error('Invalid aud from Google ID token: %s', id_info['aud'])
        raise ValueError('Unverified audience.')
    # ...
except ValueError as exc:
    logger.error('Fail to verify Google ID token: %s', exc, extra={'request': request})

错误来自google.auth.jwt 模块 https://github.com/googleapis/google-auth-library-python/blob/master/google/auth/jwt.py#L226,根据 Google 公共证书列表验证 Google 颁发的 JWT 时。

深入研究 google-auth 代码 https://github.com/googleapis/google-auth-library-python/blob/master/google/oauth2/id_token.py#L139, 我理解了verify_oauth2_token()函数正在从 URL 获取 Google 公共证书https://www.googleapis.com/oauth2/v1/certs https://www.googleapis.com/oauth2/v1/certs。有时,对于从某些 Android 手机发送的某些 Google ID 令牌,似乎无法在该 URL 中找到密钥 ID。

以下是一些可能有用的其他详细信息:

  • iOS应用似乎没有这种问题。来自USER_AGENT标题,我可以看到错误仅发生在 Android 应用程序中(USER_AGENT=okhttp/3.11.0)。而且这种情况仅发生在部分 Android 设备上,并非全部。
  • 我想知道这种情况是否只发生在中国的 Android 手机上(例如,如果它们通过 VPN 连接)。所以我也检查了用户的IP地址。但事实证明,其中一些用户来自欧洲。
  • 某些密钥 ID 在服务器错误日志中一次又一次重复出现。例如,密钥 IDaa436c3f63b281ce0d976da0b51a34860ff960eb从11月初到现在(12月底),出现了几十次。
  • 我经常看到这个错误,每天好几次(10~30次)。

我的网站运行在以下环境:

  • 操作系统:Linux(CentOS 7)64位
  • Apache 2 与 mod_wsgi 4.5.24
  • Python 3.6.7 和 Django 2.1.2
  • google-auth 版本:尝试了 1.3.0 和 1.6.1

由于我无法用我的 iPhone 或 Android 手机(华为 P20,在法国购买)重现此问题,所以我完全陷入困境。

但是,我的一个朋友现在遇到了这个问题,他从香港购买了 Android 手机。这让我想到,对于某些国家/地区,Google 登录是否可能使用除公共证书之外的一些不同证书https://www.googleapis.com/oauth2/v1/certs https://www.googleapis.com/oauth2/v1/certs?

我不认为这是 google-auth 包中的错误。我想知道你们中是否有人听说过这个错误,并且可以给我一些关于其可能原因的提示?

提前致谢!


好吧,我终于想通了。我在这里发布我的发现,希望对其他人有帮助。

服务器端Python代码没有任何错误。失败的原因是客户端应用程序提交了过期的 Google ID 令牌。

这是我的 LoginActivity 的固定版本:

...

@OnClick(R.id.google_sign_in_button)
void loginWithGoogle() {
    //
    // If user has already signed in to our app with Google, sign him out first.
    //
    // NOTE: This step is required, or the ID token might not pass the server-side validation!
    //
    // After sign-in, we need to get the user's ID token issued and signed by Google, and send
    // it back to our server for validation.
    //
    // Google is rotating its OAuth2 certificate regularly, so an old ID token issued long time
    // ago by Google might not pass the server-side validation -- if the certificate used to
    // sign the ID token has expired.
    //
    // This may happen when user has already signed in to our app with Google. In such case,
    // the ID token we get from the user's Google account is obsolete. Our server will fail to
    // validate it, with the error message:
    //
    //     Fail to verify Google ID token: Certificate for key id xxx not found.
    //
    // Google recommends using the `silentSignIn` method for the already-signed-in user
    // (see step 2 of: https://developers.google.com/identity/sign-in/android/backend-auth).
    // For the sake of simplicity, we don't do that. Instead, we go directly to step 3
    // by signing user out, giving him the option to sign-in again.
    //
    final GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
    if (account != null) {
        // User has already signed in: Sign out and sign in again.
        // NOTE: THIS IS THE FIX TO MY PROBLEM.
        mGoogleSignInClient.signOut().addOnCompleteListener(this, new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                startGoogleSignInActivity();
            }
        });
    } else {
        // User is not yet signed in: Start the Google sign-in flow.
        startGoogleSignInActivity();
    }
}

private void startGoogleSignInActivity() {
    final Intent intent = mGoogleSignInClient.getSignInIntent();
    startActivityForResult(intent, REQUEST_LOGIN_WITH_GOOGLE);
}

关键点是:我需要检查用户是否已经使用 Google 登录。如果是,我需要注销用户并重新启动“使用 Google 登录”活动。

由于 Android 对 Google 帐户有本机支持,我想如果用户已经通过身份验证(在某些其他应用程序或系统范围内),操作系统可能会缓存用户的 Google 帐户。但该缓存帐户可能包含过期的 ID 令牌。强制用户注销并重新登录将为我提供一个全新的 ID 令牌。

这也解释了为什么我的iOS应用程序没有这个问题。因为iOS从不缓存用户的Google帐户。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Google 登录:使用 google-auth Python 包时“未找到密钥 ID xxxx 的证书” 的相关文章

  • 混合命名和未命名函数参数

    我有这个功能来验证 JWT 令牌 不是中间件 它说 package main import net http log fmt github com dgrijalva jwt go func ValidateToken w http Res
  • 我们如何在 google puppeteer 的无头 Chrome 中传递身份验证令牌?

    我想在 puppeteer 标头中传递身份验证令牌 JWT 以用于我的应用程序中使用无头 Chrome 的 pdf 视图 我们使用 React 作为我们的前端 UI 使用 puppeteer 我们可以生成 pdf 但是 pdf 的链接我们需
  • Google 登录 - 刷新时注销

    我进行了以下设置 service googleService q function q var self this this load function var deferred q defer gapi load auth2 functi
  • 如何在 C# MVC 中从 Google+ 登录迁移到 Google 登录

    我的网站允许用户使用其 Google 帐户注册并登录 我的 C MVC 应用程序使用 Microsoft AspNet Identity Owin 提供的模板功能 我收到了一封来自 Google 的电子邮件 称他们将关闭 Google 该电
  • JWT:slim v3 和 Android 中的身份验证

    我正在使用 Slim 框架将 JSON 返回到我的 Android 设备 我目前正在我的设备上登录 我使用 3 种不同的方式登录 Facebook Google 和帐户登录 当他进行帐户登录时 他可以注册一个新帐户或使用现有帐户登录 为了我
  • Google 服务帐户未获得日历 API 授权

    我正在尝试通过服务帐户连接到我们 G Suite 域上的所有日历 我创建了一个新项目 并在 API 和服务页面中启用了 Google Calendar API 我创建了一个 Google 服务帐户 A name 似乎适用的角色 生成的jso
  • 无状态 Spring JWT 应用程序 + EnableOAuth2Client

    我在这个解决方案上花费了 50 多个小时 非常感谢您的任何意见 我有一个使用 Angular Spring JWT 无状态身份验证 myApp 的 JHipster 4 x 生成的应用程序 我正在将经过身份验证的 myApp 用户的第 3
  • 无法使用 RS256 验证 JWT - 算法无效

    我正在尝试将 JWT Auth 从秘密短语移至 RS256 这是示例代码 import fs from fs import jwt from jsonwebtoken const private key fs readFileSync pr
  • 使用 v2.0 端点的声明中缺少 UPN

    我已经设置了一个类似于 Microsoft 的以下示例的项目 其中我有一个本机应用程序请求使用 v2 0 端点访问 Web api https github com azureadquickstarts appmodelv2 nativec
  • 使用 JWT 缺少授权标头

    我正在尝试设置 JSON Web 令牌以从移动应用程序与我的 php 后端进行通信 我可以请求一个令牌就好了 当我需要验证它 或向另一个端点发出请求 时 我使用以下格式设置授权标头 Bearer
  • 如何在 Webpack 5 中为 jsonwebtoken 填充缓冲区

    我正在升级到 Webpack 5 并且 jsonwebtoken 包存在问题 https github com auth0 node jsonwebtoken https github com auth0 node jsonwebtoken
  • Oauth2 Google 身份验证流程 - Next.JS / Express

    我正在使用 React Next Js 前端 并尝试通过 Google 的 Oauth2 策略实现身份验证 我对这个过程感到非常困惑 目前在客户端上 我有一个 Google 登录组件 其中包含客户端 ID 并且可以检索访问令牌
  • 使用 React 前端的 Django Google 登录

    这个问题可能非常简单 但我已经搜索了一段时间 但还没有找到确切的解决方案 我正在尝试使用 React 作为前端 使用 Django 作为后端来实现 Google Login 我到底该怎么做呢 我见过一些解决方案 其中将令牌发送到后端 然后后
  • 如何将 JWT 承载令牌添加到 API 的所有请求

    我正在尝试组建一个使用 Asp Net Core Identity Identity Server 4 和 Web API 项目的小项目 我的 MVC 项目已使用 IdS4 进行了正确身份验证 从中我获得了一个 JWT 然后我可以将其添加到
  • JJWT依赖混乱

    我继承了一个java项目 在POM xml中有这个
  • 页面刷新后如何注销用户?

    我正在跟进谷歌的指南 https developers google com identity sign in web sign in sign out a user注销用户 考虑到gapi auth2刷新页面后将是未定义的 我正在做 if
  • JWT Web 令牌加密 - SecurityAlgoritms.HmacSha256 与 SecurityAlgoritms.HmacSha256Signature

    用于基于令牌的身份验证Microsoft IdentityModel Tokens提供了可用于创建的安全算法列表SigningCredentials string secretKey MySuperSecretKey byte keybyt
  • 在浏览器上验证 JWT

    我一直在读关于JWT https jwt io 我知道它分为三个部分 即header payload and signature 我将哈希算法保留在标头中 将基本信息保留在有效负载中例如 姓名 年龄 职务 有效期等在有效负载中 然后这两个都
  • 如何在 access_token 中添加角色声明,目前它是在 id_token 中?

    我正在使用 PKCE 跟踪身份验证代码流 我的身份提供程序是 Azure Active Directory 我从应用程序注册创建了一个应用程序 客户端应用程序 在清单中 我添加了如下所示的 appRoles appRoles allowed
  • 单击关闭按钮后不显示 Google 一键登录 UI

    我正在尝试按照本指南使新的谷歌一键登录工作 https developers google com identity one tap web https developers google com identity one tap web

随机推荐

  • 在测试中的 Spring 环境中使用 @EnabledIf 和 spring.profiles.active 属性

    根据文档 https docs spring io spring framework docs current javadoc api org springframework test context junit jupiter Enabl
  • PHP 标签关闭——什么时候需要?

    推荐的是 http framework zend com manual en coding standard php file formatting html不应在文件末尾放置 PHP 结束标记 以避免出现各种不良错误 但是有没有什么情况需
  • 没有 Mac 的 Xamarin Visual Studio IOS 开发?

    我是一名 NET 开发人员 想用 C 编写 IOS 和 Android 应用程序 我读过有关 Xamarin for Visual Studio 的文章 它看起来很有趣 如果不是有点贵的话 您需要 Mac 来调试代码吗 您是否只需要一台联网
  • 将字符串从 datagridview 传递到另一种形式的文本框

    我设置了 2 个表单 第一个表单加载 datagridview 用户单击视图来选择他们想要的值 我可以在与 datagridview 相同的表单上获取消息框中显示的值 但是当我尝试将其传递到另一个表单时 它显示为 NULL 我如何让它显示在
  • Spring MVC 3:如何向 HTTP 404 错误的错误页面提供动态内容?

    我想要的是 我想为 HTTP 404 错误页面提供一个模型 我不想编写在 web xml 中指定的静态错误页面 而是使用 异常控制器 处理 HTTP 404 错误 我做了什么 从 web xml 中删除了错误页面标签
  • Spring工具套件中maven使用的settings.xml在哪里?

    我想设置 ftp 服务器以从 STS 进行部署 如下所述 http maven apache org plugins maven deploy plugin examples deploy ftp html http maven apach
  • 改造多个 POST 参数

    我正在尝试向需要 2 组信息的服务器提交调用 这是我的界面 POST venues get by location void getByLocation Body Coordinates coordinates Body MaxDistan
  • React-native:如何控制键盘向上推

    该应用程序的结构相当简单 底部有一个搜索栏 一个列表视图和react native tabs 问题 如果我点击 Android 上的搜索栏 它会将整个应用程序向上推 因此我可以直接在键盘上看到选项卡 但在 iOS 上 键盘覆盖了整个应用程序
  • 调用从 EDN 文件读取的函数

    我有一个 EDN 配置文件 其中的条目引用现有功能 例如 attribute modules content class lohan extractors content process schema class lohan extract
  • 查询超慢...我做错了什么?

    你们太棒了 在过去的几天里 我已经在这里发帖两次 作为一个新用户 我对这些帮助感到震惊 因此 我想我应该采用软件中最慢的查询 看看是否有人可以帮助我加快速度 我使用此查询作为视图 因此速度快很重要 但事实并非如此 首先 我有一个联系人表 用
  • 我们应该在数据库表命名约定中使用前缀吗?

    我们正在工作中的开发团队决定表 列 过程等的命名约定 单复数表命名已经决定了 我们使用单数 我们正在讨论是否为每个表名使用前缀 我想阅读有关是否使用前缀以及原因的建议 它是否提供任何安全性 至少为可能的入侵者多了一个障碍 我认为用前缀命名它
  • 通过 Python 在 Selenium 中使用 WebDriverWait for link_text “TypeError: 'str' object is not callable”

    这是我在 Stack Overflow 上的第一篇文章 我一直在浏览和搜索这个问题的每一个可能的答案 我想在这一点上我应该问一个问题 因为我已经在这堵墙上呆了好几天了 我目前正在使用 Python 中的 Selenium 开发一个网络抓取项
  • 强制编码风格[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 几年前 当我开始一个小型开发项目时 我和其他开发人员坐下来就折衷的大括号和缩进样式达成了一致 它不是任何人的最爱 但却是没有人真正讨厌的东西 我
  • 如何在 PHP 中查找单词组合

    我有一个数组 new array array c a m t p 现在我想找到单词表中存在的单词组合 我曾尝试实现但没有成功 这是我的 php 代码 words array set powerSet new array 2 mysql ne
  • Webstorm 关闭匿名函数声明中的新空格

    例如我有这个 exports getsertHexId function table hex Webstorm 8 的自动缩进在关键字之间创建空格function和开括号 其设置空间选项包括 函数声明括号 函数调用括号 如果 括号 很困惑
  • 如何定期唤醒我的应用程序

    我想在Android中做一个功能 比如提醒 我想在我的应用程序 活动未运行或者其 UI 不可见时启动它 它类似于提醒 在所需的时间唤醒应用程序 我没有使用过任何类型的后台任务或服务 所以我不知道该怎么办 或者我应该学习什么类型的课程或演示
  • 在 SQLite 中的 GROUP_CONCAT 函数中使用 ORDER BY 子句

    我不认为我可以使用ORDER BY里面的子句GROUP CONCAT功能 有谁知道一种棘手的方法来完成这种行为SQLite 我看到了这个question https stackoverflow com questions 1897352 s
  • 如何将由东北坐标和西南坐标组成的特定边界拟合到可见地图视图中?

    我需要在地图内适应特定的边界 我通过调用谷歌地理编码器并读取视口属性来获取边界 如下所示 northeast lat 30 4212235 lng 97 486942 southwest lat 30 1128403 lng 97 9991
  • 在加载的 ELF(.so 共享库)中挂钩并替换导出函数

    我正在编写一些 C 代码来将 so ELF 共享库 的某些函数加载到内存中 我的 C 代码应该能够重定向另一个加载到应用程序 程序内存中的 so 库的导出函数 这里有一些详细说明 Android 应用程序将加载多个 so 文件 我的 C 代
  • Google 登录:使用 google-auth Python 包时“未找到密钥 ID xxxx 的证书”

    我正在维护一个网站及其移动应用程序 iOS 和 Android 对于移动应用程序中的 Google 登录 我正在使用google auth Python 包 https github com googleapis google auth l