【问题标题】:Spring OAuth2 + JWT, how to map external access token to local userSpring OAuth2 + JWT,如何将外部访问令牌映射到本地用户
【发布时间】:2018-03-13 19:30:48
【问题描述】:

我目前正在使用 Spring 开发 Web 服务。我想为用户提供通过外部 OAuth 服务登录的可能性,例如谷歌,Github,...以及传统的用户名/密码登录。 POJO 方面,我有以下设置:

  • 每个User 都与AuthenticationMethods 存在一对多关系
  • 每个AuthenticationMethod都有一个AuthenticationProvider(例如googlegithublocal),并存储了这个认证方法的sub和对应的User。如果是本地身份验证,则为用户 ID。
  • 每个AuthenticationMethodAuthenticationProvider == local 额外存储一个密码。

已经有效的方法

本地身份验证(用户名/密码)是通过自己的 OAuth2 身份验证服务器(Spring 应用程序的一部分)完成的,并返回一个包含用户名的 JWTAccessToken (前端永远不会看到 client_secret,因此是 password在这种情况下,赠款是可以接受的)。

我还能够通过authorization_request 授权过程从外部 OAuth 提供者(Google、Github 等)检索访问令牌,其中包含来自所述提供者的用户sup

问题

我需要将外部sub 映射到User 对象。因为理论上,两个不同的用户可能在两个不同的外部提供商处拥有相同的sub,所以我还必须检查发行者,从而导致讨厌的if-else 构造。此外,每次需要授权的访问都必须执行从 JWT 令牌到 User 的转换。

解决方案的想法

我想做的是向外部生成的 JWT 添加信息。这显然是不可能的,因为我无法“重新签署”外部 JWT。我的想法是拦截外部 JWT 并发出包含用户名的本地 JWT,因此仅将外部 JWT 用于初始身份验证。

Spring 中是否有内置的可能性来完成我想要的?还是有解决这个问题的“最佳实践”?

【问题讨论】:

    标签: java spring-boot spring-oauth2


    【解决方案1】:

    最佳做法是让 OAuth2 服务器将用户名添加为对 JWT 的附加声明。 Spring 已经有一个句柄,它从 JWT 获取“user_name”声明并将其用作 Principal 对象。

    【讨论】:

    • 问题是:我无法更改外部访问令牌,因此无法添加其他声明。
    • 我认为 Spring 没有内置任何东西可以帮助您解决问题。你检查过来自 OAuth2 服务器的 JWT 令牌吗?也许他们有额外的声明,你可以用来从中获取用户名。
    • 令牌不是问题。我可以找到与令牌对应的User。问题是令牌拦截。我不希望前端看到外部令牌。
    • @Turing85 为什么不呢?从外部提供者获取令牌的用户被认证为令牌中详细信息的所有者。您必须让用户将数据传递给您。我认为您应该考虑始终将电子邮件声明附加到令牌上。抱歉,我不知道如何在 Spring 中实现这一点,但本质上你想验证来自用户的令牌(在 ASP 中,我们使用 Owin middilewhere 自动执行此操作),然后获取应该有他们的电子邮件的用户声明。跨度>
    • 任何用户都可以向您的服务器发送数据。 JWT 包含原始可读数据,以及相同数据的签名版本。为了确保这是合法的,您的后端需要使用 Google 的公钥 来解码 JWT 的 签名 并检查它是否与有效负载数据相同。用户无法向您发送伪造的 JWT,因为他们无法对数据进行编码(谷歌必须这样做)。谷歌让它变得稍微困难​​一些,因为它们在访问代码中包含了另一个步骤(出于其他原因),但这个概念仍然存在:lostechies.com/content/jimmybogard/uploads/2014/11/image.png
    猜你喜欢
    • 2015-04-16
    • 2014-10-29
    • 1970-01-01
    • 2017-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多