【问题标题】:How to Securely Convert Open ID Connect Tokens to Cookies如何安全地将 Open ID Connect 令牌转换为 Cookie
【发布时间】:2020-05-28 14:37:41
【问题描述】:

我们有一个客户端应用程序,希望通过 OIDC 启用 SSO。客户端应用程序是具有专用后端 API 的 SPA。目前,身份验证是通过 cookie 实现的,并且在后端根据 Auth_Cookie 的用户执行授权。 OIDC 身份验证完成后,我们希望继续利用这些现有的基于本地 cookie 的代码/逻辑,这也避免了将令牌与 SPA 一起存储的需要。

在完成 Auth Code PKCE 流程后,前端 SPA 将直接从 OP 的 /token 端点接收 ID_Token 和 Access_Token。要从 ID/Access_Token 到 Auth_Cookie,方法可能是:

  1. 前端 SPA 调用后端 API 进行身份验证(例如 /authenticate),传递 Access_Token
  2. 后端验证 Access_Token 并发出 Auth_Cookie

由于 ID_Token 仅适用于客户端应用程序(在此上下文中是前端 SPA),我的假设是它在此序列中没有任何作用(尽管从逻辑上讲,您会认为调用后端 - end API 的/authenticate 端点应该提供类似于凭据的东西,例如 ID_Token)。

上述方法是否有意义,是否存在任何安全问题/担忧?是否有替代/更好的方法可以将前端 OIDC 身份验证的上下文转换为 cookie?

任何见解或帮助将不胜感激。谢谢。

【问题讨论】:

    标签: oauth-2.0 single-sign-on single-page-application access-token openid-connect


    【解决方案1】:

    我认为让您的后端进程成为身份验证重定向会更容易 - 使其成为 OAuth2 客户端而不是您的 SPA。您的 SPA 不需要令牌,也无需将访问令牌传输到后端。接收授权码的后端处理程序将获取令牌并创建授权 cookie(带有所有安全参数)。

    如果您需要将您的 SPA 保留为 OAuth2 客户端,那么您提出的解决方案可能很好。

    【讨论】:

    • 感谢您的回复!正如您所建议的,我最初的想法是应用标准的身份验证代码流,后端处理 auth_code/token 交换——它会工作得很好。但是,在阅读了现在推荐用于所有场景 (tools.ietf.org/html/…) 的 Auth Code + PKCE 之后,我的决定发生了变化。我们可以使用Auth Code + PKCE,后端完成令牌交换吗?如果是,则前端 SPA 启动 OIDC 流程,而后端完成它。前端或后端会被视为客户端应用程序吗?
    • PKCE 类似于“公共客户的客户机密”。由于基于浏览器和本机(移动、桌面)应用程序无法保密,因此它们使用 PKCE。服务器应用程序可以使用密钥并且它具有相同的目的 - 即使身份验证代码被盗,如果没有客户端密钥或 code_verifier 也无法使用它。如果您将后端用作客户端,则后端应启动身份验证重定向,因为它知道其重定向 URI 并可以生成 state 值(并稍后验证)。
    • 我喜欢你非常谨慎地思考谢尔曼的问题。我已经用有关令牌存储的更多信息更新了我的原始答案。没有一刀切的答案,但希望我的反馈能让您了解主要因素。
    • @JánHalaša 我的理解也是,反向通道 client_secret 应该达到与 PKCE 相同的结果,但只是不确定为什么现在推荐用于所有场景。这是有道理的,后端将被视为客户端,因为它将是发起重定向的那个(实际上不是 SPA,正如我错误地认为的那样)。
    • 如果所有客户端都必须使用 PKCE,那么即使您的后端作为客户端,您也应该能够使用它——连同它的客户端密码。我不知道为什么它对所有客户端都是强制性的,但同时使用秘密和 PKCE 验证器比仅使用 PKCE 更安全,因为 PKCE 哈希算法理论上可能会被攻击者破坏。
    【解决方案2】:

    感谢 Sherman 的有趣讨论 - 你让我意识到我做的不太对,所以我更新了一些东西。

    选项 1 - Cookie

    这很有意义,尤其是在您还不需要跨域功能的情况下。完全致力于无 cookie 也可能需要大量工作。

    选项 2 - 使用存储在内存中的令牌的无 COOKILES

    可以构建一个完全无 cookie 的 SPA,并且仍然可以处理可用性问题,例如用户无需重新登录即可刷新页面。不过,它有一个授权服务器的先决条件,它正确支持 prompt=none 参数。

    选项 3 - 将令牌存储在 HTML5 会话存储中的无 COOKILES

    正如我们所讨论的,许多人认为这并不安全,因此最好尽可能避免。如果您的授权服务器不支持 prompt=none,您可以考虑使用它。

    【讨论】:

    • 感谢您的回复和链接您的博客 - 这是一本非常有用且内容丰富的读物,尤其是关于无 cookie 方法的好处的部分。现在,客户端应用程序实际上已经部分采用 OAuth2/OIDC,cookie 本身存储了加密的 JWT。围绕 cookie 的其他安全措施已经到位,以防止常见的漏洞,例如 XSS 或 CSRF。我们采用 cookie 方法的主要原因是因为它似乎是在 SPA 上安全存储令牌的最简单和最安全的方式。
    • 好的 - 值得澄清您对在浏览器中使用令牌的确切担忧 - 对您对此的想法感兴趣。 guidance for browser based apps 对令牌没有问题,尽管我意识到并不是每个人都对此感到满意。
    • 您引用的链接摘录:在浏览器中处理访问令牌的另一个问题是,没有安全的存储机制可以让 JavaScript 代码保留访问令牌以供以后在 API 中使用要求。使用 OAuth 流会导致 JavaScript 代码获取访问令牌,需要将其存储在某处,然后检索它以发出 API 请求。相反,更安全的设计是在 JavaScript 应用程序和 API 之间使用仅 HTTP cookie,这样 JavaScript 代码就无法访问 cookie 值本身。
    • 我们采用了那里建议的方法,使用仅 HTTP cookie 来存储/传输令牌。当然,我们知道会有一些限制(在您的博客中也有说明),但我们希望确保令牌可以安全地从 SPA 存储/传输到后端 API。
    • 当时使用 cookie 非常有意义。最后一条评论是,您让我意识到我可以通过仅将令牌存储在 SPA 内存中来更新我的样本以更安全,因此我已更新到该模型。请注意,仍然有一种方法可以处理用户重新加载页面。上面的详细信息以备将来使用。
    猜你喜欢
    • 2013-01-27
    • 1970-01-01
    • 2020-04-17
    • 1970-01-01
    • 2021-09-14
    • 2020-10-09
    • 2019-09-20
    • 2020-11-12
    • 2012-08-12
    相关资源
    最近更新 更多