I'm creating an app with 4 roles. I don't have permissions stored in my database, just the roles.
At the controller level, I restrict my routes only to certain roles, for example :
@PreAuthorize("hasRole('ADMIN')")
And in my service's methods, I did a more thorough check as needed.
However, the problem I have with having authorization conditions in my services is that it only works if the SecurityContextHolder.getContext() is not null.
And I realized that this could be the case, for example, in one of my jobs with Jobrunr.
So I inject my service into my job and I want to call a method, but it crashes because it can't retrieve the authenticated user.
Is there a way to manually authenticate a user in the job, is this a good way to do it?
Update following @Ken Chan's reply - code not working :
Jobrunr job :
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class InactiveUsersEmail implements JobRequest {
private Integer userId;
@Override
public Class<InactiveUsersEmailHandler> getJobRequestHandler() {
return InactiveUsersEmailHandler.class;
}
}
Run it using DelegatingSecurityContextRunnable:
Stream<DelegatingSecurityContextRunnable> jobs = this.userService
.findAll()
.map(user -> {
Runnable task = () -> new InactiveUsersEmail(user.getId());
return new DelegatingSecurityContextRunnable(task, this.authorizationComponent.getSecurityContext());
});
// here not working:
// cannot resolve method 'enqueue(java.util.stream.Stream<org.springframework.security.concurrent.DelegatingSecurityContextRunnable>)'
BackgroundJobRequest.enqueue(jobs);
You can wrap the
Runnablethat is submitted to Jobrunr byDelegatingSecurityContextRunnableIt requires you to define the
SecurityContextfor running theRunnableand it will take care of setting up and cleaningSecurityContextbefore and after running the task.When configuring the
SecurityContext, it is better to align with the existing used authentication mechanism to define anAuthenticationobject that has enough permission to run the job.Below is a getting started example :