package me.alidg.errors.conf; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; import org.springframework.context.annotation.Bean; import org.springframework.security.web.server.ServerAuthenticationEntryPoint; import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler; import static org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type.REACTIVE; /** * A reactive specific auto-configuration to register an {@link ServerAccessDeniedHandler} and another * {@link ServerAuthenticationEntryPoint} when the Reactive Spring Security is detected. These two handlers * are just gonna eventually delegate the exception handling procedure to plain old * {@link me.alidg.errors.WebErrorHandlers}. * * @author Ali Dehghani * @implNote In contrast with other handlers which register themselves automatically, in order to use these * two handlers, you should register them in your security configuration manually as follows: * <pre> * {@code * @EnableWebFluxSecurity * public class WebFluxSecurityConfig { * * // other configurations * * @Bean * public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http, * ServerAccessDeniedHandler accessDeniedHandler, * ServerAuthenticationEntryPoint authenticationEntryPoint) { * http * .csrf().accessDeniedHandler(accessDeniedHandler) * .and() * .exceptionHandling() * .accessDeniedHandler(accessDeniedHandler) * .authenticationEntryPoint(authenticationEntryPoint) * // other configurations * * return http.build(); * } * } * } * </pre> */ @ConditionalOnWebApplication(type = REACTIVE) @ConditionalOnBean(ErrorWebExceptionHandler.class) @ConditionalOnClass(name = "org.springframework.security.web.server.authorization.ServerAccessDeniedHandler") public class ReactiveSecurityErrorsAutoConfiguration { /** * Responsible for catching all access denied exceptions and delegating them to typical web error handlers * to perform the actual exception handling procedures. * * @param errorWebExceptionHandler Spring Boot's default exception handler which in turn would delegate to our * typical error handlers. * @return The registered access denied handler. */ @Bean @ConditionalOnClass(name = "org.springframework.security.web.server.authorization.ServerAccessDeniedHandler") public ServerAccessDeniedHandler accessDeniedHandler(ErrorWebExceptionHandler errorWebExceptionHandler) { return errorWebExceptionHandler::handle; } /** * Responsible for catching all authentication exceptions and delegating them to typical web error handlers * to perform the actual exception handling procedures. * * @param errorWebExceptionHandler Spring Boot's default exception handler which in turn would delegate to our * typical error handlers. * @return The registered authentication entry point. */ @Bean @ConditionalOnClass(name = "org.springframework.security.web.server.ServerAuthenticationEntryPoint") public ServerAuthenticationEntryPoint authenticationEntryPoint(ErrorWebExceptionHandler errorWebExceptionHandler) { return errorWebExceptionHandler::handle; } }