Describe the bug
ObservationAuthorizationManager custom MessageSource implementation in AccessDeniedException message localization not working. Its always taking from SpringSecurityMessageSource
To Reproduce
Authenticate yourself with user/password /user endpoint and then call /admin
Expected behavior
ObservationAuthorizationManager custom MessageSource implementation should pick up custom localization message
Sample (https://github.com/deepaksorthiya/spring-boot-3-security-6-custom-authprovider)
Comment From: jzheaux
Thanks for reaching out, @deepaksorthiya. Spring Security configuration typically doesn't take MessageSource beans into account and so it's up to you to call the appropriate setter method.
There are several places where AuthorizationDeniedException and AccessDeniedException are thrown so it may be better for you to catch them in a common place and localize from there (ExceptionTranslationFilter already knows how to do this, for example). Can you say more about why you want the exception message localized?
Comment From: deepaksorthiya
@jzheaux Thanks for the reply. I would like to have a more specific message like "user:
Comment From: jzheaux
Gotcha, @deepaksorthiya. First, it's my recommendation that you take care when giving the user internal information like what privileges they would need to successfully perform an action. If they don't need to know it, I'd stick with Access Denied.
If you still feel you need to add more information, Spring Security now throws an AuthorizationDeniedException (a subclass of AccessDeniedException), which contains the reasons for the failure, including the permissions needed. If you catch that exception, then that should give you enough information to send a message that contains the permissions.
If you are using Spring MVC, you can use a global exception handler to catch AuthorizationDeniedException:
@ExceptionHandler(AuthorizationDeniedException.class)
public class Handler {
@ControllerAdvice
ModelAndView handle(AuthorizationDeniedException ex) {
// ...
}
}
If not, you can catch AccessDeniedExceptions by implementing AccessDeniedHandler. You'll wire your implementation to Spring Security like so:
@Bean
SecurityFilterChain filters(HttpSecurity http, AccessDeniedHandler denied) throws Exception {
http
.exceptionHandling((exceptions) -> exceptions.accessDeniedHandler(denied))
// ...
}
At that point, your AccessDeniedHandler implementation will be called each time an AccessDeniedException is thrown by Spring Security.
How well would something like this achieve what you are wanting to do?
Comment From: deepaksorthiya
@jzheaux Exactly, Thank you for your suggestions and support. I greatly appreciate it. Closing this ticket.
Comment From: deepaksorthiya
@jzheaux I came across https://github.com/jzheaux/spring-boot-3-security-6-custom-authprovider/tree/gh-16188, which is also a nice solution. Thank you again @jzheaux