【问题标题】:Spring boot OIDC Refresh token scenarioSpring boot OIDC 刷新令牌场景
【发布时间】:2020-07-17 20:51:01
【问题描述】:

我们目前正在开发具有以下组件的微服务架构的应用程序,如下图所示,一切正常。但是需要对以下几点进行澄清。

  1. 为了保护 Gateway 和 Deep 微服务之间的通信,我们传递 IDToken 并在每个微服务级别对其进行验证,但是一旦 IDtoken 过期服务返回 401 状态代码,然后在 Ui 上我们触发授权流程,最终导致全页面刷新,如果用户在在提交非常大的表单的过程中,根据 OIDC 规范,所有数据都将丢失,我们无法刷新 ID 令牌,因此不确定如何处理这种情况。
  2. 1234563
  3. 或者我们在这里遗漏了一些东西并且有更好的替代方法来解决这个问题?

任何帮助将不胜感激

application.yml 文件中的 Spring boot OIDC 属性

security:         
    oauth2:
      client:
        registration: 
          pingIdentity: 
            scope:
            - openid
            - profile
            - email
            - phone
            - job_title
            - scoped_entitlement
            - authorization_group
            - entitlement_group
            - organizational_data
            - basic_start_authorization            
            client-id: <Client  ID>
            client-secret:  <Client  Secret>
            provider: pingIdentity
        provider:
          pingIdentity: 
            issuer-uri: <Issuer URI>

【问题讨论】:

    标签: java spring-security microservices openid-connect spring-security-oauth2


    【解决方案1】:

    我认为您的关键问题是令牌在没有用户控制的情况下过期。

    您可以考虑以下选项。

    1. 在您的 SPA 中保留一个重复性任务,该任务将检查当前时间和 IDToken 的到期时间。当令牌即将到期时(比如不到 5 分钟),SPA 会提示一个小对话框并要求用户输入她的凭据。提交表单后,将在会话/本地存储或 cookie 中接收和替换新令牌。

      这样当用户提交表单时,它将使用新的令牌。

      这不需要任何额外的服务而不是当前的服务,您只需要 SPA 中的额外功能。

      这样做的缺点是,用户必须再次输入密码。

    2. 如果您可以定义另一个服务来接收 referh_token 以及 IDToken 并存储它,那么 SPA 可以保持定期发送心跳请求。当用户/或用户在本地与页面交互时,可以在页面处于焦点时发送请求。 (例如,可以在鼠标移动/滚动等时每 5 分钟发送一次)。

      后端服务会检查令牌是否即将过期,然后它会使用刷新令牌来获取新令牌,然后将其传递给 SPA。 SPA 将在其结束时为后续请求更新令牌。只要用户在页面上工作,所有这些都将在后台发生,而不会打扰用户。

      您将不得不处理额外的复杂性以换取用户的便利。

    【讨论】:

      【解决方案2】:

      我认为使用 open id connect 存在概念问题。

      Open id connect 不像 oauth2 那样是一种身份验证/授权协议,它是 oauth2 之上的一层,用于向客户端提供用户信息。

      因此,idtoken 中包含的信息的目标受众是尝试使用资源(前端)的应用程序,而不是资源服务器(微服务)。如您所见

      https://openid.net/specs/openid-connect-core-1_0.html

      必须发送到微服务的令牌是与 idtoken 一起发布的访问令牌,因为这是必须用于授权操作的令牌。

      其他问题是您可能需要用户信息才能在服务中执行某些操作,但这不是同一流程的一部分。

      身份验证/授权流程仅确保一个用户是有效的,并且有权在某些资源服务器(微服务)上执行某些操作

      如果这样,当认证过程结束时,你需要获取用户信息,我建议你三种可能的解决方案:

      1. 您可以使用 jwt 令牌(自编码访问令牌)作为访问令牌而不是不透明的令牌,因此您可以在子声明中获取用户 ID,然后查询用户服务以获取另一个信息。

      2. 与第一点一样,您可以使用 jwt 访问令牌,此外还可以添加自定义声明以存储其他用户信息

      3. 如果您在 zuul 网关中进行访问令牌验证,您可以在网关中获取用户信息,并使用您需要的信息将自定义 jwt 传递给微服务。这个令牌不需要是访问令牌,因为认证/授权操作已经由网关完成。

      这样您就可以毫无问题地刷新您的访问令牌

      【讨论】:

      • 感谢您的详细解答。如果我选择实施第一种方法,您认为每次都调用 /userinfo 是个好主意吗
      • 将其视为服务之间的任何其他数据依赖关系,例如,如果订单服务每次需要计算价格时都必须查询商品服务。您可以使用缓存或通过用户事件更新数据的本地副本来解决性能问题。无论如何,性能最好的选项可能是 2。
      • 再次感谢。你有任何博客链接或 github repo 链接已经实现了吗?
      • 对不起,我所做的这样的项目是为客户服务的,所以回购是私有的
      • 感谢您的宝贵意见,我正在标记此答案,但如果您能分享第三种方法的任何参考,将不胜感激。我的意思是我们已经实现了这个,但想知道它是否正确。
      猜你喜欢
      • 2019-01-18
      • 2022-01-28
      • 2015-06-02
      • 2020-08-14
      • 2020-02-17
      • 2021-01-19
      • 2020-02-12
      • 2020-06-02
      • 2018-09-27
      相关资源
      最近更新 更多