如何在使用 oauth 的同时使用 cookie?
How to make use of cookies while still using oauth?
目前我们有一个 SPA 和 API,SPA 发送 email/password 到 API 和 API returns 响应有两个安全/HttpOnly/Lax饼干。第一个 cookie 是具有短 TTL 的访问令牌(自定义 JWT 存储在 cookie 中),第二个是具有长 TTL 的刷新令牌。 SPA 使用这些 cookie 向 API 发出请求,并且 API 验证访问令牌是否过期并在需要时通过从 cookie 读取刷新令牌并设置新的访问令牌 cookie 来刷新它。
因为我们很快就会有更多 API 客户端(移动应用程序和 machine-to-machine 客户端),所以我们想利用 OAUTH 来标准化授权。在做了一些研究之后,OAUTH 似乎对除 SPA 之外的所有东西都有好处,因为在浏览器中存储刷新令牌是不安全的,应该避免。对于移动设备,它似乎是 secure-enough,因为刷新令牌可以存储在 OS 钥匙串或类似的东西中。
因此,仍然为 SPA 使用安全 cookie 并为移动和 machine-to-machine 使用访问令牌是合理的。为了保持一致,我们希望将常规的 oauth 访问/刷新令牌存储在 cookie 中,并在 API 端以与授权 header 中传递的承载令牌相同的方式处理。我们的 SPA 和 API 在同一个域(不同的子域)中,这更多是关于一个 API 和许多客户的情况。
我们正在考虑 SPA 的以下选项:
只需使用资源所有者密码流程 - 虽然不推荐,但可以从高度信任的“客户端”使用 - 在我们的例子中,SPA 将凭证发送到 API 和 API 调用 oauth 服务器(带有客户端 ID、秘密和用户凭据)以获取访问令牌和刷新令牌,然后 return 将安全 cookie 中的这些令牌返回给 SPA。
我不确定这是否可行,但我正在考虑在 SPA 和 API 之间拆分授权代码流。 SPA 重定向到 oauth 授权页面,用户在托管登录页面上登录,然后使用授权代码重定向回 SPA。然后 SPA 不是在 oauth 服务器上调用 /oauth/token,而是将授权代码发送到 API 并且 API 最后调用 oauth 服务器上的 /oauth/token 以获取访问令牌和刷新令牌并存储它在 cookie 中。它会以任何方式降低安全性吗?
还有其他选择吗?`
1.使用资源所有者密码凭据 (ropc)
避免 ROPC 授权。此赠款旨在用于 OAuth 的遗留解决方案和安全最佳实践 RFC 不鼓励使用(例如:- rfc6819 :section-4.4.3, draft-ietf-oauth-security-topics-19 :section-2.4 ) . Further, this will get deprecated with OAuth 2.1
2。拆分解决方案 - 带后端的 SPA
您已经有了 cookie,我假设它们是通过后端的一些验证(例如:- 用于建立 cookie 的有效访问令牌)启动的。因此,如果您的应用程序架构支持或可以修改以支持基于后端的令牌获取(而不是仅前端授权代码流),请寻求该解决方案。
优点 - 您不在浏览器中存储任何令牌,令牌可以存储在安全的后端中。 Cookie 过期时间可以映射到令牌生命周期。
3。 Pure SPA : session storage or local storage
如果您不能拥有 SPA 的后端并且不想保留长期存在的刷新令牌(例如:- 记住我这种功能),您可以使用会话存储或本地存储(取决于用户体验和安全要求)。
这里要考虑的事情是正确管理存储在浏览器存储中的令牌(例如:- 在 SPA 退出时清除本地存储)和在 API 时刷新访问令牌returns 401。此外,使用短暂的刷新令牌。
我会选择你的两个选项 2,尽管在获得 SPA 和 API 解决方案方面有一些微妙之处。这些应该是最终结果:
- 在您使用 HTTP Only SameSite=strict cookies 的浏览器中
- 您可以使用 React 等技术进行开发
- Web 和移动客户端可以调用相同的 API 路由
- 如果您愿意,可以将 SPA 部署到 CDN
在 Curity,我们有关于这种方法的一些详细资源,我们称之为 Token Handler Pattern. It is basically just website security via an API. I provided an architectural overview a while back in this blog post。
虽然在部署方面这是一个棘手的流程,所以不妨看看 React SPA Example。另请注意,这适用于任何 OAuth 提供程序,并且是一种设计模式,而不是供应商解决方案。
目前我们有一个 SPA 和 API,SPA 发送 email/password 到 API 和 API returns 响应有两个安全/HttpOnly/Lax饼干。第一个 cookie 是具有短 TTL 的访问令牌(自定义 JWT 存储在 cookie 中),第二个是具有长 TTL 的刷新令牌。 SPA 使用这些 cookie 向 API 发出请求,并且 API 验证访问令牌是否过期并在需要时通过从 cookie 读取刷新令牌并设置新的访问令牌 cookie 来刷新它。
因为我们很快就会有更多 API 客户端(移动应用程序和 machine-to-machine 客户端),所以我们想利用 OAUTH 来标准化授权。在做了一些研究之后,OAUTH 似乎对除 SPA 之外的所有东西都有好处,因为在浏览器中存储刷新令牌是不安全的,应该避免。对于移动设备,它似乎是 secure-enough,因为刷新令牌可以存储在 OS 钥匙串或类似的东西中。
因此,仍然为 SPA 使用安全 cookie 并为移动和 machine-to-machine 使用访问令牌是合理的。为了保持一致,我们希望将常规的 oauth 访问/刷新令牌存储在 cookie 中,并在 API 端以与授权 header 中传递的承载令牌相同的方式处理。我们的 SPA 和 API 在同一个域(不同的子域)中,这更多是关于一个 API 和许多客户的情况。
我们正在考虑 SPA 的以下选项:
只需使用资源所有者密码流程 - 虽然不推荐,但可以从高度信任的“客户端”使用 - 在我们的例子中,SPA 将凭证发送到 API 和 API 调用 oauth 服务器(带有客户端 ID、秘密和用户凭据)以获取访问令牌和刷新令牌,然后 return 将安全 cookie 中的这些令牌返回给 SPA。
我不确定这是否可行,但我正在考虑在 SPA 和 API 之间拆分授权代码流。 SPA 重定向到 oauth 授权页面,用户在托管登录页面上登录,然后使用授权代码重定向回 SPA。然后 SPA 不是在 oauth 服务器上调用 /oauth/token,而是将授权代码发送到 API 并且 API 最后调用 oauth 服务器上的 /oauth/token 以获取访问令牌和刷新令牌并存储它在 cookie 中。它会以任何方式降低安全性吗?
还有其他选择吗?`
1.使用资源所有者密码凭据 (ropc)
避免 ROPC 授权。此赠款旨在用于 OAuth 的遗留解决方案和安全最佳实践 RFC 不鼓励使用(例如:- rfc6819 :section-4.4.3, draft-ietf-oauth-security-topics-19 :section-2.4 ) . Further, this will get deprecated with OAuth 2.1
2。拆分解决方案 - 带后端的 SPA
您已经有了 cookie,我假设它们是通过后端的一些验证(例如:- 用于建立 cookie 的有效访问令牌)启动的。因此,如果您的应用程序架构支持或可以修改以支持基于后端的令牌获取(而不是仅前端授权代码流),请寻求该解决方案。
优点 - 您不在浏览器中存储任何令牌,令牌可以存储在安全的后端中。 Cookie 过期时间可以映射到令牌生命周期。
3。 Pure SPA : session storage or local storage
如果您不能拥有 SPA 的后端并且不想保留长期存在的刷新令牌(例如:- 记住我这种功能),您可以使用会话存储或本地存储(取决于用户体验和安全要求)。
这里要考虑的事情是正确管理存储在浏览器存储中的令牌(例如:- 在 SPA 退出时清除本地存储)和在 API 时刷新访问令牌returns 401。此外,使用短暂的刷新令牌。
我会选择你的两个选项 2,尽管在获得 SPA 和 API 解决方案方面有一些微妙之处。这些应该是最终结果:
- 在您使用 HTTP Only SameSite=strict cookies 的浏览器中
- 您可以使用 React 等技术进行开发
- Web 和移动客户端可以调用相同的 API 路由
- 如果您愿意,可以将 SPA 部署到 CDN
在 Curity,我们有关于这种方法的一些详细资源,我们称之为 Token Handler Pattern. It is basically just website security via an API. I provided an architectural overview a while back in this blog post。
虽然在部署方面这是一个棘手的流程,所以不妨看看 React SPA Example。另请注意,这适用于任何 OAuth 提供程序,并且是一种设计模式,而不是供应商解决方案。