Multiple HttpSecurity for different path matcher - java

In my current system, we are using below functionality for Spring Security gateway which is mentioned below.
http
.csrf().disable()
.exceptionHandling()
.and()
.httpBasic().disable()
but now I want to build a new endpoint which will use HTTP basic auth. How to manage this things using PathMatcher?
If we want to use different configuration methods for HTTP basic auth disable or enable. How it will work for me?
When I will use two filter inside same class then I will get below error:
Description:
The bean 'conversionServicePostProcessor', defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

The Spring Security documentation has some examples of how to do that.
I think you could do something like:
#Configuration
#EnableWebFluxSecurity
static class MultiSecurityHttpConfig {
#Order(Ordered.HIGHEST_PRECEDENCE)
#Bean
SecurityWebFilterChain yourEndpointHttpSecurity(ServerHttpSecurity http) {
http
.securityMatcher(new PathPatternParserServerWebExchangeMatcher("/your-endpoint/**"))
.authorizeExchange((exchanges) -> exchanges
.anyExchange().authenticated()
)
.httpBasic(withDefaults());
return http.build();
}
#Bean
SecurityWebFilterChain webHttpSecurity(ServerHttpSecurity http) {
http
.csrf().disable()
.exceptionHandling().and()
.httpBasic().disable()
return http.build();
}
}
This way firstly your yourEndpointHttpSecurity Bean would be evaluated if the path matches /your-endpoint/** and then your default webHttpSecurity

Related

Migration to the new spring security configuration fails

I am currently migrating the version from Spring to the newest one, but having a lot of struggle when it comes to the new SecurityFilterChain settings.
I am having a list of endpoints which should be available for all. Mainly login, registration as well as some callbacks from other partner sides. Before the migration I've just provided the array to the filter and it worked.
The current (new) implemetation looks like this:
#Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable).cors(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers(Endpoints.PUBLIC_ENDPOINTS).permitAll()
.anyRequest().authenticated()
)
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
This gives me a 401 Unauthorized for the /authentication/login endpoint. What I am doing wrong? Is there any good tutorial or example for the new way of creating the filter.
For completeness here my old implementation:
httpSecurity.cors().and().csrf().disable() // dont authenticate this particular request
.authorizeRequests()
.antMatchers(Endpoints.PUBLIC_ENDPOINTS)
.permitAll()
.anyRequest() // all other requests need to be authenticated
.authenticated().and().exceptionHandling() // make sure we use stateless session; session won't be used to
// store user's state.
.authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
I've finally found the solution to my problem.
It had nothing to do with the code above. The problem was that the Annotation for the application had some parameters for scanBasePackages. I've removed them and everything started working nicely. The commented line is the old one, not working.
//#SpringBootApplication(scanBasePackages = {"de.company.app.data.user", "de.company.app.security"})
#SpringBootApplication

Spring-Security : OAuth2 Set roles in user object before it is stored in the security context

The goal is to manipulate the roles of a user(or simply create a new Authentication object since I'v got a hunch they cant be manipulated directly) before its stored in the context. After a lot of digging I found that the authentication is perfomred in the OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication and later stored using a sessionStrategy.
The part where I am stuck at is telling spring to use/override that filter.
So far I have managed to create a CustomOAuth2ClientAuthenticationProcessingFilter extending the original one.
I tried to instantiate the filter and add it to the filter chane like so.
#Configuration
#EnableOAuth2Sso
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/login**", "/callback/**", "/resources/**", "/static/**", "/webjars/**", "/webjar/**", "/error**")
.permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.csrf().disable()
.logout()
.permitAll()
.logoutSuccessUrl("/")
.and().addFilterAt(createCustomOAuth2ClientAuthenticationProcessingFilter(), AbstractPreAuthenticatedProcessingFilter.class)
;
}
private CustomOAuth2ClientAuthenticationProcessingFilter createCustomOAuth2ClientAuthenticationProcessingFilter(){
OAuth2SsoProperties sso = (OAuth2SsoProperties)this.getApplicationContext().getBean(OAuth2SsoProperties.class);
OAuth2RestOperations restTemplate = ((UserInfoRestTemplateFactory)this.getApplicationContext().getBean(UserInfoRestTemplateFactory.class)).getUserInfoRestTemplate();
ResourceServerTokenServices tokenServices = (ResourceServerTokenServices)this.getApplicationContext().getBean(ResourceServerTokenServices.class);
CustomOAuth2ClientAuthenticationProcessingFilter customFilter=new CustomOAuth2ClientAuthenticationProcessingFilter(sso.getLoginPath());
customFilter.setRestTemplate(restTemplate);
customFilter.setTokenServices(tokenServices);
customFilter.setApplicationEventPublisher(this.getApplicationContext());
return customFilter;
}
but that, as expected, just calls both filters- mine and the default one.
Is there a way to "replace" the original filter functionality without creating serious issues and save the ability to later use the #Secured anotation for example, in order to secure application endpoints ?
I'v read about using postProcessor in the configuration but never found an extensive well expleined answer.I'v also read about custom configuration classes but not for OAuth2 . Any suggestions are welcome.

SpringBoot Security Configuration not working as intended

I have been trying to configure Spring Boot security in order to allow some urls without requiring an authentication and not allowing any other requests without an authentication. I am having trouble achieving this.
As per my understanding, anyRequest().authenticated() requires previously declared antMatchers to require authentication.
How is it possible to achieve my requirement.
My Http Security configuration
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.antMatchers(HttpMethod.POST,SIGN_UP_URL).permitAll()
.antMatchers(HttpMethod.GET,banner_top_url).permitAll()
.antMatchers(HttpMethod.GET,banner_bottom_url).permitAll()
.antMatchers(HttpMethod.GET,javascript_url).permitAll()
.antMatchers(HttpMethod.GET,stylesheet_url).permitAll()
.antMatchers(HttpMethod.GET,photos_url).permitAll()
.antMatchers(HttpMethod.GET,transformed_photos_url).permitAll()
.antMatchers(HttpMethod.GET,preview_url).permitAll()
.antMatchers(HttpMethod.GET, "/", "/**/*.html", "/static/favicon.ico", "/**/*.js", "/**/*.js.map", "/**/*.css", "/**/*.png", "/**/*.jpg", "/**/*.jpeg", "/**/*.gif", "/**/*.ttf", "/**/*.json", "/**/*.woff", "/**/*.woff2", "/**/*.eot", "/**/*.svg").permitAll()// allows static content from resource folder
.antMatchers("/error").permitAll() // By default Security framework disables error pages (Unauthrorized)
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and().addFilterBefore(jwtExceptionHandler,CorsFilter.class)
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
// this disables session creation on Spring Security
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().formLogin().disable();
}
I assume that the below urls must be granted access without authentication.
SIGN_UP_URL
banner_top_url
banner_bottom_url
javascript_url
stylesheet_url
photos_url
transformed_photos_url
preview_url
The problem is this line : .anyRequest().authenticated()
If I remove it, then all the endpoints within the REST interface becomes available without authentication which I do not want.
Why aren't you excluding the static resource files globally via web.ignoring?
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
By default, Spring-security allows to pass everything. You have to tell Spring what can pass and what cannot pass. By removing anyRequest().authenticated you are telling to spring that everything that matches the patterns you mentioned are allowed to go and with the rest do what you do by default, that means, proceed. Here you are Spring Security doc: https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#jc-httpsecurity
I have found that Spring-Working as intended. That being said,any antMAtchers will match the requestPath and not the resourcePath. An example is provided below.
*localhost:8080/image.jpg*
points at the root of the application which is src/main/resources/static/image.jpg
Now why is static used as a resource handler, that is because in the staticResourceConfiguration.java class I had the following lines
registry
.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");

Spring security application of antMatcher() vs. antMatchers()

Just want to see whether I'm interpreting the answer to this question the right way.
If we only need to secure one path like this:
http.antMatcher("/api/**").authorizeRequests()....
Then use antMatcher().
If we need to secure multiple URL paths like this:
http
.authorizeRequests()
.antMatchers("/high_level_url_A/sub_level_1").hasRole('USER')
.antMatchers("/high_level_url_A/sub_level_2").hasRole('USER2')
...
Then use antMatchers().
There are two answers in this question, but the example provided in each of them contradicts example given in the other. The first answer says that the author does not need antMatcher() and the second says to always start with `antMatcher() IIUC.
HttpSecurity.antMatcher() changes the default request matcher for the HttpSecurity instance to an AntPathRequestMatcher from AnyRequestMatcher. ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry.antMatchers() is used for applying authorization rules to a subset of endpoints associated with the current HttpSecurity instance.
Example code:
http
.antMatcher("/api/**")
.httpBasic()
.disable()
.authorizeRequests()
.antMatchers("/api/user/**", "/api/ticket/**", "/index")
.hasRole("USER");
In the example above, basic authorization is disabled for all endpoints matching /api/**. Additionally, endpoints matching /api/user/** or /api/ticket/** will require the request's Authentication to contain ROLE_USER. However, when a user attempts to access /index, they will be met with a basic auth prompt. Upon entering credentials, the user will be granted access to the endpoint regardless of whether or not the request's Authentication contains ROLE_USER. This is because .antMatcher("/api/**") is limiting the scope of the entire HttpSecurity instance to that specific AntMatcher.
The example below would ensure that the HttpSecurity's scope includes the three previous AntMatchers and nothing else:
http
.requestMatchers()
.antMatchers("/api/user/**", "/api/ticket/**", "/index")
.and()
.httpBasic()
.disable()
.authorizeRequests()
.any()
.hasRole("USER");
EDIT
If you use #hasRole(), then your role should not start with "ROLE_" as this is automatically inserted.
antMatcher() allows configuring the HttpSecurity to only be invoked when matching the provided ant pattern.
If more advanced configuration is necessary, consider using requestMatchers() or requestMatcher(RequestMatcher).
Invoking antMatcher() will override previous invocations of antMatcher(), mvcMatcher(), requestMatchers(), regexMatcher(), and requestMatcher()
See the example bellow for using requestMatchers
#Configuration
#EnableWebSecurity
public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers((requestMatchers) ->
requestMatchers
.antMatchers("/api/**")
.antMatchers("/oauth/**")
)
.authorizeRequests((authorizeRequests) ->
authorizeRequests
.antMatchers("/**").hasRole("USER")
)
.httpBasic(withDefaults());
}
}
The configuration below is also the same as the above configuration.
#Configuration
#EnableWebSecurity
public class RequestMatchersSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers((requestMatchers) ->
requestMatchers
.antMatchers("/api/**")
)
.requestMatchers((requestMatchers) ->
requestMatchers
.antMatchers("/oauth/**")
)
.authorizeRequests((authorizeRequests) ->
authorizeRequests
.antMatchers("/**").hasRole("USER")
)
.httpBasic(withDefaults());
}
}

spring oauth error Full authentication is required to access this resource

Our application is using spring security to secure the application,i just added one rest controller which supporting spring oauth security, for oauth token validation, will be called by some other application following are my controller code
#RestController
#EnableResourceServer
public class Controller extends BaseRestController{
#RequestMapping(value="/api/v1/public/insertData", method=RequestMethod.POST)
ResponseEntity<?> insertTPQueueData(TitleProcurementQueue queue,Authentication authentication) {
return null;
}
}
after adding spring oauth security i am getting following error for my other controller using spring security
<oauth>
<error_description>
Full authentication is required to access this resource
</error_description>
<error>unauthorized</error>
</oauth>
Please help
When you put security in your project spring implement some filters, like Cors, basic auth etc..
So you need to tell spring how apply security in your resources.
enter link description here
need to create a class with #EnableWebSecurity
and configure like this:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/h2-console/**").permitAll()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.csrf().disable();
http.headers().frameOptions().sameOrigin();
}

Categories