8

I have a method secured with @PreAuthorize

@PreAuthorize("hasRole('ROLE_ADMIN') and (#action.userId != principal.id)")
public void execute(EditAction action)

Now I need to call this method from a background task. If I simply run this code - I catch an exception:

AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext

Seems, I need to set required Authentication to SecurityContext. I can:

  1. Write some custom AuthenticationToken for background tasks.
  2. Use UsernamePasswordAuthenticationToken with fake User.
  3. Don't use secured methods in background tasks.
  4. Any other recommendations ?

What is the right way?

Soumen Mukherjee
  • 2,953
  • 3
  • 22
  • 34
Popandopolos
  • 628
  • 6
  • 15
  • can you please show some code? How are you calling it? – danny.lesnik Apr 26 '12 at 10:37
  • 1
    This is not a transparent call - we are using command pattern. Secured method is a method of Handler. By a "background task" I mean a jms MessageListener or some @Scheduled method. I'm calling secured method some way, as I calling it by processing servlet - by dispatching an Action. – Popandopolos Apr 26 '12 at 11:12

2 Answers2

2

You can register an Authentication token yourself in the current thread and session(if used in a web application):

SecurityContextHolder.getContext().setAuthentication(token);
session.put(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());

You can use the standard UsernamePasswordAuthenticationToken for this as long as you add the appropriate roles.

tom
  • 2,735
  • 21
  • 35
2

In this case Manual Workaround is an option:

(1) If this is an independent job,

Create an Authentication object and set it to the security context before the secured method is invoked. Remove the Authentication object from the security context after the secured method is done execution.

public final class AuthenticationUtil {

//Ensures that this class cannot be instantiated
private AuthenticationUtil() {
}

public static void clearAuthentication() {
    SecurityContextHolder.getContext().setAuthentication(null);
}

public static void configureAuthentication(String role) {
    Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(role);
    Authentication authentication = new UsernamePasswordAuthenticationToken(
            "user",
            role,
            authorities
    );
    SecurityContextHolder.getContext().setAuthentication(authentication);
}

So it would look like

AuthenticationUtil.configureAuthentication(role);
// Call to the secured method 
AuthenticationUtil.clearAuthentication();

(2) For web application, where we can't make authentication object as null, don't call

AuthenticationUtil.configureAuthentication(role);
// call to the secured method 
Madhu Tomy
  • 662
  • 11
  • 25