Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring security oauth2 + switch user filter

I would like to set up SwitchUserFilter in my spring-boot app which implements spring-security-oauth2 yet. I've already set up this filter in my WebSecurityConfiguration that extends WebSecurityConfigurerAdapter.

After login I obtain my token, a bearer token, and I use a configured endpoint to switch user.

I follow the code with debug in my IDE and apparently SecurityContextHolder is updated and a new target user is injected.

However, when the request is redirected to the target URL (a property of this filter), SecurityContextHolder gives me the old user back and not what I've requested.

I've inspected OAuth2AuthenticationProcessingFilter and the token extracted from request return a same bearer token and with this it builds user detail and inject it into SecurityContextHolder.

Is there any way to use this kind of filter with oauth2 approach?

like image 526
Claudio Pomo Avatar asked Oct 31 '25 13:10

Claudio Pomo


1 Answers

The problem is that you need to create a new token that contains the new target user information. This new token has to be sent back to the client, so for future requests the new target user token is used. In our case the token is persisted on the server side (using the JDBCTokenStore), but it would also work in completely server-side stateless environments (JWT-Token).

Our environment is a spring-boot/jhipster application with an angular 1.2 client.

Creating a new token:

@Inject
private UserDetailsService userDetailsService;

@Inject
private AuthorizationServerTokenServices tokenService;

@Inject
private ClientDetailsService clientDetailsService;


   public OAuth2AccessToken createImpersonationAccessToken(String login) {
       UserDetails userDetails = userDetailsService.loadUserByUsername(login);
       log.info("Switching current user to {}", login);

       Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
       List<GrantedAuthority> impersonationAuthorities = new ArrayList<>(authorities);
       Authentication source = SecurityContextHolder.getContext().getAuthentication();
       // add current user authentication (to switch back from impersonation):
       SwitchUserGrantedAuthority switchUserAuthority = 
               new SwitchUserGrantedAuthority(AuthoritiesConstants.IMPERSONATION, source);
       impersonationAuthorities.add(switchUserAuthority);
                   UserDetails newUserDetails = 
               org.springframework.security.core.userdetails.User
               .withUsername(login)
               .authorities(impersonationAuthorities)
               .password("justinventedhere")
               .build();
                           Authentication userPasswordAuthentiation = 
               new UsernamePasswordAuthenticationToken(newUserDetails, null, impersonationAuthorities);

       Map<String, String> parameters = new HashMap<>();        
       ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
                   OAuth2Request oauthRequest = new OAuth2Request(parameters, client.getClientId(), client.getAuthorities(), true, 
               client.getScope(), client.getResourceIds(), null, null, null);
       OAuth2Authentication authentication = new OAuth2Authentication(oauthRequest, userPasswordAuthentiation);
       OAuth2AccessToken createAccessToken = tokenService.createAccessToken(authentication);
                   return createAccessToken;
   }

This new token is returned to the client (in our case an angular 1.2 application) that stores the token in its local storage (to be used on next requests). Then the application needs reloading (simplest way to update the target user):

vm.switchToClient = function (client) {
    vm.switchingUser = true;
    UserService.switchToClient(client, function(response) {
                var expiredAt = new Date();
                $localStorage.authenticationToken = response;
                window.location.href='#/';
                window.location.reload()
            });
}
like image 177
cdaller Avatar answered Nov 03 '25 03:11

cdaller



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!