How to map an OAuth 2 token to a UserDetails object on a resource server?

I have 2 separate Spring boot applications, one of which serves as an OAuth 2 authorization server, and the other as a resource server. I am using Spring RemoteTokenServices on my resource server to verify tokens from the authorization server. Now I'm trying to determine the protected code of the controller in the application of my resource server, but I'm not sure how to map the UserDetails class to the authentication principal provided through the OAuth 2 mechanism.

I installed my authorization server with a custom TokenEnhancer , which adds more details to the token so that /oauth/check_token?token=<token> comes back with custom fields that I want to map to resource server controllers.

In a more seamless installation, where the authorization server is also a resource server, I can define controller methods that use the authenticated principle as follows:

 //User implements UserDetails public Map<String, Object> getResource(@AuthenticationPrincipal User user) { //code that uses the user object } 

However, this does not seem to work so directly in a more distributed approach. The mapping is not performed, and the user parameter becomes the null object. I tried using the following approach:

 public Map<String, Object> getResource(Authentication authentication) { //code that uses the authentication object } 

Although the above code successfully matches authentication data, it does not provide me with direct access to the custom fields that I set through the TokenEnhancer , which I mentioned earlier. I can't seem to find anything in the Spring docs regarding this.

+6
source share
2 answers

To solve this problem, let me first go through a little architectural background. The UserDetails object UserDetails is automatically displayed through @AuthenticationPrincipal comes from the principal field of the active Authentication object. The resource server controller has access to the OAuth2Authencation object, which is a specialized instance of Authentication for the Spring OAuth2 security infrastructure, simply by declaring it as part of the method parameters.

 public void controllerMethod(OAuth2Authentication authentication) { //controller definition } 

Knowing this, now the problem goes to how to verify that the getPrincipal() method in the Authentication object is an instance of my user class UserDetails . RemoteTokenServices that I use in the resource server application uses an AccessTokenConverter instance to interpret the token data sent by the authorization server. By default, it uses the DefaultAccessTokenConverter , which simply sets the authentication principal as the username, which is String . This converter uses the UserAuthenticationConverter to convert the data coming from the authorization server into an Authentication instance. This is what I needed to configure:

 DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); tokenConverter.setUserTokenConverter(new DefaultUserAuthenticationConverter() { @Override public Authentication extractAuthentication(Map<String, ?> map) { Authentication authentication = super.extractAuthentication(map); // User is my custom UserDetails class User user = new User(); user.setSpecialKey(map.get("specialKey").toString()); return new UsernamePasswordAuthenticationToken(user, authentication.getCredentials(), authentication.getAuthorities()); } }); tokenServices.setAccessTokenConverter(tokenConverter); 

With all these settings, the @AuthenticationPrincipal mechanism now works as expected.

+9
source

Have you enabled AuthenticationPrincipalArgumentResolver like the following xml?

 <mvc:annotation-driven> <mvc:argument-resolvers> <bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" /> </mvc:argument-resolvers> </mvc:annotation-driven> 

And you need to implement UserDetails to return your own CustomerUser object , then you can use annotation to directly get the principal.

0
source

Source: https://habr.com/ru/post/1013069/


All Articles