Google OAuth2 流程和 id_token 刷新

Chr*_*isV 5 oauth-2.0 jwt angularjs google-oauth

我在以正确的方式实施 OAuth 时遇到了麻烦。我使用客户端/API 架构(前端为 Angular,后端为 Node.js),并且我希望用户仅使用 Google OAuth 身份验证进行登录。

这是我认为目前正确的方法(如果我误解了什么,请告诉我):

  • Angular 打开 Google 弹出窗口询问用户同意。
  • 一旦用户同意,Google 授权服务器就会向 Angular 发送回一个验证码。
  • 该验证码被转发到 API 端点。
  • 然后,API 要求 Google 授权服务器将此代码交换为 access_token、id_token 和 refresh_token。
  • Google 发送这 3 个令牌。
  • API 使用 access_token 从 Google API 检索用户
  • API 保留用户

这是一个小难题,在我看来,access_token和refresh_token应该存储到数据库中,id_token应该发送回Angular客户端。这样,它将允许 API 请求 Google API 中的资源,并且如果令牌过期,由于刷新令牌,它仍然可以请求新令牌。在客户端,id_token 嵌入在所有请求中,从而允许 API 识别客户端并使用来自https://www.googleapis.com/oauth2/v3/certs的 Google 证书验证其身份验证。

假设这是使用令牌的正确方法,由于客户端没有任何刷新令牌,我该如何处理 id_token 过期问题?

谢谢 !

pfo*_*oti 0

我的做法略有不同(尽管我有相同的基本架构)。

  • Angular 决定用户需要登录并显示登录弹出窗口。
  • 登录弹出窗口中的 url 不是Angular 提供服务,而是直接从后端服务器运行:/auth/google。(我个人使用 hapijs 和 Bell)。
  • /auth/google由响铃插件提供服务并启动 OAUTH 舞蹈。
  • OAUTH 舞蹈的结束导致我的节点服务器生成本地令牌(我只是生成随机字节并将它们存储在映射到用户 ID 的 Redis 中)
  • 因为初始登录弹出窗口是由 创建的window.open,所以成功页面(在 api 端生成,而不是在 Angular 中生成)可用于将window.opener.postMessage令牌传回 Angular 运行时。

这样,我所有敏感的 google 凭据(用户的 oauth 令牌、刷新令牌(如果需要)以及我的应用程序的 api ID 和密钥)仅位于服务器上,除了在 OAUTH 舞蹈接力期间(当它们在 URL 字符串中时)客户端重定向。这是相当安全的。

然后,对于与 api 的所有实际用户交互,我使用在第四步中生成的令牌进行身份验证。如果你愿意的话,这可以是 JWT,但我不会那样做;我只是使用 redis 从 'longrandostring' -> userId 进行映射。例如,如果我擦除存储了所有令牌的 Redis 数据库,那么我可以强制每个人重新登录,或者我可以编写一个 lua 脚本来删除映射到某个用户 ID 的所有条目。

如果您需要刷新令牌,可以access_type=offline在初始请求中设置为oauth2/auth,并且您将获得刷新令牌作为响应的一部分,除非您之前已获得刷新令牌。然后,您可以将其保留在服务器端并根据需要获取新的访问令牌。如果您approval_prompt=force也进行了设置,您将强制一个新的同意屏幕并保证获得刷新令牌(但是在向用户授予少量刷新令牌后,较旧的刷新令牌会在同一应用程序上过期,因此最好仅在确实需要时才请求它们)需要)。