Trying to apply multiple http configuration as described in the documentation multiple-httpsecurity
Using Spring-4.1.6.RELEASE and Spring-Security-4.0.1.RELEASE (also tried 3.2.7.RELEASE)
As a result I'm getting only the basic auth applied against the /api/** pattern the formLogin is not working.
In the filterChain object during debug we can see that the UsernamePasswordAuthenticationFilter is missing.
On the other hand when tried to apply the #Order(1) annotation to the FormLoginWebSecurityConfigurerAdapter instead to the ApiWebSecurityConfigurationAdapter, got only the formLogin authentication applied. In the filterChain object during debug we can see that the BasicAuthenticationFilter is missing.
Feel free to use the source code of the project to reproduce the issue:
https://github.com/kmarabet/SpringSecurityMultiHttpSample
Related
I'm trying to enable HSTS in my Spring Boot application. I've added the following to my WebSecurityConfig (based on Enable HTTP Strict Transport Security (HSTS) with spring boot application):
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
protected void configure(HttpSecurity http) throws Exception
{
// Other http configurations, e.g. authorizeRequests and CSRF
// ...
http.headers().httpStrictTransportSecurity()
.maxAgeInSeconds(Duration.ofDays(365L).getSeconds())
.includeSubDomains(true);
}
}
I do get the strict-transport-security header when in HTTPS requests, but the max-age is always 0:
strict-transport-security: max-age=0; includeSubDomains
I'm getting the exact same header if I don't add the Spring configuration, so it looks my configuration is not being picked up. It appears to be specific to the HSTS configuration, because the other configurations, e.g. http.authorizeRequests(), are working. That seems to indicate that the HSTS configuration is somehow being overwritten, especially when considering that Spring's default max-age is one year. However, I've been able to find any other HSTS-related configuration in our codebase.
I also tried setting a breakpoint in o.springframework.s.c.a.w.c.HeadersConfigurer.HstsConfig#maxAgeInSeconds to check whether it's being called more than once. My call from configure was the only invocation.
Does anyone know why my HSTS configuration is not used? Or do you have any other ideas on how to debug this?
Turns out that this was caused by a Cloudflare configuration that rewrote the header and set the max-age to 0.
It was also easier to update the Cloudflare configuration than to update the configuration in every micro-service.
In a Spring Secuity / Boot application I have multiple #Configuration annotated Configurations that extend WebSecurityConfigurerAdapter.
In one of these specific configurations, I want to protect a specific URL with basic auth. I do that by overriding configure(final HttpSecurity) and using antMatcher("myURL") onto the HttpSecurity object, followed by the usual authorization-chain and httpBasic().
But configuring basic auth in spring also requires your configuration to override configure(final AuthenticationManagerBuilder auth), where you configure an authentication-mechanism, as I understand. In my case, that is a simple inMemoryAuthentication(), with user and password of my choice.
Now, I know that some of the other configurations in the project configure the rest of the urls with a way more complex authentication-mechanism, which implement's SSO. I am not entirely sure if my configuration, which messes with the AuthenticationManagerBuilder, interferes with these other mechanisms in any way?
My expectation is that, because in configure(final HttpSecurity) I use antMatcher("myURL"), this configuration will create a SecurityFilterChain that has my specific inMemoryAuthentication() logic (somewhere deep in a spring filter that handles basic auth) and that this chain will only be used for the requests matching "myURL" pattern. I expect other filters-chains that are created by other other existing configurations and their more complex authentication mechanisms to be unaffected by my new configuration. My new inMemoryAuthentication should never play a role there. Is that correct?
I'm trying to integrate waffle-spring-security4 with an existing Spring Boot project, where most of the configuration happens automatically. I've noticed that when the NegotiateSecurityFilter is in the chain, some weird things occur: I get ClassNotFoundException on initializing a completely trivial class with one String property; a Thymeleaf template which previously loaded fine now can't be resolved and so on. When this happened, I had the following filters in the chain:
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
NegotiateSecurityFilter (by Waffle)
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
With switching back to a HTTP Basic authentication the issue disappears, so I think the issue might be with the filters above. Do you have any idea on how to troubleshoot this? (If you have any strategy for debugging similar issues, that would be excellent.)
Yes, it was caused by Waffle, as it has turned out.
The problem was that once you've done a successful authentication with Waffle, for the rest of the run, the necessary files were not accessible. This caused everything which were trying to load something from the classpath to fail miserably. I have to add here that I've tried to run this from source with gradle bootRun and by building the jar and running that instead; in the first case, the Thymeleaf resolution failed, in the second, a Spring class was not found.
It turns out that if the remote user (who's logging in via SSO) doesn't have read access to the files, once the user it's authenticated, the application won't work normally anymore at all! I wasn't aware of this environmental change caused by Waffle, as I don't recall seeing anything about it on the docs - but it makes sense. After I gave read access to the user, it started to work.
I have been trying to get a grip on spring security and always get confused with the initial configuration. Where in few tutorial I find CSRF disabled and in few I found it enabled.
At some forum it's written as it's good to disable it and in some tutorials few people mention it's not a good practice to disable csrf.
My point is why do we need CSRF? what's the reason behind using CSRF? what if we disable it and why if we shouldn't disable it?
http.csrf()
.csrfTokenRepository(csrfTokenRepository()).and()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
and
http.csrf().disable()
.exceptionHandling().and()
.anonymous().and()
.servletApi().and()
.headers().cacheControl().and()
.authorizeRequests()
What's the best configuration if I am using Spring Security with REST? Because in second configuration it's showing me a popup window to login. And in first configuration it's giving me
(Expected CSRF token not found. Has your session expired?)
If CSFR is enabled or not depends on The Spring Security version and type of configuration used.
Before Spring Security 4, when using XML configuration CSFR would be disabled and when using Java based configuration it would be enabled. As of Spring Security 4 CSFR is enabled for both XML and Java based configuration by default.
Do you need CSFR, well if you have a public facing site or API I would say yes. Every security layer you disable makes your application more vulnerable.
What CSFR is is explained on this page
I am attempting to set the X-Frame-Options to DENY for all management endpoints, particularly the /error endpoint. I have the following in my application.properties of my Spring Boot application.
security.headers.frame=true
management.security.enabled=true
management.port=8001
When I go to http://localhost:8001/error I do not have the X-Frame-Options header, however the http://localhost:8001/trace endpoint does have the header. How do I configure my application.properties or what do I need to override to get that response header for the error endpoint?
Going through the current Spring Boot source (1.1.7.RELEASE), I don't see anyway that you can do what you want without totally doing away with the Security auto-configuration.
That is because in order for an endpoint to be eligible for the customized HTTP Headers (like X-Frame-Options) it needs to be a bean in the parent context (the one that is associated with the application on the normal port) that implements MvcEndpoint. Such beans are HealthMvcEndpoint, JolokiaMvcEndpoint etc.
My statement adove can be viewed in code at ManagementSecurityAutoConfiguration in the ManagementWebSecurityConfigurerAdapter.configure method (endpointHandlerMapping is created from the MvcEndpoint implementation beans).
The error page for the management app, is ManagementErrorEndpoint that is created in errorEndpoint of EndpointWebMvcChildContextConfiguration which is triggered when the child context is created (due the inclusion of the management app), which is too late to be included in the endpoints that supported for HTTP Headers customization
The /error endpoint is not an Actuator Endpoint and it's not secured by default (lots of errors can happen when a user is not authenticated). You could maybe make it available to anonymous users, but my guess is not even that would prevent some nasty infinite loops, where there is a mistake in the security configuration. I'm sure there's another way to add the header without Spring Security?