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:
-
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]
-
Caused by: java.lang.NoClassDefFoundError: jakarta/servlet/Filter
-
Caused by: java.lang.ClassNotFoundException: jakarta.servlet.Filter
-
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);
}
}
implementation("org.springframework.boot:spring-boot-starter-web")