【问题标题】:OAuth2 process and best practices for private apps私有应用的 OAuth2 流程和最佳实践
【发布时间】:2020-08-07 09:15:29
【问题描述】:

请耐心等待我解释我的问题和我找到的解决方案/指南。

描述:在我的公司,我们有一个产品有多个模块。每个模块都是其独立的后端和前端。我们有 JavaEE/JakartaEE 和 JAX-RS 作为我们的后端堆栈和 React 作为我们的前端。到目前为止,我们通过会话使用 JavaEE Security Basic Authentication,但是由于产品在不断发展,我们需要移动客户端并允许第三方访问数据,因此我们决定集成 OAuth2/OpenID Connect进入我们的应用程序。

由于有多种实现提供 OAuth2 功能,我们目前正在研究一些可用的选项。 (例如KeycloakORY Hydra)。我们将选择的决定取决于我们想要做多少工作来改变应用程序的现有结构,我们如何处理数据库中的用户。但无论我们选择哪种实施方式,我们都会遇到类似的问题。

问题

  1. React 应用程序如何处理登录过程和令牌存储?

    每个文档都说:如果用户没有登录,他/她会被重定向到登录页面。在登录并同意后,他将被重定向回应用程序(显然在完成 oauth2 工作流程之后),使用资源服务器的访问/ID 令牌和/或刷新访问/ID 令牌的刷新令牌。

    现在我不清楚的是:

    • 由于这是我们自己的 React 应用程序,我们不想显示同意屏幕,就像在 Microsoft/Google 等应用程序中您看不到任何内容一样。我想这可以通过在请求本身中设置一个值,或者根据客户端 ID 跳过同意屏幕来实现,但我只是想确定一下。

    • 接下来我在哪里存储访问和刷新令牌?访问令牌应作为承载令牌与每个请求一起发送。因此它可以存储在本地存储中,因为它们是短暂的,但刷新令牌应该安全存储。就像在安全的 http cookie 中一样?如果是这种情况,那么服务器必须设置它。如果这是正确的,流程会是这样吗?

      Our React App (Not logged In) --> Login Page (Another React Page) --> User Enters Credentials --> Java Backend --> Authenticates the user --> Initiate the OAuth2 process --> Get the Access and Refresh Tokens --> Set them as secure Cookies -- > Return the authenticated response to frontend with the cookies --> Login Page redirects to the previous page --> User continues with the app

      这感觉不正确。在这种情况下,PKCE 将如何提供帮助?

  2. 假设我上面写的是正确的,当用户从我们自己的应用程序或第三方应用程序登录时,我将需要不同的登录流程。但是,这可以通过检查客户端 ID 或禁用第三方客户端的密码流来确定。

  3. 同样适用于刷新令牌流。因为对于我自己的应用程序,我必须设置 cookie,对于第三方,这必须直接来自 OAuth 服务器

我已阅读/研究过的资源:

https://gist.github.com/mziwisky/10079157

How does OAuth work?

编辑:添加更多我已阅读的链接

What is the purpose of implicit grant

Best practices for session management

RESTful Authentication

当然还有来自 Keycloak 和 ORY Hydra 的各种著作和例子。

我目前正在同时尝试 Keycloak 和 ORY Hydra,以确定哪个更适合我们的需求。

提前谢谢大家!

【问题讨论】:

    标签: security authentication oauth oauth-2.0 openid-connect


    【解决方案1】:
    1. 您不必显示同意屏幕。下面是一个使用授权代码授予进行身份验证的 React 应用示例:https://fusionauth.io/blog/2020/03/10/securely-implement-oauth-in-react(完全披露,这是在我雇主的网站上,但可以与任何符合 OAuth2 的身份服务器一起使用)。

    简短的回答是,您最好避免隐式授权,并将访问和刷新令牌存储在一些中间件中,而不是浏览器中。链接中的示例使用 100 行快速服务器并将这些令牌存储在会话中。

    我写了一些关于 PKCE 的文章。摘录:

    代码交换证明密钥 (PKCE) RFC 于 2015 年发布,扩展了授权代码授权,以防止在部分授权流程通过非 TLS 连接发生时受到攻击。例如,在本机应用程序的组件之间。如果 TLS 存在漏洞,或者路由器固件遭到破坏并且正在欺骗 DNS 或从 TLS 降级到 HTTP,也可能发生这种攻击。 PKCE 需要将额外的一次性代码发送到 OAuth 服务器。这用于验证请求没有被拦截或修改。

    1. 以下是您拥有的各种 OAuth 选项的细分(同样,这是在我雇主的网站上,但适用于任何符合 OAuth2 的身份服务器):https://fusionauth.io/learn/expert-advice/authentication/login-authentication-workflows 您可以为不同的客户端允许不同的流程。例如,您可以为第三方使用授权代码授权,为您自己的应用程序使用资源所有者密码凭据授权(本质上是用户名和密码)。

    我不确定我是否回答了您的所有问题,但我希望其中的一些对您有所帮助。

    【讨论】:

    • 如果我理解正确的话,那么示例中使用的中间件实际上就是我们的后端。它的工作方式与我在问题中描述的相同。前端将用户发送到登录页面,接收代码,将其发送到后端,后端将此代码发送到 oauth 服务器,并接收令牌,在会话中设置它们并将用户重定向到他/她想要的位置去吧。
    • 差不多:前端将用户发送到登录页面,后端从OAuth服务器接收一个代码,后端将此代码发送到oauth服务器,并接收访问令牌,将它们设置在一个会话并将用户重定向到他/她想去的地方。然后可以通过中间件代理对需要访问令牌的经过身份验证的 API 的任何调用。令牌完全被排除在反应代码之外。
    【解决方案2】:

    应该咨询OAuth 2.0 Security Best Current Practice。尽管它仍然是一个“互联网草案”,但它已经成熟并已被多个供应商实施。

    一般来说,无论使用 Bearer 令牌还是 JWT,都建议使用带有 PKCE 流的 OAuth 2.0 授权代码。

    你也应该考虑阅读WebAuthn(没有密码的地方)

    【讨论】:

    • 阅读最佳实践文档绝对是个好主意。其中一些建议将纳入 OAuth 2.1。
    猜你喜欢
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多