Search code examples
javasecurityspringspring-mvcspring-security

Spring Switching User: only allow a user with a specific role switch to another user with specific roles


I'm making a web application with Spring Security with 3 different roles:

  • SuperSupporter
  • DivisionSupporter
  • Client

Currently my application allow SuperSupporter to "impersonate" DivisionSupporter by using SwitchUserFilter, for him to act as that DivisionSupporter. This is necessary in case a DivisionSupporter meet some problems - and needs supported. This may sound strange, but it's kind of using TeamViewer to examine the computer problem for a friend.

Further more, now we need give the DivisionSupporter the right to "impersonate" the Client, so that the DivisionSupporter can "support" the Client.

But the thing makes me worried is that if we give the DivisionSupporter the right to access j_spring_security_switch_user, malicious DivisionSupporter may use it to impersonate the SuperSupporter (by posting with to the link with the according username).

I have thought of a work around to stop that case:

 <bean id="switchUserFilter" class="org.springframework.security.web.authentication.switchuser.SwitchUserFilter">
        <property name="userDetailsService" ref="userDetailsService" />
        <property name="switchUserUrl" value="/j_spring_security_switch_user" />
        <property name="exitUserUrl" value="/j_spring_security_exit_user" />
        <property name="targetUrl" value="/checkRole.html" />
     </bean>

In /checkRole action (which is the targetUrl), I make another check: if the user role is SuperSupporter and he is impersonate someone, the application will send him to /j_spring_security_exit_user (because a SuperSupporter won't need to impersonate himself).

Though it seems work, but I'm worried that a malicious user may find a way to work around this wall, and hence put our system in danger.

I think that SpringSecurity may have someway to address this needs, but still not able to find it. Is this way really safe? Can the DivisionSupporter work around to impersonate the SuperSupporter with my current solution?

More importantly, is there any better way to address this problem?

Any help would be appreciated.


Solution

  • The targetUrl approach is a bad idea, since the user can just ignore the redirect and request another URL instead. You need to prevent inappropriate switches in the first place.

    Your best bet is probably to customize the attemptSwitchUser method on SwitchUserFilter:

    protected Authentication attemptSwitchUser(HttpServletRequest request) {
        Authentication switchTo = super.attemptSwitchUser(request);
        Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
        // Inspect currentUser (e.g. authorities) and switchTo to see if valid combination
        // Raise AuthenticationException if not
    
        return switchTo;
    }
    

    That method is called before the SecurityContext is set, so it is the best place to do any checking on the validity of the switch.