Configure policy-enforcer to avoid intercepting public urls in keycloak and spring boot

We created a client resource server in keycloak and policies, permissions, scopes for resources, which works well, policy enforcer is used but the only problem that intercepts all requests (endpoint) backend including the public url which restricts and prevents access, wWe created a client resource server in keycloak and policies, permissions, scopes for resources, which works well, policy enforcer is used but the only problem that intercepts all requests (endpoint) backend including the public url which restricts and prevents access, we are new to this issue if anyone can help in indicating how to solve the problem thank you in advance.

this is the file policy-enforcer.json:e are new to this issue if anyone can help in indicating how to solve the problem thank you in advance.

this is the file policy-enforcer.json:

{
  "realm": "online",
  "auth-server-url": "http://localhost:8182",
  "resource": "client-b",
  "credentials": {
    "secret": "secret"
  }
}

this is the following code:

@Configuration @EnableWebSecurity public class OAuth2ResourceServerSecurityConfiguration {
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
String jwkSetUri;

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
            .authorizeHttpRequests((authorize) -> authorize
                             .requestMatchers("/public/*").permitAll()
                    .anyRequest().authenticated()
            )
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
            .addFilterAfter(createPolicyEnforcerFilter(), BearerTokenAuthenticationFilter.class);
    return http.build();
}

private ServletPolicyEnforcerFilter createPolicyEnforcerFilter() {
    PolicyEnforcerConfig config;

    try {
        config = JsonSerialization.readValue(getClass().getResourceAsStream("/policy-enforcer.json"), PolicyEnforcerConfig.class);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    return new ServletPolicyEnforcerFilter(new ConfigurationResolver() {
        @Override
        public PolicyEnforcerConfig resolve(HttpRequest request) {
            return config;
        }
    });
}

@Bean
JwtDecoder jwtDecoder() {
    return NimbusJwtDecoder.withJwkSetUri(this.jwkSetUri).build();
}
}

The routes were added manually in the file policy-enforcer.json following the keycloak documentation, it was done so that the keycloak resource server only uses the determined urls excluding the public url but it did not work, it still restricts the public url.

{
  "realm": "online",
  "auth-server-url": "http://localhost:8182",
  "resource": "client-b",
  "credentials": {
    "secret": "secret"
  }
  "enforcement-mode" : "ENFORCING",
  "paths": [
    {
      "path" : "/archive/*",
      "methods" : [
        {
          "method": "GET",
          "scopes" : ["urn:client-b:access"]
        }
      ]
    }
    {
      "path" : "/send/create",
      "methods" : [
        {
          "method": "POST",
          "scopes" : ["urn:client-b:send:create"]
        }
      ]
    }
  ]
}

@torx

You can disable enforcer for paths in PolicyEnforcerConfig
exmaple:

    private ServletPolicyEnforcerFilter createPolicyEnforcerFilter() {
        PolicyEnforcerConfig config;

        try {
            config = JsonSerialization.readValue(getClass().getResourceAsStream("/policy-enforcer.json"), PolicyEnforcerConfig.class);
            addExcludedPaths(config);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return new ServletPolicyEnforcerFilter(new ConfigurationResolver() {
            @Override
            public PolicyEnforcerConfig resolve(HttpRequest request) {
                return config;
            }
        });
    }

        private void addExcludedPaths(PolicyEnforcerConfig config) {
        List<String> excludeUrls = List.of("/api/public/*","/api/some-other-path/*");
        List<PolicyEnforcerConfig.PathConfig> paths = new ArrayList<>();
        for (String url : excludeUrls) {
            PolicyEnforcerConfig.PathConfig excludedPath = new PolicyEnforcerConfig.PathConfig();
            excludedPath.setPath(url);
            excludedPath.setEnforcementMode(PolicyEnforcerConfig.EnforcementMode.DISABLED);
            paths.add(excludedPath);
        }
        config.setPaths(paths);
    }

We have tried this exclude urls it won’t work for us.Still it is checking for the authentication call over the console to get the response for the path.

To address this, I use 2 SecurityFilterChains, one for public URLs, and the other one for protected URLs like this :

  private final String PUBLIC_PATH[] = {
    "/v3/api-docs",
    "/swagger-ui.html",
    "...",
  };

  @Bean
  @Order(1)
  public SecurityFilterChain springPublicSecurityFilterChain(HttpSecurity http) throws Exception {
    http.securityMatcher(PUBLIC_PATH);
    http.authorizeHttpRequests(auth -> auth.requestMatchers(PUBLIC_PATH).permitAll());
    ....
    return http.build();
  }

  @Bean
  @Order(2)
  public SecurityFilterChain springPrivateSecurityFilterChain(HttpSecurity http) throws Exception {
    http.securityMatcher("/api/v1/**");
    http.addFilterAfter(createPolicyEnforcerFilter(), BearerTokenAuthenticationFilter.class);
    http.sessionManagement(t -> t.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
    http.csrf(CsrfConfigurer::disable);
    ....
    return http.build();
  }

This is the way we found to bypass public URLs from policy enforcement