Sharmi467
Sharmi467

Reputation: 1

why securitycontextholder assigned as anonymous securitycontext for authenticated users?

My Goal is spring cloud gateway should connect to keycloak and get authenticated and route it to client method

Referred Blog [https://piotrminkowski.com/2024/03/01/microservices-with-spring-cloud-gateway-oauth2-and-keycloak/][1]

spring cloud gateway works as expected and User also authenticated by keycloak. But why securitycontextholder assigned as anonymous securitycontext for authenticated users.below is security chain at client end

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated())
                .oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()));
        return http.build();
    }
}

2025-02-01 12:53:38.420 [,] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Set SecurityContextHolder to anonymous SecurityContext 2025-02-01 12:53:38.422 [,] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Using 'text/html', given [text/html, application/xhtml+xml, image/avif, image/webp, image/apng, application/xml;q=0.9, /;q=0.8, application/signed-exchange;v=b3;q=0.7] and supported [text/plain, /, application/json, application/*+json] 2025-02-01 12:53:38.422 [,] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Writing ["WebAuthenticationDetails [RemoteIpAddress=10.0.0.159, SessionId=null] Scopes: [ROLE_ANONYMOUS]"]

How can we avoid this?

Upvotes: 0

Views: 66

Answers (1)

ch4mp
ch4mp

Reputation: 12825

When a user is authenticated with oauth2Login on a Spring Cloud Gateway instance standing in front of REST services configured with oauth2ResourceServer, you have to make sure that the "routes" to this downstream services are configured with the TokenRelay= filter on the Gateway (the trailing = is important).

When routing a request, this TokenRelay filter replaces the session cookie set by oauth2Login with a Bearer authorization header containing the access token in the session for an authenticated user.

As a side note, there is a lot to say about the article you linked. For instance:

  • oauth2Login and oauth2ResourceServer shouldn't be mixed in the same filter chain: the first requires state (session), the second is stateless by nature
  • scopes are not roles. Keycloak has built-in support for users' roles at realm and client levels. Implementing RBAC for users with client scopes just because Spring Security default authentication converter builds authorities from the scope claim is hardly sustainable.
  • fine-grained access control should be tested in unit tests (@WebMvcTest or @WebFluxTest) using mocked authentications, not in integration tests (@SpringBootTest) with test containers which are way too slow. See my Baeldung article for details
  • relying on the default access control rule (isAuthenticated() for all requests) and on the default status for unauthorized requests to a filter chain with oauth2Login is a bad idea on a Gateway for a REST API:
    • all access decisions should be taken by the downstream resource servers (the gateway should permitAll() requests routed with the TokenRelay filter)
    • a REST API should return 401 Unauthorized when an anonymous request is sent to a protected resource, not 302 Redirect to Login suited for server-side rendered applications (Thymeleaf, JSP, etc...)

I believe my OAuth2 BFF tutorial on Baeldung to be based on more experience with OAuth2.

Upvotes: 0

Related Questions