Spring Cloud Gateway: is it possible to call OncePerRequestFilter before GlobalFilter? - spring

Is it possible to use OncePerRequestFilter before GlobalFilter in the gateway app?
How?
OncePerRequestFilter is not being called.

Related

How to make WebFilter work in a non-WebFlux/non-reactive Spring Boot application?

I'm trying to solve this: How to rewrite URLs with Spring (Boot) via REST Controllers?
by creating some kind of "filter" which would be applied to every incoming HTTP request.
The matter is covered by some answers like for this question: Spring Boot Adding Http Request Interceptors
but interface HandlerInterceptor deals with javax' HttpServletRequest and HttpServletResponse which are not as practical as the new class introduced by Spring i.e. the ServerWebExchange (see the use of setLocation() in the code below) which appears in an interface whose name sounds promising, org.springframework.web.server.WebFilter:
So I ended with something like:
#Component
public class LegacyRestRedirectWebFilter implements WebFilter {
#Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
URI origin = exchange.getRequest().getURI();
String path = origin.getPath();
if (path.startsWith("/api/")) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
URI location = UriComponentsBuilder.fromUri(origin).replacePath(path.replaceFirst("/api/", "/rest/")).build().toUri();
response.getHeaders().setLocation(location);
}
return chain.filter(exchange);
}
}
...in the same way people are doing something similar like:
Spring WebFlux add WebFIlter to match specific paths
WebFilter in WebFlux application
Alas, my filter is never called!!!
The thing is: I am not in a "WebFlux" context (on the contrary to the questions above) because:
I don't need to, and
I tried and got the following problems:
Reactive Webfilter is not working when we have spring-boot-starter-web dependency in classpath (but no definitive answer); marked duplicate of:
Don't spring-boot-starter-web and spring-boot-starter-webflux work together?
Spring WebFlux with traditional Web Security (I have the "traditional" spring-boot-starter-security dependency in my pom.xml plus a #Configuration class extending WebSecurityConfigurerAdapter - but not willing to migrate it to... what by the way?)
Also I don't understand why would I need to be in a WebFlux context, because org.springframework.web.server.WebFilter neither deals with reactive nor Webflux, right? ..or does it? This is not very clear in the Javadoc.
In fact, I didn't find a way to make WebFilter work in a non-WebFlux context, but I could successfully implement such a filter, which both implements javax.servlet.Filter (non-reactive) AND org.springframework.web.server.WebFilter (reactive).
Here is my answer to the other related question: https://stackoverflow.com/a/63780659/666414

Combining OAuth2 with http basic authentication spring security

I've implemented OAuth2 using spring boot and spring security. Now I've different set of APIs available and I want to use different authentication methods for it. For e.g I want to use OAuth2 for /users/** apis and Http Basic Authentication for /admin/** APIs.
However, OAuth2 shouldn't work for /admin/** and HTTP basic shouldn't work for /users/** APIs.
Any help would be great!
In Spring Security you can have multiple filter chains that handle different requests.
So you can have one that handles requests to the /users/** uri which will have the Basic Authentication filter , and one that handles requests to /admin/** uri which will have the Oauth2 filters. To set this up, you need 2 instances of the WebSecurityConfigurerAdapter
One for Oauth2
#Configuration
#Order(1)
public static class Oauth2ConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.mvcMatcher("/user/**")
......
And another for Basic:
#Configuration
#Order(2)
public static class BasicConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.mvcMatcher("/admin/**")
......
This article explains it in more detail: https://www.baeldung.com/spring-security-multiple-entry-points
Also this code does something similar with Digest auth for /admin and Basic for all other. https://github.com/wlesniak/spring-security-authn-authz-course/tree/master/module_2/mod2_crypto_portfolio_digest

Spring boot actuator auditevents with custom ReactiveAuthenticationManager

I have setup my own ReactiveAuthenticationManager
public class CustomReactiveAuthenticationManager implements ReactiveAuthenticationManager
and then in SecurityWebFilterChain:
.authenticationManager(this.authenticationManager)
However after this setup im not getting anything in the actuator auditevents endpoint:
{"events":[]}
What do I need to change to have audit events even if I use a custom ReactiveAuthenticationManager?
This isn't a problem with your custom AuthenticationManager. It is a limitation of Spring Security. At the time of writing, events are not published when using reactive Spring Security. An enhancement that will remove the limitation is being tracked in this Spring Security issue.

SAML and Oauth2 in a single spring boot application

In an attempt to develop a generic identity service for a project I am working on, I need to support Azure ADFS-based SAML security for UI pages and Oauth2 based security for my REST APIs in a single spring-boot application
I have a spring boot application attempting to provide SAML based protection for some of my UI resources and Oauth2 based protection for my REST APIs. The UI pages and the REST APIs are hosted in the same spring boot based application. I have a SecurityConfiguration class that extends WebSecurityConfigurerAdapter and that contains my SAML configuration. I also have a ResourceServerConfig class that extends ResourceServerConfigurerAdapter where I have tried to configure the Oauth2 authentication for my REST APIs.
Here is what my code looks like
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
/////// Other methods //////
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests().anyRequest().authenticated();
http.httpBasic().authenticationEntryPoint(samlEntryPoint());
http.csrf().disable();
http.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class).addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);
http.authorizeRequests().antMatchers("/oauth/token").permitAll().anyRequest().authenticated();
}
The ResourceServerConfig class looks something like the following
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter
{
#Override
public void configure(HttpSecurity http) throws Exception
{
http
.csrf().disable()
.anonymous().and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/api/**").authenticated();
}
My problem is, with the above configuration in place, I can either get SAML protection on my UI pages OR Oauth2 protection on my APIs but not both. If I remove #EnableResourceServer from the ResourceServerConfig class and try to access one of my UI pages, I am reliably redirected to the microsoft Azure login page which redirects me back to my UI page after successful authentication. But with this, any attempt to access my apis (with valid bearer tokens) results in a redirection to the microsoft Azure login page. If I re-enable #EnableResourceServer my APIs get protected and behave as expected but SAML protection for all UI pages gets completely disabled with spring allowing unhindered access to all UI resources.
I can't figure out how to tell spring boot to use which authentication framework for the two kinds of URL patterns I have. Is such a thing even possible?
Any help with this would be appreciated.
Regards,
Dipak Jha
I think I have found an answer to my own question. This reply here provides a workable solution. A properly configured OAuthRequestedMatcher seems to do the trick. Please let me know if someone thinks this can be done in a better way.
Regards
Dipak Jha

Spring Boot and OAuth2, WebSecurityConfigurerAdapter vs ResourceServerConfigurerAdapter

What is the difference between WebSecurityConfigurerAdapter and ResourceServerConfigurerAdapter and which should have higher precedence?
I don't really see difference if I am both resource owner and the client. I can configureHttpSecurity in both classes.
EDIT:
Which type of matchers should I add in WebSecurityConfigurerAdapter and which in ResourceServerConfigurerAdapter? I found in some examples that WebSecurityConfigurerAdapter matches pages for login, registration etc. and ResourceServerConfigurerAdapter for the real resource. Is that a correct way of doing it?
ResourceServerConfigurerAdapter for adjust the access rules and paths that are protected by OAuth2 security (Some additional oauth2 filters activated).
WebSecurityConfigurerAdapter for the basic Spring Security customization.

Resources