Accessing current ClientDetails inside custom UserDetailsService

Viewed 190

I'm using Spring Boot OAuth Authorization Server (old stack) and implementing my own versions of ClientDetailsService and UserDetailsService, using Oauth2 password flow.

Our JpaClientDetailsService implements loadClientByClientId and returns a ClientDetails, with the details of the client that is being authenticated.

@Service
public class JpaClientDetailsService implements ClientDetailsService {

    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
    
        BaseClientDetails baseClientDetails = new BaseClientDetails(...);

        //do processing....

        return baseClientDetails;

    }

}

After that, the method loadUserByUsername of our implementation of JpaUserDetailsService is called, receiving the username of user that is trying to authenticate:

@Service
public class JpaUserDetailsService implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        return null;

    }

}

My question is: How could I access the current ClientDetails, returned by JpaClientDetailsService.loadClientByClientId inside JpaUserDetailsService.loadUserByUsername?

Thanks!

1 Answers

I realized that SecurityContextHolder.getContext().getAuthentication() contains information about the client that is being authenticated. So, I was able to get the client's name and load it's data as follow:

@Service
public class JpaUserDetailsService implements UserDetailsService {

    @Autowired
    private OAuthClientsRepository oAuthClientsRepository;

    @Override
    public org.springframework.security.core.userdetails.UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //Gets the Authentication from SecurityContextHolder
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        
        //ClientId is 'Principal's' Username
        var clientId = ((User) authentication.getPrincipal()).getUsername();

        //Gets clientDetails from JPA Repository. This would execute another Roundtrip to Database, but since we have 2nd level cache configured, this
        //problema is minimized.
        ClientDetails authClient = oAuthClientsRepository
                .findByClientId(clientId)
                .orElseThrow(() -> new NoSuchClientException(String.format("ClientId '%s' not found", clientId)));

        //....

    }

}

That's it.

Related