I am using spring web-flux (spring-boot-starter-webflux - 2.7.5)
I am trying to update the pathMatchers pattern (spring security) for authentication programmatically but it is not taking any effect.
My declarative security config
-------------------------------
http
.csrf().disable()
.authorizeExchange()
.pathMatchers("index","/css/*","js/*").permitAll()
.pathMatchers("/v2/**", "/server-1/**", "/service-2/**").authenticated()
updating the pathMatchers programmatically
-----------------------------------------
#Autowired
ServerHttpSecurity serverHttpSecurity;
#PostMapping(value = "/api/config/update", produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<ResponseEntity<String>> fetchServiceAPIEndpoints() throws IOException {
log.info("fetchServiceAPIEndpoints");
serverHttpSecurity.authorizeExchange().pathMatchers("").authenticated();
return Mono.just(ResponseEntity.ok().body("Success"));
}
Could someone help me why the update of pathMatchers is not taking any effect?
Related
I am trying to build a custom authentication manager for my spring-webflux app. However I find that my manager is never called. My code below:
#Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
return http
.authorizeExchange().pathMatchers("/**").authenticated().and().httpBasic().disable()
.securityContextRepository(webSessionServerSecurityContextRepository())
.addFilterAfter(new AuthenticationWebFilter(bearerTokenAuthenticationManager()),
SecurityWebFiltersOrder.REACTOR_CONTEXT)
.build();
}
What am I doing wrong?
Assuming you put this bean in a class annotated with #Configuration and #EnableWebFluxSecurity your problem seems that you didn't disabled csrf that is configured by default by Spring Security.
You can do that with the following:
#Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
return http
.authorizeExchange().pathMatchers("/**").authenticated()
.and()
.httpBasic().disable()
.csrf().disable() // Disable csrf
.securityContextRepository(webSessionServerSecurityContextRepository())
.addFilterAfter(new AuthenticationWebFilter(bearerTokenAuthenticationManager()),
SecurityWebFiltersOrder.REACTOR_CONTEXT)
.build();
}
Furthermore, you have to configure correctly the AuthenticationWebFilter.
An AuthenticationWebFilter has the following dependencies:
...most of them are provided by default as HttpBasic deps (copy and pasted from Spring Security source code):
private final ReactiveAuthenticationManagerResolver<ServerWebExchange> authenticationManagerResolver;
private ServerAuthenticationSuccessHandler authenticationSuccessHandler = new WebFilterChainServerAuthenticationSuccessHandler();
private ServerAuthenticationConverter authenticationConverter = new ServerHttpBasicAuthenticationConverter();
private ServerAuthenticationFailureHandler authenticationFailureHandler = new ServerAuthenticationEntryPointFailureHandler(new HttpBasicServerAuthenticationEntryPoint());
private ServerSecurityContextRepository securityContextRepository = NoOpServerSecurityContextRepository.getInstance(); // Stateless session
private ServerWebExchangeMatcher requiresAuthenticationMatcher = ServerWebExchangeMatchers.anyExchange();
You could set whatever you want with the setters method of AuthenticationWebFilter. An AuthenticationWebFilter has the following logic:
So depending of the case you have to configure one dependency or another. You could see a complete example of how Authentication and Authorization works in my repo: https://github.com/soasada/kotlin-coroutines-webflux-security (is in kotlin but for the case is the same)
I'm developing an application using Spring security.
#Override
public void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.csrf().disable().authorizeRequests().antMatchers("/api/client/findByVariable?variable=").permitAll();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().requestMatchers()
.antMatchers("/api/**").and().authorizeRequests().antMatchers("/api/**")
.access("#oauth2.hasScope('read') or (!#oauth2.isOAuth() and hasRole('USER'))");
// #formatter:on
}
How can I modify above code so that endpoint "/api/client/findByVariable?variable=" can be allowed to be accessed without requiring authentication just as if there was no Spring Security ?
I tried adding the line :
http.csrf().disable().authorizeRequests().antMatchers("/api/client/findByVariable?variable=").permitAll();
But it is not working
You can ignore endpoints with overriding the configure method that gives you a WebSecurity instance:
#Override
public void configure(WebSecurity web)
{
web.ignoring().antMatchers("/api/client/findByVariable");
}
I'm not sure if you can also match by query params like /api/client/findByVariable?variable=*
I use this statements in the WebSecurityConfigurerAdapter#configure method to secure my application.
If csrf is disabled (http.csrf().disable();) than everything works fine, if I remove this line than I get an exception (Forbidden 403).
It is not clear for me why - I want to be safe against csrf- attack.
Does anyone know what I am doing wrong?
#Override
protected void configure(final HttpSecurity http) throws Exception {
final List<String> activeProfiles = Arrays.asList(environment.getActiveProfiles());
final CsrfTokenResponseHeaderBindingFilter csrfFilter = csrfTokenResponseHeaderBindingFilter();
http.addFilterAfter(csrfFilter, CsrfFilter.class).headers().cacheControl().xssProtection();
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
final String[] restEndpointsToSecure = WebSecurityConfig.restEndpointsToSecure;
for (final String endpoint : restEndpointsToSecure) {
http.authorizeRequests().antMatchers("/" + endpoint + "/**").hasRole(UserRoleEnum.USER.toString());
}
xAuthTokenConfigurer.setDetailsService(userDetailsServiceBean());
final SecurityConfigurer<DefaultSecurityFilterChain, HttpSecurity> securityConfigurerAdapter = xAuthTokenConfigurer;
http.apply(securityConfigurerAdapter);
}
Spring Security CSRF Documentation
You need to include the token in your requests. If you use Thymeleaf as your templating engine, this is handled automatically. The documentation also describes how to handle Ajax as well.
I am trying to secure a web application using Spring Security java configuration.
This is how the configuration looks:-
#Configuration
#EnableWebMvcSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private String googleClientSecret;
#Autowired
private CustomUserService customUserService;
/*
* (non-Javadoc)
*
* #see org.springframework.security.config.annotation.web.configuration.
* WebSecurityConfigurerAdapter
* #configure(org.springframework.security.config
* .annotation.web.builders.HttpSecurity)
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/","/static/**", "/resources/**","/resources/public/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic().disable()
.requiresChannel().anyRequest().requiresSecure();
// #formatter:on
super.configure(http);
}
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
// #formatter:off
auth
.eraseCredentials(true)
.userDetailsService(customUserService);
// #formatter:on
super.configure(auth);
}
}
Notice that I have explicitly disabled HTTP Basic authentication using:-
.httpBasic().disable()
I am still getting HTTP Authenticaton prompt box while accessing a secured url. Why?
Please help me fix this.
I just want to render the default login form that comes bundled.
Spring Boot Starter Version : 1.1.5
Spring Security Version : 3.2.5
Thanks
First of all, calling super.configure(http); will override whole your configuration you have before that.
Try this instead:
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic().disable();
In case you use Spring Boot, the documentation states:
To switch off the Boot default configuration completely in a web
application you can add a bean with #EnableWebSecurity
So if you want to fully customize itself that might be an option.
Just to make it clear... You just need to put #EnableWebSecurity annotation on your main application class or application configuration class.
You can disable the formLogin through the HttpSecurity instance as follow:
http.authorizeRequests().antMatchers("/public/**").permitAll()
.antMatchers("/api/**").hasRole("USER")
.anyRequest().authenticated()
.and().formLogin().disable();
This will lead receiving 403 Http error when trying to access any secured resource
Anonymous option worked for me. My code like
http.csrf().disable().headers().frameOptions().sameOrigin().and().
authorizeRequests().anyRequest().anonymous().and().httpBasic().disable();
Suitable for Spring Boot or folks using OAuth
#Profile("test")
#EnableWebSecurity
static class BasicWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().anonymous().and().httpBasic().disable();
}
}
If you are using #EnableOAuth2Client or #EnableResourceServer, then in test profile switch to basic auth and then disable the same. In Spring Boot,to switch off the spring security default configuration completely in a web application you need to add a bean with #EnableWebSecurity
The following worked for me:
http
.authorizeRequests()
.anyRequest().permitAll();
I want to convert spring security configuration from xml to java config.
Is't nearly done, the last issue is the AuthenticationEntryPoint. The settings of it in HttpSecurity will be ignored.
I use Spring security 3.2.0.M2
Snipped of SecurityConfig.class
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(httpPayloadFilter(), ChannelProcessingFilter.class)
.addFilterAfter(httpRestLoginFilter(), SecurityContextPersistenceFilter.class)
.authorizeUrls()
.antMatchers("/**").hasRole("USER")
.antMatchers("/secure/clientident/**").hasRole("REQUESTVALID")
.and()
.httpBasic().authenticationEntryPoint(delegatingAuthenticationEntryPoint());
}
#Bean
public DelegatingAuthenticationEntryPoint delegatingAuthenticationEntryPoint() {
ELRequestMatcher matcher = new ELRequestMatcher("hasHeader('user-agent', 'Mozilla') or " +
"hasHeader('user-agent', 'Chromium') or " +
"hasHeader('user-agent', 'Chrome') or " +
"hasHeader('user-agent', 'Safari')");
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> map =
new LinkedHashMap<RequestMatcher, AuthenticationEntryPoint>();
map.put(matcher, new BasicAuthenticationEntryPoint());
DelegatingAuthenticationEntryPoint delegatingAuthenticationEntryPoint = new DelegatingAuthenticationEntryPoint(map);
delegatingAuthenticationEntryPoint.setDefaultEntryPoint(new Http403ForbiddenEntryPoint());
return delegatingAuthenticationEntryPoint;
}
I always get the "HTTP 403" (guess Http403ForbiddenEntryPoint) on client side.
I also have tried an easier config without delegatingAuthenticationEntryPoint like.
.httpBasic().authenticationEntryPoint(new BasicAuthenticationEntryPoint())
this will not work too.
Has anyone an idea what I'm doing wrong?
Add:
Should have locked better. Found another post about this issue.
need spring security java config example showing basic auth only
A Ticket SEC-2198 has also been placed.
current workaround.
.exceptionHandling()
.authenticationEntryPoint(delegatingAuthenticationEntryPoint())
.and()
.httpBasic();