[英]Spring OAuth2 + JWT, how to map external access token to local user
I am currently developing a web service with Spring.我目前正在使用 Spring 开发 Web 服务。 I would like to provide users the possibility to login via external OAuth-Services, eg Google, Github,... as well as a traditional username/password-login.我想为用户提供通过外部 OAuth 服务登录的可能性,例如谷歌、Github...以及传统的用户名/密码登录。 POJO-wise, I have the following setup:在 POJO 方面,我有以下设置:
User
has a One-to-Many relation to AuthenticationMethod
s每个User
与AuthenticationMethod
一对多的关系AuthenticationMethod
has exactly one AuthenticationProvider
(eg google
, github
, local
) and stores the sub
of this authentication method and the corresponding User
.每个AuthenticationMethod
恰好有一个AuthenticationProvider
(例如google
、 github
、 local
)并存储此身份验证方法的sub
项和相应的User
。 In case of a local authentication, it is the User's ID.在本地身份验证的情况下,它是用户的 ID。AuthenticationMethod
with AuthenticationProvider == local
additionally stores a password.每个AuthenticationMethod
用AuthenticationProvider == local
还保存密码。What already works什么已经有效
Local authentication (username/password) is done through an own OAuth2 authentication server (part of the Spring application) and returns an JWTAccessToken
, containing the username (the frontend never sees the client_secret
, thus a password
grant is acceptible in this situation).本地身份验证(用户名/密码)通过自己的 OAuth2 身份验证服务器(Spring 应用程序的一部分)完成并返回一个JWTAccessToken
,其中包含用户名(前端永远不会看到client_secret
,因此在这种情况下可以接受password
授予)。
I am also able to retrieve access tokens from the external OAuth Providers (Google, Github,...) via the authorization_request
grant process containing their user'S sup
from said provider.我还可以通过包含来自所述提供者的用户sup
的authorization_request
请求authorization_request
过程从外部 OAuth 提供者(Google、Github 等)检索访问令牌。
Problem问题
I need to map the external sub
to a User
object.我需要将外部sub
映射到User
对象。 Since, in theory, two different users could have the same sub
at two different, external providers, I would have to check the issuer as well, resulting in a nasty if-else
construct.由于理论上,两个不同的用户可以在两个不同的外部提供商处拥有相同的sub
,因此我也必须检查发行者,从而导致令人讨厌的if-else
构造。 Also, this translation from JWT token to a User
must be performed with every access where authorization is required.此外,必须在每次需要授权的访问时执行从 JWT 令牌到User
这种转换。
Ideas for solutions解决方案的想法
What I would like to do is add information to the externally generated JWT.我想做的是向外部生成的 JWT 添加信息。 This is obviously not possible since I cannot "re-sign" the external JWT.这显然是不可能的,因为我无法“重新签署”外部 JWT。 My idea is to intercept the external JWT and issue a local JWT, containing the username, thus using the external JWT only for initial authentication.我的想法是拦截外部 JWT 并发出包含用户名的本地 JWT,从而仅将外部 JWT 用于初始身份验证。
Is there a built-in possibility in Spring to accomplish what I want? Spring 中是否有内置的可能性来完成我想要的? Or is there a "best-practice" to solve this problem?或者是否有解决此问题的“最佳实践”?
The best practice is to have OAuth2 server to add username as an additional claim to JWT.最佳实践是让 OAuth2 服务器将用户名添加为 JWT 的附加声明。 Spring already has a handle that takes "user_name" claim from JWT and uses it as Principal object. Spring 已经有一个句柄,它从 JWT 获取“user_name”声明并将其用作 Principal 对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.