Spring Security Unexpected Behaviour for Public Endpoints - spring

I have a Spring HttpSecurity configuration as
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.csrf().disable().httpBasic().and()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/secure/**").authenticated()
.antMatchers("/backend/**").authenticated()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
}
It might be stupid for the client to set the Authorization Header for '/public/**' endpoints.
However, I noticed Spring Security attempts to authenticate tries to create an authenticated session for even public requests because the Authorization Header was provided.
Should the HttpSecurity config not override this behaviour?

Answered in the comments:
No it shouldn't... Permit all is something different as not secured at all. For the latter override the 'configure(WebSecurity)' and use the 'ignoring' for no security at all.

Related

Spring Security: don't redirect to login page in case unauthorised

I have Spring Security with oAuth2 authorisation.
I use it for REST API.
My configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf().disable()
.authorizeRequests()
.antMatchers("/health").permitAll()
.antMatchers("/**").authenticated()
.and()
.oauth2Login()
.and()
.httpBasic();
}
}
I need to make all requests return me 401 when I didn't authorise.
But now when I'm not authorised I got redirect to /login page.
I need to use it like usual REST API: if I did authorise then get content, otherwise get 401 Unauthorised.
How I can make it?
Thanks in addition for help.
Basically you need to configure an AuthenticationEntryPoint which is invoked when Spring Security detects a non-authenticated request. Spring also gives you a handy implementation which enables you to return whatever HttpStatus you need:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
//rest of your config...
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
}

spring boot security allow post request but only with permission

So my problem is a little different from the rest of the spring boot questions. I want to allow post requests in my security config but only with authentication
here is my config file:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
http.csrf().disable();
}
thanks for helping ;)
You can use antMachers with the following pattern.
antMatchers(HttpMethod.POST)
if you want to authenticate POST method of only certainpath
antMatchers(HttpMethod.POST, "/path")

Spring security antMatcher not working as expected

I have my custom controller "/my-endpoint" and spring app with the following configuration:
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/my-endpoint", "/health")
.permitAll()
.antMatchers(DENY_RESOURCE_PATTERNS)
.denyAll()
.anyRequest()
.authenticated()
}
It seems that for a unanimous user it working fine. But if I already authorized (using oauth2) and my session(or token) is expired -> spring trying to redirect me to the login page.
I don't want this, I want to allow any user to connect to "/my-endpoint" endpoint.
What I forgot to configure?
The interesting thing, that built-in endpoint "/health" working as expected, even if session is expired.
you can use configure(WebSecurity web). It will bypass the Spring Security Filters and will allow any user to access the endpoint. see HttpSecurity vs WebSecurity
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(HttpMethod.yourMethod, "/health")
.antMatchers(HttpMethod.yourMethod, "/my-endpoint");
}

Securing same endpoint with multiple configurations

We have a microservice architecture with securities for front to back with JWT, and back-to-back security with HTTP Basic.
Here is our configuration class for JWT :
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers(endpointsProperties.getJwtWithWildcard())
.and()
.csrf().disable()
.authorizeRequests().anyRequest().authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class);
}
jwtFilter is a simple filter that reads the Authorization header, and set the SecurityContextHolder.
And the HTTP Basic :
#Override
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
for (Map<String, String> userData : properties.getUsers()) {
auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser(userData.get("login")).password(userData.get("password")).authorities(BASIC_AUTH_AUTHORITY);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers(endpoints.getBasicWithWildcard() )
.and().csrf().disable()
.authorizeRequests().anyRequest().authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().httpBasic();
}
Those configuration class are used in differnets services, with distinct JWT and HTTP Auth endpoints. They are used either at the same time or independently. EndpointsProperties are loaded from application.yml.
But now, we have some referential microservices that we want to be reached either by other services or direclty by a (web) frontend application. We want to know if it is possible to secure a same URL ('/api/referential', for example) with the two different methods. Combining those configuration class with the same endpoints does not work, and it seems one configuration eraze the other.
Is it possible to secure a same URL path with different methods like that ? If yes, what do we need to change to enable it ?
Thanks for your support.
I think you can just add the two filters to the filter chain in this order
BasicAuthenticationFilter
JwtFilter
and make sure the ignoreFailure property of the BasicAuthenticationFilter is set to true.
This will make The basicAuthFilter authenticate requests with basicAuth and just continue down the filter chain if no basicAuth is sent - thus delegating to the JwtFilter.
then remove .httpBasic() from the WebsecurityConfig - as it will try to add another BasicSecurityFilter.
Just an off the cuff idea

Mix HttpBasic and FormLogin in Spring Security with Spring-boot-starter

I use spring-boot-starter 0.5.0.M6 with spring security to build my application which contains:
"/admin/"**: should be accessible to anyone have role ADMIN, form-based login
"/api/"**: should be accessible to anyone have role API, http basic login
My first attempt was:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.and()
.formLogin()
.defaultSuccessUrl("/admin/home")
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"))
.permitAll();
http
.authorizeRequests()
.antMatchers("/api/**").hasRole("API")
.and()
.httpBasic();
}
With this approach:
all the "/admin/" and "/api/" can authentication use both basic & form-based login. This is not a critical issue.
when any security issue occurred, eg: authentication failed, or authorization failed, the login form is shown. This is a critical issue, I want if /api/** get authentication failed or authorization failed, it show the basic authentication popup with 401/403 status code.
Then I try with the solution from https://github.com/spring-projects/spring-security-javaconfig/blob/master/samples-web.md#sample-multi-http-web-configuration, but I only able to secure either /api/** or /admin/** but not both, depends on which one I annotated with #Order.
Please give me a hand.
Thanks much
For your api part, use the following. Note the first ant matcher that limits the scope of what is filtered by this security configuration. That was the part I did not understand at first from your reference.
#Configuration
#Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// the ant matcher is what limits the scope of this configuration.
http.antMatcher("/api/**").authorizeRequests()
.antMatchers("/api/**").authenticated()
.and().httpBasic().realmName("Sourcing API");
}
}

Resources