Brief description of the initial situation: Let's assume a Spring Boot based RESTful API acting as a OAuth2 Resource Server. The resource server is cofigured using Spring Security 5 and common approaches. The external authorization server delivers user information (e.g. E-Mail, First Name, Last Name) as JWT claims, received when a client authenticates. The generic user information, hold by the authorization server, are extended by resource server specific user information (e.g. Business Roles, Domain UID). The domain user is composed of information from two data sources:
- Authorization Server User Data
- Resource Server (Application) User Data
New users who have never been authenticated at the resource server via a JWT are created in the database of the resource server. The database of the resource server accordingly contains a user entity for each user who uses the API of the resource server, consisting of the information synchronized by the authorization server and the information supplemented by the business logic of the resource server.
public class User {
// Information synchronized from Authorization Server
private String subject;
private String preferredUsername;
private String firstName;
private String lastName;
private String email;
// Information added by Resource Server's business logic
private UUID id;
private String businessRole;
}
The synchronization of the domain users is carried out by listening to the AuthenticationSuccessEvent and creating the user in the database or updating it if necessary. To summarize, for each OAuth2 user, identified by the subject claim, there is a domain profile with domain-specific additional information in database.
This article also clearly describes this synchronization and distribution of user data.
Now to the actual question: While OAuth2 Scopes control which authorizations an application has, it must also be controlled which authorizations the user has. The user authorizations are domain-specific and recorded in the database of the Resource Server. For example, a user should only be able to delete comments that he has created. Such access control cannot be controlled via OAuth2 Scopes. As an aside, I'm talking about the Spring Method Security using @PreAuthorize or @PostAuthorize.
@GetMapping
@PreAuthorize("...")
public void func(@AuthenticationPrincipal JWT jwt) {
}
Such access could be controlled via Attribute based Access control (ABAC), for example. However, this assumes that the current @AuthenticationPrincipal is not a JWT as it is standard for a Spring Resource Server, but an instance of the domain-specific User profile. Is there a way to convert a JWT into a User profile, possibly using a UserDetailsService?
Is there a recommended approach for Spring Security 5 OAuth2 Resource Server to load information from the database based on the JWT, more precisely a User?