Java Spring OAuth2+;JWT,如何将外部访问令牌映射到本地用户

Java Spring OAuth2+;JWT,如何将外部访问令牌映射到本地用户,java,spring-boot,spring-oauth2,Java,Spring Boot,Spring Oauth2,我目前正在用Spring开发一个web服务。我想为用户提供通过外部OAuth服务登录的可能性,例如google、github,。。。以及传统的用户名/密码登录。Pojo wise,我有以下设置: 每个用户都与身份验证方法有一对多的关系 每个AuthenticationMethod都有一个AuthenticationProvider(例如google,github,local),并存储此验证方法的子,以及相应的用户。对于本地身份验证,它是用户的ID 每个AuthenticationProvide

我目前正在用Spring开发一个web服务。我想为用户提供通过外部OAuth服务登录的可能性,例如google、github,。。。以及传统的用户名/密码登录。Pojo wise,我有以下设置:

  • 每个
    用户
    都与
    身份验证方法
    有一对多的关系
  • 每个
    AuthenticationMethod
    都有一个
    AuthenticationProvider
    (例如
    google
    github
    local
    ),并存储此验证方法的
    ,以及相应的
    用户
    。对于本地身份验证,它是用户的ID
  • 每个
    AuthenticationProvider==local
    AuthenticationMethod
    额外存储一个密码
什么已经起作用了

本地身份验证(用户名/密码)通过自己的OAuth2身份验证服务器(Spring应用程序的一部分)完成,并返回一个
JWTAccessToken
,其中包含用户名(前端从未看到
客户机机密
,因此在这种情况下可以接受
密码
授权)

我还能够通过
authorization\u request
grant过程从外部OAuth提供商(google、github等)检索访问令牌,该过程包含来自所述提供商的用户的
sup

问题

我需要将外部
子对象
映射到
用户
对象。从理论上讲,两个不同的用户可能在两个不同的外部提供商处拥有相同的
sub
,因此我还必须检查发行人,从而产生一个讨厌的
if-else
结构。此外,从JWT令牌到
用户
的转换必须在需要授权的每次访问中执行

解决方案的想法

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


在春天是否有一种内在的可能性来实现我想要的?或者有解决这个问题的“最佳实践”吗?

最佳实践是让OAuth2服务器向JWT添加用户名作为附加声明。Spring已经有了一个句柄,从JWT获取“user_name”声明并将其用作主要对象

问题是:我无法更改外部访问令牌,因此我无法添加额外的声明。我认为Spring没有任何内置功能来帮助您解决这个问题。您是否检查了OAuth2服务器上的JWT令牌?也许他们有额外的声明可以用来获取用户名。令牌不是问题所在。我可以找到对应于令牌的
用户
。问题是令牌拦截。我不希望前端看到外部标记。@Turing85为什么不?从外部提供程序获取令牌的用户被认证为令牌中详细信息的所有者。您必须让用户将数据传递给您。我认为您应该考虑将电子邮件声明始终附加到令牌。很抱歉,我不知道如何在Spring中实现这一点,但实际上,您希望验证用户的令牌(在ASP中,我们使用Owin middilewhere自动执行此操作),然后获取用户声明,该声明应该包含他们的电子邮件。任何用户都可以向您的服务器发送数据。JWT包含原始可读数据,以及相同数据的签名版本。为了确保这是合法的,您的后端需要使用谷歌的公钥来解码JWT的签名,并检查它是否与有效负载数据相同。用户无法向您发送伪造的JWT,因为他们无法对数据进行编码(谷歌必须这样做)。谷歌让它变得稍微困难一些,因为他们在访问代码中加入了另一个步骤(出于其他原因),但这个概念仍然存在: