diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 52a87a02356fc..c937f51950862 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -178,7 +178,7 @@
5.12.0
5.8.0
2.1.0
- 24.0.4
+ 25.0.0
1.15.1
3.44.0
2.28.0
@@ -5959,18 +5959,6 @@
${quarkus-spring-boot-api.version}
-
-
- org.keycloak
- keycloak-adapter-core
- ${keycloak.version}
-
-
- commons-logging
- commons-logging
-
-
-
org.keycloak
keycloak-core
diff --git a/build-parent/pom.xml b/build-parent/pom.xml
index 1dd725b5233a9..48dfabb947163 100644
--- a/build-parent/pom.xml
+++ b/build-parent/pom.xml
@@ -102,7 +102,7 @@
- 24.0.4
+ 25.0.0
19.0.3
quay.io/keycloak/keycloak:${keycloak.version}
quay.io/keycloak/keycloak:${keycloak.wildfly.version}-legacy
diff --git a/docs/src/main/asciidoc/security-openid-connect-dev-services.adoc b/docs/src/main/asciidoc/security-openid-connect-dev-services.adoc
index 32ebe11900fc0..f8d398f50a74d 100644
--- a/docs/src/main/asciidoc/security-openid-connect-dev-services.adoc
+++ b/docs/src/main/asciidoc/security-openid-connect-dev-services.adoc
@@ -258,7 +258,7 @@ For more information, see xref:security-oidc-bearer-token-authentication.adoc#in
[[keycloak-initialization]]
=== Keycloak initialization
-The `quay.io/keycloak/keycloak:24.0.4` image which contains a Keycloak distribution powered by Quarkus is used to start a container by default.
+The `quay.io/keycloak/keycloak:25.0.0` image which contains a Keycloak distribution powered by Quarkus is used to start a container by default.
`quarkus.keycloak.devservices.image-name` can be used to change the Keycloak image name.
For example, set it to `quay.io/keycloak/keycloak:19.0.3-legacy` to use a Keycloak distribution powered by WildFly.
Be aware that a Quarkus-based Keycloak distribution is only available starting from Keycloak `20.0.0`.
diff --git a/extensions/keycloak-admin-resteasy-client/runtime/pom.xml b/extensions/keycloak-admin-resteasy-client/runtime/pom.xml
index 8d372fe884843..00afe7ca465f6 100644
--- a/extensions/keycloak-admin-resteasy-client/runtime/pom.xml
+++ b/extensions/keycloak-admin-resteasy-client/runtime/pom.xml
@@ -30,10 +30,6 @@
io.quarkus
quarkus-resteasy-client-jaxb
-
- org.keycloak
- keycloak-adapter-core
-
org.keycloak
keycloak-core
diff --git a/extensions/oidc-client/deployment/pom.xml b/extensions/oidc-client/deployment/pom.xml
index 7c9b963b973d0..bfed4a40847b6 100644
--- a/extensions/oidc-client/deployment/pom.xml
+++ b/extensions/oidc-client/deployment/pom.xml
@@ -49,11 +49,6 @@
rest-assured
test
-
- org.keycloak
- keycloak-adapter-core
- test
-
org.keycloak
keycloak-core
diff --git a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java
index 5a9ace88d43d5..9f71002fb2e7f 100644
--- a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java
+++ b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/DevServicesConfig.java
@@ -34,7 +34,7 @@ public class DevServicesConfig {
* ends with `-legacy`.
* Override with `quarkus.keycloak.devservices.keycloak-x-image`.
*/
- @ConfigItem(defaultValue = "quay.io/keycloak/keycloak:24.0.4")
+ @ConfigItem(defaultValue = "quay.io/keycloak/keycloak:25.0.0")
public String imageName;
/**
diff --git a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java
index f7f2e1cdff083..4ab77d13b638a 100644
--- a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java
+++ b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/devservices/keycloak/KeycloakDevServicesProcessor.java
@@ -109,7 +109,7 @@ public class KeycloakDevServicesProcessor {
private static final String KEYCLOAK_QUARKUS_HOSTNAME = "KC_HOSTNAME";
private static final String KEYCLOAK_QUARKUS_ADMIN_PROP = "KEYCLOAK_ADMIN";
private static final String KEYCLOAK_QUARKUS_ADMIN_PASSWORD_PROP = "KEYCLOAK_ADMIN_PASSWORD";
- private static final String KEYCLOAK_QUARKUS_START_CMD = "start --http-enabled=true --hostname-strict=false --hostname-strict-https=false "
+ private static final String KEYCLOAK_QUARKUS_START_CMD = "start --http-enabled=true --hostname-strict=false "
+ "--spi-user-profile-declarative-user-profile-config-file=/opt/keycloak/upconfig.json";
private static final String JAVA_OPTS = "JAVA_OPTS";
diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java
index 1797e8f2812ce..70e50c2a359e3 100644
--- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java
+++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java
@@ -431,7 +431,7 @@ private static JsonObject getRolesJson(Map requestData, TenantCo
private Uni verifyCodeFlowAccessTokenUni(Map requestData,
TokenAuthenticationRequest request,
TenantConfigContext resolvedContext, UserInfo userInfo) {
- if (request.getToken() instanceof IdTokenCredential
+ if (isIdToken(request)
&& (resolvedContext.oidcConfig.authentication.verifyAccessToken
|| resolvedContext.oidcConfig.roles.source.orElse(null) == Source.accesstoken)) {
final String codeAccessToken = (String) requestData.get(OidcConstants.ACCESS_TOKEN_VALUE);
@@ -469,7 +469,7 @@ private Uni verifyTokenUni(Map requestD
return introspectTokenUni(resolvedContext, token, false);
} else if (resolvedContext.oidcConfig.jwks.resolveEarly) {
// Verify JWT token with the local JWK keys with a possible remote introspection fallback
- final String nonce = (String) requestData.get(OidcConstants.NONCE);
+ final String nonce = tokenCred instanceof IdTokenCredential ? (String) requestData.get(OidcConstants.NONCE) : null;
try {
LOG.debug("Verifying the JWT token with the local JWK keys");
return Uni.createFrom()
diff --git a/integration-tests/oidc-client-reactive/pom.xml b/integration-tests/oidc-client-reactive/pom.xml
index 35cb2616b04d7..3ea6362e1a7f0 100644
--- a/integration-tests/oidc-client-reactive/pom.xml
+++ b/integration-tests/oidc-client-reactive/pom.xml
@@ -19,10 +19,6 @@
-
- org.keycloak
- keycloak-adapter-core
-
org.keycloak
keycloak-core
diff --git a/integration-tests/oidc-client/pom.xml b/integration-tests/oidc-client/pom.xml
index d121b609b21bd..5cb7970336c4d 100644
--- a/integration-tests/oidc-client/pom.xml
+++ b/integration-tests/oidc-client/pom.xml
@@ -20,10 +20,6 @@
-
- org.keycloak
- keycloak-adapter-core
-
org.keycloak
keycloak-core
diff --git a/integration-tests/oidc-code-flow/pom.xml b/integration-tests/oidc-code-flow/pom.xml
index fb37f2ceb8635..5edca73ef37c8 100644
--- a/integration-tests/oidc-code-flow/pom.xml
+++ b/integration-tests/oidc-code-flow/pom.xml
@@ -51,11 +51,6 @@
quarkus-test-keycloak-server
test
-
- org.keycloak
- keycloak-adapter-core
- test
-
org.keycloak
keycloak-core
diff --git a/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/CustomTenantResolver.java b/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/CustomTenantResolver.java
index 759473eea051a..22a1a4056aff9 100644
--- a/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/CustomTenantResolver.java
+++ b/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/CustomTenantResolver.java
@@ -57,8 +57,7 @@ public String resolve(RoutingContext context) {
}
if (path.contains("tenant-https")) {
- if (context.getCookie("q_session_tenant-https_test_chunk_1") != null
- && context.getCookie("q_session_tenant-https_test_chunk_2") != null) {
+ if (context.getCookie("q_session_tenant-https_test") != null) {
context.put("reauthenticated", "true");
return context.get(OidcUtils.TENANT_ID_ATTRIBUTE);
} else {
@@ -67,8 +66,7 @@ public String resolve(RoutingContext context) {
}
if (path.contains("tenant-nonce")) {
- if (context.getCookie("q_session_tenant-nonce_chunk_1") != null
- && context.getCookie("q_session_tenant-nonce_chunk_2") != null) {
+ if (context.getCookie("q_session_tenant-nonce") != null) {
context.put("reauthenticated", "true");
return context.get(OidcUtils.TENANT_ID_ATTRIBUTE);
} else {
diff --git a/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java b/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java
index e4d0d732f453f..9629c61ce5dab 100644
--- a/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java
+++ b/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java
@@ -13,11 +13,7 @@
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
-import java.util.ArrayList;
import java.util.Base64;
-import java.util.List;
-import java.util.SortedMap;
-import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
@@ -25,7 +21,6 @@
import javax.crypto.spec.SecretKeySpec;
import org.hamcrest.Matchers;
-import org.htmlunit.CookieManager;
import org.htmlunit.FailingHttpStatusCodeException;
import org.htmlunit.SilentCssErrorHandler;
import org.htmlunit.TextPage;
@@ -228,9 +223,8 @@ public void testCodeFlowForceHttpsRedirectUriAndPkce() throws Exception {
page = webClient.getPage(endpointLocationWithoutQueryUri.toURL());
assertEquals("tenant-https:reauthenticated", page.getBody().asNormalizedText());
- List sessionCookies = verifyTenantHttpTestCookies(webClient);
- assertEquals("strict", sessionCookies.get(0).getSameSite());
- assertEquals("strict", sessionCookies.get(1).getSameSite());
+ Cookie sessionCookie = getSessionCookie(webClient, "tenant-https_test");
+ assertEquals("strict", sessionCookie.getSameSite());
// Check both session cookie chunks are removed if the new authentication is enforced
webClient.getOptions().setRedirectEnabled(false);
@@ -238,7 +232,7 @@ public void testCodeFlowForceHttpsRedirectUriAndPkce() throws Exception {
TextPage textPage = webClient.getPage("http://localhost:8081/index.html");
assertEquals(302, textPage.getWebResponse().getStatusCode());
- assertNull(getSessionCookies(webClient, "tenant-https"));
+ assertNull(getSessionCookie(webClient, "tenant-https_test"));
webClient.getCookieManager().clearCookies();
}
@@ -349,17 +343,12 @@ public void testCodeFlowForceHttpsRedirectUriWithQueryAndPkce() throws Exception
URI endpointLocationWithoutQueryUri = URI.create(endpointLocationWithoutQuery);
assertEquals("code=b", endpointLocationWithoutQueryUri.getRawQuery());
- List sessionCookies = verifyTenantHttpTestCookies(webClient);
-
- StringBuilder sessionCookieValue = new StringBuilder();
- for (Cookie c : sessionCookies) {
- sessionCookieValue.append(c.getValue());
- }
+ Cookie sessionCookie = getSessionCookie(webClient, "tenant-https_test");
SecretKey key = new SecretKeySpec(OidcUtils
.getSha256Digest("secret".getBytes(StandardCharsets.UTF_8)),
"AES");
- String decryptedSessionCookieValue = OidcUtils.decryptString(sessionCookieValue.toString(), key);
+ String decryptedSessionCookieValue = OidcUtils.decryptString(sessionCookie.getValue(), key);
String encodedIdToken = decryptedSessionCookieValue.split("\\|")[0];
@@ -372,21 +361,12 @@ public void testCodeFlowForceHttpsRedirectUriWithQueryAndPkce() throws Exception
Integer duration = Integer.valueOf(response.substring(response.length() - 1));
assertTrue(duration > 1 && duration < 5);
- verifyTenantHttpTestCookies(webClient);
+ assertNull(getSessionCookie(webClient, "tenant-https"));
webClient.getCookieManager().clearCookies();
}
}
- private List verifyTenantHttpTestCookies(WebClient webClient) {
- List sessionCookies = getSessionCookies(webClient, "tenant-https_test");
- assertNotNull(sessionCookies);
- assertEquals(2, sessionCookies.size());
- assertEquals("q_session_tenant-https_test_chunk_1", sessionCookies.get(0).getName());
- assertEquals("q_session_tenant-https_test_chunk_2", sessionCookies.get(1).getName());
- return sessionCookies;
- }
-
@Test
public void testCodeFlowNonce() throws Exception {
doTestCodeFlowNonce(false);
@@ -448,11 +428,9 @@ private void doTestCodeFlowNonce(boolean wrongRedirect) throws Exception {
// At this point the session cookie is already available, this 2nd redirect only drops
// OIDC code flow parameters such as `code` and `state`
- List sessionCookies = getSessionCookies(webClient, "tenant-nonce");
- assertNotNull(sessionCookies);
- assertEquals(2, sessionCookies.size());
- assertEquals("q_session_tenant-nonce_chunk_1", sessionCookies.get(0).getName());
- assertEquals("q_session_tenant-nonce_chunk_2", sessionCookies.get(1).getName());
+ Cookie sessionCookie = getSessionCookie(webClient, "tenant-nonce");
+ assertNotNull(sessionCookie);
+ assertEquals("q_session_tenant-nonce", sessionCookie.getName());
String endpointLocationWithoutQuery = webResponse.getResponseHeaderValue("location");
URI endpointLocationWithoutQueryUri = URI.create(endpointLocationWithoutQuery);
@@ -462,7 +440,7 @@ private void doTestCodeFlowNonce(boolean wrongRedirect) throws Exception {
assertEquals("tenant-nonce:reauthenticated", page.getBody().asNormalizedText());
// both cookies should be gone now.
- assertNull(getSessionCookies(webClient, "tenant-nonce"));
+ assertNull(getSessionCookie(webClient, "tenant-nonce"));
webClient.getCookieManager().clearCookies();
}
}
@@ -1595,19 +1573,6 @@ private Cookie getSessionCookie(WebClient webClient, String tenantId) {
return webClient.getCookieManager().getCookie("q_session" + (tenantId == null ? "_Default_test" : "_" + tenantId));
}
- private List getSessionCookies(WebClient webClient, String tenantId) {
- String sessionCookieNameChunk = "q_session" + (tenantId == null ? "_Default_test" : "_" + tenantId) + "_chunk_";
- CookieManager cookieManager = webClient.getCookieManager();
- SortedMap sessionCookies = new TreeMap<>();
- for (Cookie cookie : cookieManager.getCookies()) {
- if (cookie.getName().startsWith(sessionCookieNameChunk)) {
- sessionCookies.put(cookie.getName(), cookie);
- }
- }
-
- return sessionCookies.isEmpty() ? null : new ArrayList(sessionCookies.values());
- }
-
private Cookie getSessionAtCookie(WebClient webClient, String tenantId) {
return webClient.getCookieManager().getCookie("q_session_at" + (tenantId == null ? "_Default_test" : "_" + tenantId));
}
diff --git a/integration-tests/oidc-tenancy/pom.xml b/integration-tests/oidc-tenancy/pom.xml
index de7d04c6100c0..efc494393105d 100644
--- a/integration-tests/oidc-tenancy/pom.xml
+++ b/integration-tests/oidc-tenancy/pom.xml
@@ -30,10 +30,6 @@
io.quarkus
quarkus-resteasy-jackson
-
- org.keycloak
- keycloak-adapter-core
-
org.keycloak
keycloak-core
diff --git a/integration-tests/oidc-tenancy/src/test/java/io/quarkus/it/keycloak/BearerTokenAuthorizationTest.java b/integration-tests/oidc-tenancy/src/test/java/io/quarkus/it/keycloak/BearerTokenAuthorizationTest.java
index fc2c666eb54b2..72d591502e151 100644
--- a/integration-tests/oidc-tenancy/src/test/java/io/quarkus/it/keycloak/BearerTokenAuthorizationTest.java
+++ b/integration-tests/oidc-tenancy/src/test/java/io/quarkus/it/keycloak/BearerTokenAuthorizationTest.java
@@ -11,14 +11,10 @@
import java.io.IOException;
import java.net.URI;
import java.time.Duration;
-import java.util.ArrayList;
import java.util.List;
-import java.util.SortedMap;
-import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
-import org.htmlunit.CookieManager;
import org.htmlunit.FailingHttpStatusCodeException;
import org.htmlunit.SilentCssErrorHandler;
import org.htmlunit.WebClient;
@@ -310,9 +306,8 @@ public void testReAuthenticateWhenSwitchingTenants() throws IOException {
page = loginForm.getInputByName("login").click();
assertEquals("tenant-web-app2:alice", page.getBody().asNormalizedText());
assertNull(getSessionCookie(webClient, "tenant-web-app"));
- List sessionCookieChunks = getSessionCookies(webClient, "tenant-web-app2");
- assertNotNull(sessionCookieChunks);
- assertEquals(2, sessionCookieChunks.size());
+ Cookie sessionCookie = getSessionCookie(webClient, "tenant-web-app2");
+ assertNotNull(sessionCookie);
webClient.getCookieManager().clearCookies();
}
}
@@ -937,17 +932,4 @@ private Cookie getSessionAtCookie(WebClient webClient, String tenantId) {
private Cookie getSessionRtCookie(WebClient webClient, String tenantId) {
return webClient.getCookieManager().getCookie("q_session_rt" + (tenantId == null ? "_Default_test" : "_" + tenantId));
}
-
- private List getSessionCookies(WebClient webClient, String tenantId) {
- String sessionCookieNameChunk = "q_session" + (tenantId == null ? "" : "_" + tenantId) + "_chunk_";
- CookieManager cookieManager = webClient.getCookieManager();
- SortedMap sessionCookies = new TreeMap<>();
- for (Cookie cookie : cookieManager.getCookies()) {
- if (cookie.getName().startsWith(sessionCookieNameChunk)) {
- sessionCookies.put(cookie.getName(), cookie);
- }
- }
-
- return sessionCookies.isEmpty() ? null : new ArrayList(sessionCookies.values());
- }
}
diff --git a/integration-tests/oidc-token-propagation/pom.xml b/integration-tests/oidc-token-propagation/pom.xml
index 7152184c09b7e..96757a10b9381 100644
--- a/integration-tests/oidc-token-propagation/pom.xml
+++ b/integration-tests/oidc-token-propagation/pom.xml
@@ -14,10 +14,6 @@
Quarkus - Integration Tests - RESTEasy Client OpenID Connect Token Propagation
-
- org.keycloak
- keycloak-adapter-core
-
org.jboss.logging
commons-logging-jboss-logging
diff --git a/integration-tests/oidc/pom.xml b/integration-tests/oidc/pom.xml
index d279684696577..8e4c5c8e9dafb 100644
--- a/integration-tests/oidc/pom.xml
+++ b/integration-tests/oidc/pom.xml
@@ -27,11 +27,6 @@
quarkus-websockets
-
- org.keycloak
- keycloak-adapter-core
- test
-
org.keycloak
keycloak-core
diff --git a/integration-tests/oidc/src/test/java/io/quarkus/it/keycloak/KeycloakXTestResourceLifecycleManager.java b/integration-tests/oidc/src/test/java/io/quarkus/it/keycloak/KeycloakXTestResourceLifecycleManager.java
index abe4321c0789d..813c1d8e7cac7 100644
--- a/integration-tests/oidc/src/test/java/io/quarkus/it/keycloak/KeycloakXTestResourceLifecycleManager.java
+++ b/integration-tests/oidc/src/test/java/io/quarkus/it/keycloak/KeycloakXTestResourceLifecycleManager.java
@@ -54,7 +54,7 @@ public Map start() {
.withClasspathResourceMapping("/upconfig.json", "/opt/keycloak/upconfig.json", BindMode.READ_ONLY)
.withCommand("build --https-client-auth=required")
.withCommand(String.format(
- "start --https-client-auth=required --hostname-strict=false --hostname-strict-https=false"
+ "start --https-client-auth=required --hostname-strict=false"
+ " --https-key-store-file=%s --https-trust-store-file=%s --https-trust-store-password=password"
+ " --spi-user-profile-declarative-user-profile-config-file=/opt/keycloak/upconfig.json",
SERVER_KEYSTORE_MOUNTED_PATH, SERVER_TRUSTSTORE_MOUNTED_PATH));
diff --git a/integration-tests/smallrye-jwt-oidc-webapp/pom.xml b/integration-tests/smallrye-jwt-oidc-webapp/pom.xml
index 2d89d6642b982..802c1498e549c 100644
--- a/integration-tests/smallrye-jwt-oidc-webapp/pom.xml
+++ b/integration-tests/smallrye-jwt-oidc-webapp/pom.xml
@@ -20,10 +20,6 @@
-
- org.keycloak
- keycloak-adapter-core
-
io.quarkus
quarkus-reactive-oracle-client
diff --git a/integration-tests/smallrye-jwt-token-propagation/pom.xml b/integration-tests/smallrye-jwt-token-propagation/pom.xml
index 71fbe6c39c452..40ec80ae74834 100644
--- a/integration-tests/smallrye-jwt-token-propagation/pom.xml
+++ b/integration-tests/smallrye-jwt-token-propagation/pom.xml
@@ -19,10 +19,6 @@
-
- org.keycloak
- keycloak-adapter-core
-
org.keycloak
keycloak-core
diff --git a/test-framework/keycloak-server/pom.xml b/test-framework/keycloak-server/pom.xml
index 6e6bceb661fb9..704f2b9e24481 100644
--- a/test-framework/keycloak-server/pom.xml
+++ b/test-framework/keycloak-server/pom.xml
@@ -13,10 +13,6 @@
quarkus-test-keycloak-server
Quarkus - Test Framework - Keycloak Server support
-
- org.keycloak
- keycloak-adapter-core
-
org.keycloak
keycloak-core