1

I am using Spring Security to Authenticate user.

Question is what would be the best way to dynamically update authorities? I would like to update it per request, now I just doing it once after user login into the system.

I have manager based application, so admin could decide what user could do at any time, and remove/add roles. Problem with this approach that user will get new set of permissions only after he log out and log in back.

I know I could use

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = Lists.newArrayList();

userDao.getAuthorities(authorities, user);

Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), authorities);
 SecurityContextHolder.getContext().setAuthentication(newAuth);

The main question is what would be the right moment to do it? Some filter chain before framework hit controller or interceptor? And how safe it is? Thread safe?

Lets say if I put it in interceptor, and while I am updating SecurityContextHolder in one request another request reading it - what will happen ?

Just quick draft

public class VerifyAccessInterceptor extends HandlerInterceptorAdapter {
    public boolean preHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler) throws Exception {

          Authentication auth =  SecurityContextHolder.getContext().getAuthentication();
           List<GrantedAuthority> authorities = Lists.newArrayList();

           userDao.getAuthorities(authorities, user);

           Authentication newAuth = new  UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(),             authorities);
               SecurityContextHolder.getContext().setAuthentication(newAuth);

    }
}
Vedran Pavic
  • 2,339
  • 2
  • 27
  • 31
antohoho
  • 950
  • 2
  • 17
  • 37

1 Answers1

0

Correct me if I am wrong.

From your question it is obvious that you want request based Authority changes. Ideally an Administrator will have a different UI where he can remove/add Authorities. These changes must be reflected in any logged in user session near real time.

Currently the code snippet you have provided is the only way you can do it.

Answering your concerns.

The main question is what would be the right moment to do it?

If you want this to be applied to only logged in Users then you must have it in a interceptor, because it will only be applied after the Spring security filter chain.

Some filter chain before framework hit controller or interceptor?

Yes, the DelegatingFilterProxy and FilterChainProxy will be invoked first before your request hit the controller or interceptor.

And how safe it is? Thread safe?

Yes, If you use the SecurityContextHolder with default settings it will be using ThreadLocalSecurityContextHolderStrategy which is thread safe.

There will be a performance hit as all the request have to go through the interceptor. And since you need to change the authorities only if they changed better to check that in your interceptor before re-setting the Authentication

public class VerifyAccessInterceptor extends HandlerInterceptorAdapter {
    public boolean preHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler) throws Exception {

          Authentication auth =  SecurityContextHolder.getContext().getAuthentication();
           List<GrantedAuthority> authorities = Lists.newArrayList();

           userDao.getAuthorities(authorities, user);

           // If contents of auth.getAuthorities() equals authorities then no need to re-set.
           Authentication newAuth = new  UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(),             authorities);
               SecurityContextHolder.getContext().setAuthentication(newAuth);

    }
}
shazin
  • 21,379
  • 3
  • 54
  • 71
  • No need to correct, your understanding is exactly what I need. But still something stopping me of doing it in interceptor, is there any other step in a process. Found this URL - http://stackoverflow.com/questions/892733/how-to-immediately-enable-the-authority-after-update-user-authority-in-spring-se . Talking about alwaysReauthenticate in your AbstractSecurityInterceptor, but not sure how to use it with my code shippet . – antohoho Feb 04 '15 at 05:15
  • alwaysReauthenticate flag is used to re login user everytime which will ideally just call the AuthenticationProvider again and set the Authentication in SecurityContextHolder.getContext(). So in your case this is not required as you just need to reload the authorities. – shazin Feb 04 '15 at 05:36
  • shazin, agree with you, but still how safe is to have an interceptor? Something stopping me from doing so, is it possible to make SecurityContextHolder request scope instead of Session scope and create it with request ? So I kno another browser tab wont modify? – antohoho Feb 04 '15 at 16:44