1

I am currently working on routing api which uses Spring Cloud Gateway library. I also want to use Keycloak for authentication purposes, but I failed to implement a proper Keycloak configuration for my application. I tried these Keycloak configuration which I writed below on an another Spring Web application and it worked perfectly fine. But when I tried it on routing application which uses Spring Cloud Gateway I got these 4 different errors 1:

enter image description here

  1. Caused by: java.lang.IllegalStateException: Failed to introspect Class [org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration] from ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader@266474c2]
    
  2. Caused by: java.lang.NoClassDefFoundError: jakarta/servlet/Filter
    
  3. Caused by: java.lang.ClassNotFoundException: jakarta.servlet.Filter
    
  4. Execution failed for task ':AuthServiceApplication.main()'.
    > Process 'command 'C:\Program Files\Java\jdk-17\bin\java.exe'' finished with non-zero exit value 1
    
    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights.
    > Get more help at https://help.gradle.org.
    Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
    You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
    For more on this, please refer to https://docs.gradle.org/8.8/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
    BUILD FAILED in 5s
    3 actionable tasks: 1 executed, 2 up-to-date
    

I am currently stuck and have been trying to find a way to implement Keycloak configuration for my routing application. I tried using @EnableWebFluxSecurity rather than @EnableWebSecurity, added Jakarta artifact (compileOnly("jakarta.servlet:jakarta.servlet-api:6.0.0")) and did various other things like repeatedly checking my Java and Gradle version but after 3 days, none of these methods worked. So, is there any method that could give me a way to authenticate my routing application using Keycloak?

All my related codes are given below:

Keycloak Configuration Class:

@Configuration
@EnableWebSecurity(debug = true)
public class KeycloakSecurityConfiguration {

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

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
                .cors(cors -> cors.configurationSource(request -> {
                    CorsConfiguration configuration = new CorsConfiguration();
                    configuration.setAllowedOrigins(List.of("*"));
                    configuration.setAllowedMethods(List.of("*"));
                    configuration.setAllowedHeaders(List.of("*"));
                    return configuration;
                }))
                .csrf(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .oauth2ResourceServer(configurer -> configurer.jwt(Customizer.withDefaults()))
                //.addFilterAfter(createPolicyEnforcerFilter(), BearerTokenAuthenticationFilter.class)
                .sessionManagement(t -> t.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .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(request -> config);
    }

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

build.gradle.kts

plugins {
    java
    id("org.springframework.boot") version "3.2.3"
    id("io.spring.dependency-management") version "1.1.4"
}

group = "tubitak.bilgem.bte.apron.authservice"
version = "0.0.1-SNAPSHOT"

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

repositories {
    mavenCentral()
}

extra["springCloudVersion"] = "2023.0.0"

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.cloud:spring-cloud-starter-gateway")

    implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.keycloak:keycloak-policy-enforcer:24.0.4")
    implementation("org.keycloak:keycloak-core:24.0.4")

    compileOnly("org.projectlombok:lombok:1.18.30")
    annotationProcessor("org.projectlombok:lombok:1.18.30")

    compileOnly("jakarta.servlet:jakarta.servlet-api:6.0.0")
    runtimeOnly("org.postgresql:postgresql")

    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("io.projectreactor:reactor-test")

    testImplementation("org.keycloak:keycloak-admin-client:24.0.4")
    testImplementation("org.springframework.security:spring-security-test")
    testImplementation("org.keycloak:keycloak-test-helper:24.0.4")

    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

dependencyManagement {
    imports {
        mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

Main Class

@SpringBootApplication
public class AuthServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(AuthServiceApplication.class, args);
    }

}

SDK and Java Language enter image description here

Module Language Level enter image description here

1
  • add implementation("org.springframework.boot:spring-boot-starter-web")
    – life888888
    Commented Jun 10 at 5:57

1 Answer 1

0

spring-cloud-starter-gateway makes reactive applications (WebFlux, not WebMVC). You should be writing reactive security configuration (SecurityWebFilterChain) instead of synchronized one (SecurityFilterChain).

Also, are you sure that what reaches your gateway are OAuth2 clients? Because if it is single-page or mobile applications, it should not. I suggest that you have a look at this article I wrote.

Not the answer you're looking for? Browse other questions tagged or ask your own question.