user1657054
user1657054

Reputation: 21

spring-security triggers oauth flow for all requests, ignores permitAll()

I am using spring-cloud-gateway as an oauth client to implement a BFF application and I am not able to bypass specific url patterns from oauth flows.

Based on my understanding, the filter chain configured below should not trigger oauth for requests /passthru/api/public as it explicitly allows permitAll() for "/passthru/**". However, when I hit this endpoint in the browser, it redirected me to the Auth server login page.

Also seen in logs, the match is found "Checking match of request : '/passthru/api/public'; against '/**'" where as it should have been found for /passthru/**.

I have tried CHAT-GPT and DEEPSEEK among others, and they all seem to suggest what I have already implemented.

@Bean
@Order(-1)
public SecurityFilterChain securityWebFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests(authorize -> authorize
                    .requestMatchers("/passthru/**").permitAll() // Allow public access to certain endpoints
                    .anyRequest().authenticated() // Require authentication for all other endpoints
            )
            .oauth2Login(Customizer.withDefaults() // Custom login page for OAuth2
            )
            .logout(logout -> logout
                    .logoutSuccessUrl("/") // Redirect to home page after logout
            )
            .csrf(csrf -> csrf.disable()); // Disable CSRF for simplicity (not recommended for production)

    return http.build();
}

>  [ca59c5ab-1] HTTP GET "/passthru/api/public"
 Request 'GET /passthru/api/public' doesn't match 'null /oauth2/authorization/{registrationId}'
 Request 'GET /passthru/api/public' doesn't match 'null /oauth2/authorization/{registrationId}'
 Request 'GET /passthru/api/public' doesn't match 'null /login/oauth2/code/{registrationId}'
 Request 'GET /passthru/api/public' doesn't match 'GET /default-ui.css'
 Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/login', method=GET}
 Request 'GET /passthru/api/public' doesn't match 'GET /login'
 No matches found
 Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/logout', method=GET}
 Request 'GET /passthru/api/public' doesn't match 'GET /logout'
 No matches found
 Created new WebSession.
 Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/logout', method=POST}
 Request 'GET /passthru/api/public' doesn't match 'POST /logout'
 No matches found
 Checking authorization on '/passthru/api/public' using org.springframework.security.authorization.AuthenticatedReactiveAuthorizationManager@55ded0ee
 No SecurityContext found in WebSession: 'org.springframework.web.server.session.InMemoryWebSessionStore$InMemoryWebSession@7bde73c1'
 Authorization failed: Access Denied
 No SecurityContext found in WebSession: 'org.springframework.web.server.session.InMemoryWebSessionStore$InMemoryWebSession@7bde73c1'
 Trying to match using AndServerWebExchangeMatcher{matchers=[NegatedServerWebExchangeMatcher{matcher=org.springframework.security.config.web.server.ServerHttpSecurity$OAuth2LoginSpec$$Lambda$948/0x000000700152e7b8@50419914}, NegatedServerWebExchangeMatcher{matcher=AndServerWebExchangeMatcher{matchers=[OrServerWebExchangeMatcher{matchers=[PathMatcherServerWebExchangeMatcher{pattern='/login', method=null}, PathMatcherServerWebExchangeMatcher{pattern='/favicon.ico', method=null}]}, AndServerWebExchangeMatcher{matchers=[NegatedServerWebExchangeMatcher{matcher=org.springframework.security.config.web.server.ServerHttpSecurity$OAuth2LoginSpec$$Lambda$948/0x000000700152e7b8@50419914}, MediaTypeRequestMatcher [matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]}]}}]}
 Trying to match using NegatedServerWebExchangeMatcher{matcher=org.springframework.security.config.web.server.ServerHttpSecurity$OAuth2LoginSpec$$Lambda$948/0x000000700152e7b8@50419914}
 matches = true
 Trying to match using NegatedServerWebExchangeMatcher{matcher=AndServerWebExchangeMatcher{matchers=[OrServerWebExchangeMatcher{matchers=[PathMatcherServerWebExchangeMatcher{pattern='/login', method=null}, PathMatcherServerWebExchangeMatcher{pattern='/favicon.ico', method=null}]}, AndServerWebExchangeMatcher{matchers=[NegatedServerWebExchangeMatcher{matcher=org.springframework.security.config.web.server.ServerHttpSecurity$OAuth2LoginSpec$$Lambda$948/0x000000700152e7b8@50419914}, MediaTypeRequestMatcher [matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]}]}}
 Trying to match using OrServerWebExchangeMatcher{matchers=[PathMatcherServerWebExchangeMatcher{pattern='/login', method=null}, PathMatcherServerWebExchangeMatcher{pattern='/favicon.ico', method=null}]}
 Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/login', method=null}
 Request 'GET /passthru/api/public' doesn't match 'null /login'
 Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/favicon.ico', method=null}
 Request 'GET /passthru/api/public' doesn't match 'null /favicon.ico'
 No matches found
 Did not match
 matches = true
 All requestMatchers returned true
 Match found! Executing org.springframework.security.web.server.authentication.RedirectServerAuthenticationEntryPoint@628e22f1
 Trying to match using OrServerWebExchangeMatcher{matchers=[PathMatcherServerWebExchangeMatcher{pattern='/**', method=GET}]}
 Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/**', method=GET}
 Checking match of request : '/passthru/api/public'; against '/**'
 matched
 Trying to match using NegatedServerWebExchangeMatcher{matcher=OrServerWebExchangeMatcher{matchers=[PathMatcherServerWebExchangeMatcher{pattern='/favicon.*', method=null}]}}
 Trying to match using PathMatcherServerWebExchangeMatcher{pattern='/favicon.*', method=null}
 Request 'GET /passthru/api/public' doesn't match 'null /favicon.*'
 No matches found
 matches = true
 Trying to match using MediaTypeRequestMatcher [matchingMediaTypes=[text/html], useEquals=false, ignoredMediaTypes=[*/*]]
 httpRequestMediaTypes=[text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8]
 Processing text/html
 text/html .isCompatibleWith text/html = true
 All requestMatchers returned true
 Request added to WebSession: '/passthru/api/public'
 Redirecting to '/oauth2/authorization/localauth'
 [ca59c5ab-1] Completed 302 FOUND
 [ca59c5ab-2] HTTP GET "/oauth2/authorization/localauth"
 Checking match of request : '/oauth2/authorization/localauth'; against '/oauth2/authorization/{registrationId}'
 Redirecting to 'http://localhost:9000/oauth2/authorize?response_type=code&client_id=<..removed content...>
 [ca59c5ab-2] Completed 302 FOUND

Upvotes: 0

Views: 24

Answers (1)

user1657054
user1657054

Reputation: 21

On further debugging, I realized that the SecurityFilterChain bean was not recognized, hence the matcher was never invoked.

I was able to make it work with the following changes:

spring-cloud.version=2024.0.0 with spring-boot-starter-webflux

Using @EnableWebFluxSecurity instead of @EnableWebSecurity and setting up the filter chain as

@Bean
    public SecurityWebFilterChain securityFilterChain(ServerHttpSecurity http){...}

Upvotes: 0

Related Questions