Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security: What is the right way to call method secured with @PreAuthorize in background task?

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?

like image 367
Popandopolos Avatar asked Apr 26 '12 10:04

Popandopolos


People also ask

How does @PreAuthorize work in spring boot?

Spring Security provides method level security using @PreAuthorize and @PostAuthorize annotations. This is expression-based access control. The @PreAuthorize can check for authorization before entering into method. The @PreAuthorize authorizes on the basis of role or the argument which is passed to the method.

What is @PreAuthorize annotation in spring boot?

Method-level security is implemented by placing the @PreAuthorize annotation on controller methods (actually one of a set of annotations available, but the most commonly used). This annotation contains a Spring Expression Language (SpEL) snippet that is assessed to determine if the request should be authenticated.

What is the use of @PreAuthorize annotation?

The @PreAuthorize annotation checks the given expression before entering the method, whereas the @PostAuthorize annotation verifies it after the execution of the method and could alter the result.

What's the difference between @secured and @PreAuthorize in Spring Security?

The difference between @Secured and @PreAuthorize are as follows : The main difference between @Secured and @PreAuthorize is that @PreAuthorize can work with Spring EL. We can access methods and properties of SecurityExpressionRoot while using @PreAuthorize but not with @Secured.


2 Answers

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 
like image 130
Madhu Tomy Avatar answered Sep 21 '22 01:09

Madhu Tomy


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.

like image 31
tom Avatar answered Sep 24 '22 01:09

tom