1

There had been being a monolithic java-application that is configured by Spring Security. Whenever I want to get the authenticated user, the org.springframework.serurity.authentication.UsernamePasswordAuthenticationToken object gives me like this:

User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();

This piece of code had been working correctly until I changed the configuration from Spring Security to Oauth2.
In order to OAuth2, org.springframework.serurity.oauth2.provider.OAuth2Authentication object gives me the authenticated user like this:

OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) SecurityContextHolder.getContext().getAuthentication();
LinkedHashMap linkedHashMap = (LinkedHashMap) oAuth2Authentication.getUserAuthentication().getDetails();
return linkedHashMap.get("principal");

So the result of SecurityContextHolder.getContext().getAuthentication().getPrincipal() is difference between OAuth2 and Spring Security.
What is the problem:
My problem is that
1- I have to rewrite every where contains SecurityContextHolder.getContext().getAuthentication().getPrincipal()
with

           Object obj = SecurityContextHolder.getContext().getAuthentication();
            if (obj instanceof OAuth2Authentication) {
                OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) SecurityContextHolder.getContext().getAuthentication();
                LinkedHashMap linkedHashMap = (LinkedHashMap) oAuth2Authentication.getUserAuthentication().getDetails();
                linkedHashMap.get("principal");
                LinkedHashMap  result = linkedHashMap.get("principal");
                User user = new User();
                user.setId((Integer)result.get("id"));
                user.setName((String)result.get("name"));
                //As same way to set other its attributes@@@@@@@@@@
                return user;
            } else
                return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

2- As it is seen in above code that is marked by @@@@@@@@@, the number of field of User object is near to 20, so I have to repeat user.setField(result.get("filed")) 20 times and it is so tedious.
The solution is that I have to either rewrite as same as above code or other thing that I do not know?

reza ramezani matin
  • 1,384
  • 2
  • 18
  • 41

1 Answers1

2

Yes, indeed, both of those Authentications are different between Spring Security and Spring Oauth2. You could create some sort of @Service or @Component class that handles giving you back what you are looking for. This can then be injected/autowired where ever you need it. So basically, this new class becomes the single source of truth for retrieving your principal. If you happen to change the security implementation again, your code should not be affected because the security handling service is abstracted away by a new interface.

See sample below:

@Service
public class Oauth2PrincipalService implements PrincipalService {

  public User retreivePrincipalUser(){
    //retreive user stuff here as you need using the oauth2 code you provided..

  }

}
public interface PrincipalService {

  User retreivePrincipalUser();

}

Hermann Steidel
  • 1,000
  • 10
  • 18
  • Is it possible to get User object of Oauth2 as same as it is in spring security? and I do not have to change my code? – reza ramezani matin Mar 09 '19 at 16:11
  • No, I worked with this last year and I learned that the userDetails are stored in a map as you also discovered. In my use case, this turned out to be perfect because I was able to inject custom key/value pairs into the userDetails map from our Spring AuthService microservice. I believe this is done this way because the Oauth2 stuff isn't Spring specific and those user detail fields might vary from Authentication service (i.e. Facebook vs Google vs DIY). In my case, I used Jackson to convert from a map to my POJO so I didn't have to set all those fields when hydrating my User object. – Hermann Steidel Mar 10 '19 at 14:56
  • As you said in above comment, you use jackson to convert. Would you give me the sample of jackson convertor? – reza ramezani matin Mar 11 '19 at 10:51
  • @reza ramezani matin See this answer here: https://stackoverflow.com/questions/16428817/convert-a-mapstring-string-to-a-pojo – Hermann Steidel Mar 11 '19 at 12:30