WebFlux Security :: Spring Security Why Spring Overview Trending Generative AI Cloud Architecture Patterns Microservices Reactive Event Driven Application Types Web Applications Serverless Batch Learn Getting Started Quickstart Guides Academy Courses Get Certified Projects Overview Projects Spring Boot Spring Framework Spring Cloud Spring AI Spring Data Spring Integration Spring Batch Spring Security Foundational Projects Micrometer Reactor Development Tools Spring Tools Spring Initializr Resources Blog Release Calendar Version Mappings Release Highlights Security Advisories GitHub Orgs Spring Projects Spring Cloud Community Overview Events Authors Enterprise Overview Long-term Support Automated Upgrades Governance and Compliance Modern App Development light Spring Security 7.0.7-SNAPSHOT Search Overview Prerequisites Community What’s New Preparing for 8.0 Migrating to 7 Servlet Authorization OAuth 2.0 SAML 2.0 Reactive Getting Spring Security Javadoc Features Authentication Password Storage Authorization Protection Against Exploits CSRF HTTP Headers HTTP Requests Integrations REST Client HTTP Service Clients Cryptography Spring Data Java’s Concurrency APIs Jackson Localization Project Modules Samples Servlet Applications Getting Started Architecture Authentication Authentication Architecture Username/Password Reading Username/Password Form Basic Digest Password Storage In Memory JDBC UserDetails CredentialsContainer Password Erasure UserDetailsService PasswordEncoder DaoAuthenticationProvider LDAP Multi-Factor Authentication Persistence Passkeys One-Time Token Session Management Remember Me Anonymous Pre-Authentication JAAS CAS X509 Run-As Logout Authentication Events Kerberos Introduction Reference Samples Appendices Authorization Authorization Architecture Authorize HTTP Requests Method Security Domain Object Security ACLs Authorization Events OAuth2 OAuth2 Log In Core Configuration Advanced Configuration OIDC Logout OAuth2 Client Core Interfaces and Classes OAuth2 Authorization Grants OAuth2 Client Authentication OAuth2 Authorized Clients OAuth2 Resource Server JWT Opaque Token Multitenancy Bearer Tokens DPoP-bound Access Tokens Protected Resource Metadata OAuth2 Authorization Server Getting Started Configuration Model Core Model / Components Protocol Endpoints SAML2 SAML2 Log In SAML2 Log In Overview SAML2 Authentication Requests SAML2 Authentication Responses SAML2 Logout SAML2 Metadata Migrating from Spring Security SAML Extension Protection Against Exploits Cross Site Request Forgery (CSRF) Security HTTP Response Headers HTTP HttpFirewall Integrations Concurrency Localization Servlet APIs Spring Data Spring MVC WebSocket Spring’s CORS Support JSP Taglib Observability Configuration Java Configuration Kotlin Configuration Namespace Configuration Testing Method Security MockMvc Support MockMvc Setup Security RequestPostProcessors Mocking Users Mocking CSRF Mocking Form Login Mocking HTTP Basic Mocking OAuth2 Mocking Logout Security RequestBuilders Security ResultMatchers Security ResultHandlers Appendix Database Schemas XML Namespace Authentication Services Web Security Method Security LDAP Security WebSocket Security Proxy Server Configuration FAQ Reactive Applications Getting Started Authentication X.509 Authentication Logout Session Management Concurrent Sessions Control Authorization Authorize HTTP Requests EnableReactiveMethodSecurity OAuth2 OAuth2 Log In Core Configuration Advanced Configuration OIDC Logout OAuth2 Client Core Interfaces and Classes OAuth2 Authorization Grants OAuth2 Client Authentication OAuth2 Authorized Clients OAuth2 Resource Server JWT Opaque Token Multitenancy Bearer Tokens Protection Against Exploits CSRF Headers HTTP Requests ServerWebExchangeFirewall Integrations CORS RSocket Observability Testing Testing Method Security Testing Web Security WebTestClient Setup Testing Authentication Testing CSRF Testing OAuth 2.0 Testing X509 WebFlux Security GraalVM Native Image Support Method Security Search Edit this Page GitHub Project Stack Overflow Spring Security Reactive Applications WebFlux Security This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Security 7.1.0! WebFlux Security Spring Security’s WebFlux support relies on a WebFilter and works the same for Spring WebFlux and Spring WebFlux.Fn. A few sample applications demonstrate the code: Hello WebFlux hellowebflux Hello WebFlux.Fn hellowebfluxfn Hello WebFlux Method hellowebflux-method Minimal WebFlux Security Configuration The following listing shows a minimal WebFlux Security configuration: Minimal WebFlux Security Configuration Java Kotlin @Configuration @EnableWebFluxSecurity public class HelloWebfluxSecurityConfig { @Bean public MapReactiveUserDetailsService userDetailsService() { UserDetails user = User.withDefaultPasswordEncoder() .username("user") .password("user") .roles("USER") .build(); return new MapReactiveUserDetailsService(user); } } @Configuration @EnableWebFluxSecurity class HelloWebfluxSecurityConfig { @Bean fun userDetailsService(): ReactiveUserDetailsService { val userDetails = User.withDefaultPasswordEncoder() .username("user") .password("user") .roles("USER") .build() return MapReactiveUserDetailsService(userDetails) } } This configuration provides form and HTTP basic authentication, sets up authorization to require an authenticated user for accessing any page, sets up a default login page and a default logout page, sets up security related HTTP headers, adds CSRF protection, and more. Explicit WebFlux Security Configuration The following page shows an explicit version of the minimal WebFlux Security configuration: Explicit WebFlux Security Configuration Java Kotlin @Configuration @EnableWebFluxSecurity public class HelloWebfluxSecurityConfig { @Bean public MapReactiveUserDetailsService userDetailsService() { UserDetails user = User.withDefaultPasswordEncoder() .username("user") .password("user") .roles("USER") .build(); return new MapReactiveUserDetailsService(user); } @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http .authorizeExchange((authorize) -> authorize .anyExchange().authenticated() ) .httpBasic(withDefaults()) .formLogin(withDefaults()); return http.build(); } } import org.springframework.security.config.web.server.invoke @Configuration @EnableWebFluxSecurity class HelloWebfluxSecurityConfig { @Bean fun userDetailsService(): ReactiveUserDetailsService { val userDetails = User.withDefaultPasswordEncoder() .username("user") .password("user") .roles("USER") .build() return MapReactiveUserDetailsService(userDetails) } @Bean fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { return http { authorizeExchange { authorize(anyExchange, authenticated) } formLogin { } httpBasic { } } } } Make sure to import the org.springframework.security.config.web.server.invoke function to enable the Kotlin DSL in your class, as the IDE will not always auto-import the method, causing compilation issues. This configuration explicitly sets up all the same things as our minimal configuration. From here, you can more easily make changes to the defaults. You can find more examples of explicit configuration in unit tests, by searching for EnableWebFluxSecurity in the config/src/test/ directory. Multiple Chains Support You can configure multiple SecurityWebFilterChain instances to separate configuration by RequestMatcher instances. For example, you can isolate configuration for URLs that start with /api: Java Kotlin @Configuration @EnableWebFluxSecurity static class MultiSecurityHttpConfig { @Order(Ordered.HIGHEST_PRECEDENCE) (1) @Bean SecurityWebFilterChain apiHttpSecurity(ServerHttpSecurity http) { http .securityMatcher(new PathPatternParserServerWebExchangeMatcher("/api/**")) (2) .authorizeExchange((authorize) -> authorize .anyExchange().authenticated() ) .oauth2ResourceServer(OAuth2ResourceServerSpec::jwt); (3) return http.build(); } @Bean SecurityWebFilterChain webHttpSecurity(ServerHttpSecurity http) { (4) http .authorizeExchange((authorize) -> authorize .anyExchange().authenticated() ) .httpBasic(withDefaults()); (5) return http.build(); } @Bean ReactiveUserDetailsService userDetailsService() { return new MapReactiveUserDetailsService( PasswordEncodedUser.user(), PasswordEncodedUser.admin()); } } import org.springframework.security.config.web.server.invoke @Configuration @EnableWebFluxSecurity open class MultiSecurityHttpConfig { @Order(Ordered.HIGHEST_PRECEDENCE) (1) @Bean open fun apiHttpSecurity(http: ServerHttpSecurity): SecurityWebFilterChain { return http { securityMatcher(PathPatternParserServerWebExchangeMatcher("/api/**")) (2) authorizeExchange { authorize(anyExchange, authenticated) } oauth2ResourceServer { jwt { } (3) } } } @Bean open fun webHttpSecurity(http: ServerHttpSecurity): SecurityWebFilterChain { (4) return http { authorizeExchange { authorize(anyExchange, authenticated) } httpBasic { } (5) } } @Bean open fun userDetailsService(): ReactiveUserDetailsService { return MapReactiveUserDetailsService( PasswordEncodedUser.user(), PasswordEncodedUser.admin() ) } } 1 Configure a SecurityWebFilterChain with an @Order to specify which SecurityWebFilterChain Spring Security should consider first 2 Use PathPatternParserServerWebExchangeMatcher to state that this SecurityWebFilterChain will only apply to URL paths that start with /api/ 3 Specify the authentication mechanisms that will be used for /api/** endpoints 4 Create another instance of SecurityWebFilterChain with lower precedence to match all other URLs 5 Specify the authentication mechanisms that will be used for the rest of the application Spring Security selects one SecurityWebFilterChain @Bean for each request. It matches the requests in order by the securityMatcher definition. In this case, that means that, if the URL path starts with /api, Spring Security uses apiHttpSecurity. If the URL does not start with /api, Spring Security defaults to webHttpSecurity, which has an implied securityMatcher that matches any request. Modular ServerHttpSecurity Configuration Many users prefer that their Spring Security configuration lives in a centralized place and will choose to configure it within the SecurityWebFilterChain Bean declaration. However, there are times that users may want to modularize the configuration. This can be done using: Customizer<ServerHttpSecurity> Beans Top Level ServerHttpSecurity Customizer Beans Customizer<ServerHttpSecurity> Beans If you would like to modularize your security configuration you can place logic in a Customizer<ServerHttpSecurity> Bean. For example, the following configuration will ensure all ServerHttpSecurity instances are configured to: Java Kotlin @Bean Customizer<ServerHttpSecurity> httpSecurityCustomizer() { return (http) -> http .headers((headers) -> headers .contentSecurityPolicy((csp) -> csp (1) .policyDirectives("object-src 'none'") ) ) (2) .redirectToHttps(Customizer.withDefaults()); } @Bean fun httpSecurityCustomizer(): Customizer<ServerHttpSecurity> { return Customizer { http -> http .headers { headers -> headers .contentSecurityPolicy { csp -> csp (1) .policyDirectives("object-src 'none'") } } (2) .redirectToHttps(Customizer.withDefaults()) } } 1 Set the Content Security Policy to object-src 'none' 2 Redirect any request to https Top Level ServerHttpSecurity Customizer Beans If you prefer to have further modularization of your security configuration, Spring Security will automatically apply any top level HttpSecurity Customizer Beans. A top level HttpSecurity Customizer type can be summarized as any Customizer<T> that matches public HttpSecurity.*(Customizer<T>). This translates to any Customizer<T> that is a single argument to a public method on HttpSecurity. A few examples can help to clarify. If Customizer<ContentTypeOptionsConfig> is published as a Bean, it will not be be automatically applied because it is an argument to HeadersConfigurer.contentTypeOptions(Customizer) which is not a method defined on HttpSecurity. However, if Customizer<HeadersConfigurer<HttpSecurity>> is published as a Bean, it will be automatically applied because it is an argument to HttpSecurity.headers(Customizer). For example, the following configuration will ensure that the Content Security Policy is set to object-src 'none': Java Kotlin @Bean Customizer<ServerHttpSecurity.HeaderSpec> headersSecurity() { return (headers) -> headers .contentSecurityPolicy((csp) -> csp (1) .policyDirectives("object-src 'none'") ); } @Bean fun headersSecurity(): Customizer<ServerHttpSecurity.HeaderSpec> { return Customizer { headers -> headers .contentSecurityPolicy { csp -> csp (1) .policyDirectives("object-src 'none'") } } } Customizer Bean Ordering First each Customizer<HttpSecurity> Bean is applied using ObjectProvider#orderedStream(). This means that if there are multiple Customizer<HttpSecurity> Beans, the @Order annotation can be added to the Bean definitions to control the ordering. Next every Top Level HttpSecurity Customizer Beans type is looked up and each is is applied using ObjectProvider#orderedStream(). If there is are two Customizer<HeadersConfigurer<HttpSecurity>> beans and two Customizer<HttpsRedirectConfigurer<HttpSecurity>> instances, the order that each Customizer type is invoked is undefined. However, the order that each instance of Customizer<HttpsRedirectConfigurer<HttpSecurity>> is defined by ObjectProvider#orderedStream() and can be controlled using @Order on the Bean the definitions. Finally, the HttpSecurity Bean is injected as a Bean. All Customizer instances are applied before the HttpSecurity Bean is created. This allows overriding the customizations provided by the Customizer Beans. You can find an example below that illustrates the ordering: Java Kotlin @Bean (4) SecurityWebFilterChain springSecurity(ServerHttpSecurity http) { http .authorizeExchange((exchange) -> exchange .anyExchange().authenticated() ); return http.build(); } @Bean @Order(Ordered.LOWEST_PRECEDENCE) (2) Customizer<ServerHttpSecurity> userAuthorization() { return (http) -> http .authorizeExchange((exchange) -> exchange .pathMatchers("/users/**").hasRole("USER") ); } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) (1) Customizer<ServerHttpSecurity> adminAuthorization() { return (http) -> http .authorizeExchange((exchange) -> exchange .pathMatchers("/admins/**").hasRole("ADMIN") ); } (3) @Bean Customizer<ServerHttpSecurity.HeaderSpec> contentSecurityPolicy() { return (headers) -> headers .contentSecurityPolicy((csp) -> csp .policyDirectives("object-src 'none'") ); } @Bean Customizer<ServerHttpSecurity.HeaderSpec> contentTypeOptions() { return (headers) -> headers .contentTypeOptions(Customizer.withDefaults()); } @Bean Customizer<ServerHttpSecurity.HttpsRedirectSpec> httpsRedirect() { return Customizer.withDefaults(); } @Bean (4) fun springSecurity(http: ServerHttpSecurity): SecurityWebFilterChain { http .authorizeExchange({ exchanges -> exchanges .anyExchange().authenticated() }) return http.build() } @Bean @Order(Ordered.LOWEST_PRECEDENCE) (2) fun userAuthorization(): Customizer<ServerHttpSecurity> { return Customizer { http -> http .authorizeExchange { exchanges -> exchanges .pathMatchers("/users/**").hasRole("USER") } } } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) (1) fun adminAuthorization(): Customizer<ServerHttpSecurity> { return ThrowingCustomizer { http -> http .authorizeExchange { exchanges -> exchanges .pathMatchers("/admins/**").hasRole("ADMIN") } } } (3) @Bean fun contentSecurityPolicy(): Customizer<ServerHttpSecurity.HeaderSpec> { return Customizer { headers -> headers .contentSecurityPolicy { csp -> csp .policyDirectives("object-src 'none'") } } } @Bean fun contentTypeOptions(): Customizer<ServerHttpSecurity.HeaderSpec> { return Customizer { headers -> headers .contentTypeOptions(Customizer.withDefaults()) } } @Bean fun httpsRedirect(): Customizer<ServerHttpSecurity.HttpsRedirectSpec> { return Customizer.withDefaults() } 1 First all Customizer<HttpSecurity> instances are applied. The adminAuthorization Bean has the highest @Order so it is applied first. If there are no @Order annotations on the Customizer<HttpSecurity> Beans or the @Order annotations had the same value, then the order that the Customizer<HttpSecurity> instances are applied is undefined. 2 The userAuthorization is applied next due to being an instance of Customizer<HttpSecurity> 3 The order that the Customizer types are undefined. In this example, the order of contentSecurityPolicy, contentTypeOptions, and httpsRedirect are undefined. If @Order(Ordered.HIGHEST_PRECEDENCE) was added to contentTypeOptions, then we would know that contentTypeOptions is before contentSecurityPolicy (they are the same type), but we do not know if httpsRedirect is before or after the Customizer<HeadersConfigurer<HttpSecurity>> Beans. 4 After all of the Customizer Beans are applied, the HttpSecurity is passed in as a Bean. Spring Security Stable 7.1.0 7.0.6 6.5.11 Snapshot 7.1.1-SNAPSHOT 7.0.7-SNAPSHOT 6.5.12-SNAPSHOT Related Spring Documentation Spring Framework Spring Security Spring Authorization Server Spring LDAP Spring Security Kerberos Spring Session Spring Vault Spring GraphQL All Docs... Copyright © 2005 - Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. Terms of Use • Privacy • Trademark Guidelines • Thank you • Your California Privacy Rights • Cookie Settings Apache®, Apache Tomcat®, Apache Kafka®, Apache Cassandra™, and Apache Geode™ are trademarks or registered trademarks of the Apache Software Foundation in the United States and/or other countries. Java™, Java™ SE, Java™ EE, and OpenJDK™ are trademarks of Oracle and/or its affiliates. Kubernetes® is a registered trademark of the Linux Foundation in the United States and other countries. Linux® is the registered trademark of Linus Torvalds in the United States and other countries. Windows® and Microsoft® Azure are registered trademarks of Microsoft Corporation. “AWS” and “Amazon Web Services” are trademarks or registered trademarks of Amazon.com Inc. or its affiliates. All other trademarks and copyrights are property of their respective owners and are only mentioned for informative purposes. Other names may be trademarks of their respective owners. Search in all Spring Docs