如何使 Google 登录令牌的有效期超过 1 小时?

Posted

技术标签:

【中文标题】如何使 Google 登录令牌的有效期超过 1 小时?【英文标题】:How to make Google sign-in token valid for longer than 1 hour? 【发布时间】:2015-12-30 09:39:11 【问题描述】:

我已经成功实现了谷歌登录。

我能够对用户进行身份验证,并作为响应收到令牌。但是令牌会在 1 小时后过期。

expires_in: "3600"

我尝试在文档中搜索 - https://developers.google.com/identity/sign-in/web/reference - 但找不到延长令牌寿命的参数。


我实际上想要做什么?

https://developers.google.com/identity/sign-in/web/backend-auth

用户成功登录后,使用 HTTPS 将用户的 ID 令牌发送到您的服务器

我正在向服务器发送每个请求的令牌:

endpoint/get?access_token=" + access_token

然后在服务器上我调用https://www.googleapis.com/oauth2/v3/tokeninfo

所以我有一个令牌,每个请求都经过身份验证,但在工作 1 小时后,tokeninfo 方法返回 false,我需要重新验证用户。

在我的代码中,我通过存储所有历史 access_tokens 来规避这一点,如果客户端使用旧令牌,我检查历史数据并使用 refresh_token 手动发出新令牌 (我的权限之一是授予离线访问权限)


所以是的,我很想知道:

如何延长access_token的使用寿命?

鉴于生命周期有限,如何确保请求在后端经过身份验证?

【问题讨论】:

【参考方案1】:

正如@DaImTo 所说,您无法延长 access_token 的寿命。您可以使用 refresh_token 获得一个新的令牌,但通常如果您尝试做这个客户端并拥有一个服务器,您应该重新考虑您的方法。

听起来您在这里进行了两次“身份验证”——客户端针对服务器进行身份验证,服务器针对 Google 服务进行身份验证。现在,服务器应该持有刷新令牌——因此它总是可以针对 Google 重新进行身份验证。听起来您正在努力解决如何在 auth_token 超时后针对服务器验证您的客户端。

一般情况下,客户端不应将 access_token 和 refresh_token 发送到服务器。它的作用是在第一次登录期间,客户端获得一个一次性代码(来自 Google),并将其交给服务器。服务器使用它与 Google 对话并获取 access_token 和 refresh_token,确认用户已通过身份验证,然后将某些内容(通常是 cookie)发送回客户端说“好的,我已经验证了你。这是你如何保持在我们接下来的谈话中验证自己的身份。”

后面的动作非常标准,与 oauth 本身无关。然后客户端和服务器像往常一样进行通信 - 根本没有交换任何 oauth 内容,您依靠 cookie(或等效项)来保持客户端-服务器身份验证。服务器继续使用身份验证令牌和刷新令牌与 Google 对话。

https://developers.google.com/identity/sign-in/web/server-side-flow 我认为这是目前最好的指南。或者至少它是我目前能找到的最好的。至少它有一个很好的图表。

关键是您正在与服务器交换名称精美的“代码”(我称之为“一次性代码”)。完成此操作后,服务器会通过 Google 对您进行身份验证 - 然后它具有访问/刷新令牌,您无需通过这些令牌即可与服务器通信。

【讨论】:

感谢您花时间为我澄清这一点。 “依赖 cookie” - 我错过了那个重要的部分(在当前版本中依赖于 access_tokens 我很困惑:cookie 是在用户登录后交付的,还是必须执行更多步骤? 服务器在从客户端获取“代码”并与谷歌的服务器验证代码后会发送一个cookie。 cookie 位于 OAuth 本身之外,是为了方便客户端-服务器通信。 如果我不想依赖 cookie 怎么办?我想使用“不记名令牌”方案。很多时候让服务器完全无状态(不依赖于会话)是可取的,尤其是在使用无服务器时。使用 cookie 的另一个缺点是,如果用户在他们的浏览器中启用了“安全浏览”而禁用了 cookie,那么您的网站就会完全中断。 假设 Google 使这不容易实现(令牌生命周期短),因为他们不希望您将它们用作 JWT 服务器,而只是一个简单的一次性身份验证平台。【参考方案2】:

访问令牌是短暂的,只能持续一小时,这不是您可以延长的。

您需要做的是获取刷新令牌并获取新的访问令牌。

示例:

您获取从初始请求中获得的 refresh_token 并将其通过 HTTP 发布到:注意:grant_type=refresh_token

https://accounts.google.com/o/oauth2/token client_id=ClientId.apps.googleusercontent.com&client_secret=ClientSecret&refresh_token=1/ffYmfI0sjR54Ft9oupubLzrJhD1hZS5tWQcyAvNECCA&grant_type=refresh_token

回复


"access_token" : "ya29.1.AADtN_XK16As2ZHlScqOxGtntIlevNcasMSPwGiE3pe5ANZfrmJTcsI3ZtAjv4sDrPDRnQ",
"token_type" : "Bearer",
"expires_in" : 3600

【讨论】:

“我检查历史数据并使用 refresh_token 手动发布新令牌” - 似乎这是我已经在使用的东西 - 我不确定是否这是正确的方法:1)它要求我存储过时的令牌 2)任何拥有历史令牌的人都会自动刷新到新的令牌......好吧 - 至少现在我知道令牌是短暂的并且无法扩展所以我应该问一个更好的问题——服务器端如何知道何时refresh_token 它要求您存储不会过时的“刷新令牌”,因为只要用户不撤销您的访问权限,它就可以工作。没有理由存储访问令牌,只需在需要时获取一个新令牌。您只需要记住在访问令牌过期之前刷新它。服务器端可能不知道何时需要刷新它,这取决于开发人员将其添加到代码中的时间来刷新它。您在这里使用什么语言? 我存储refresh_token。我使用node.jsFirebase,这是我的验证码:gist.github.com/stefek99/bafee8492128c63aa572 ••• “没有理由存储access_token - 为什么我存储access_token ?假设服务器收到一个请求并且access_token 无效(TTL 已过期)。在这一点上,我不知道该怎么办。通过检查access_token 以前是否有效,我可以刷新它...一定有更好的方法,这就是我首先问这个问题的原因:) "假设服务器收到一个请求并且 access_token 无效(TTL 过期)。此时我不知道该怎么办。"使用刷新令牌请求新的访问令牌?希望我们可以聊天,我认为你让这件事变得更难了。 希望我们可以聊天 :) 反正我在工作,我的笔记本电脑在家里...我会进行一些实验(稍后)...我的问题在一张图片中:@987654323 @••• 我知道我可以使用refresh_token 请求access_token - 但是安全性呢?任何人都可以摆弄对服务器的请求并可能获得不属于他们的令牌...tokeninfo - 过期时只返回“过期”并且服务器不应该信任来自客户端的任何输入,我不愿意将新的access_token 返还给任何人 :)

以上是关于如何使 Google 登录令牌的有效期超过 1 小时?的主要内容,如果未能解决你的问题,请参考以下文章

Retrofit2:如何使授权令牌标头动态化?

在 Android 上集成 Google 登录时如何在 ID 令牌过期后刷新?

用于网站的 Google 登录 - 如何获取令牌

Android:如何通过 Google 登录 API 获取刷新令牌?

Google Oauth2 verifyIdToken 返回具有有效 id_token 的无效令牌签名

如果生成了新的 JWT,如何使 JWT 过期