Integrate client secret rotation with client admin api v2 - #51615
Integrate client secret rotation with client admin api v2#51615rmartinc wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Integrates client-secret rotation into Admin API v2 and adds supporting tests and serialization fixes.
Changes:
- Adds rotation and stale-secret cleanup to v2 updates.
- Updates policy configuration builders for Jackson 3.
- Adds Admin API v2 rotation tests.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
ClientProfileBuilder.java |
Updates executor configuration serialization. |
ClientPolicyBuilder.java |
Updates condition configuration serialization. |
ClientResource.java |
Simplifies rotation-state cleanup. |
ClientApiV2ClientSecretRotationTest.java |
Tests v2 secret rotation behavior. |
DefaultClientService.java |
Integrates rotation into v2 client updates. |
Suppressed comments (1)
rest/admin-v2/services/src/main/java/org/keycloak/services/client/DefaultClientService.java:341
- This cleanup runs before
AdminClientUpdatedContext, which is the event that marks ordinary PUT/PATCH updates as rotation-enabled. An update under an active policy therefore deletes any rotated grace-period secret and resets its expiration metadata; trigger the final updated/rotation event before cleanup, matchingClientResource.java:172-176.
if (!Boolean.TRUE.equals(session.removeAttribute(ClientSecretConstants.CLIENT_SECRET_ROTATION_ENABLED))) {
OIDCClientSecretConfigWrapper.fromClientModel(model).removeClientSecretRotationInfo();
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| } | ||
| try { | ||
| executor.setConfiguration(RawJsonValue.of(JsonSerialization.mapper.readValue(JsonSerialization.mapper.writeValueAsBytes(config), JsonNode.class))); | ||
| executor.setConfiguration(JsonSerialization.mapper.readValue(JsonSerialization.mapper.writeValueAsBytes(config), RawJsonValue.class)); |
There was a problem hiding this comment.
I agree this fixes the serialization in Jackson 3 test profile, but the JsonSerialization.mapper is Jackson 2 specific. I imagine something like this would be better:
diff --git a/test-framework/builders/src/main/java/org/keycloak/testframework/realm/ClientPolicyBuilder.java b/test-framework/builders/src/main/java/org/keycloak/testframework/realm/ClientPolicyBuilder.java
index 3aa10c5655..9968094389 100644
--- a/test-framework/builders/src/main/java/org/keycloak/testframework/realm/ClientPolicyBuilder.java
+++ b/test-framework/builders/src/main/java/org/keycloak/testframework/realm/ClientPolicyBuilder.java
@@ -13,7 +13,7 @@ import org.keycloak.services.clientpolicy.condition.ClientAccessTypeCondition;
import org.keycloak.services.clientpolicy.condition.ClientScopesCondition;
import org.keycloak.services.clientpolicy.condition.GrantTypeCondition;
import org.keycloak.services.clientpolicy.condition.IdentityProviderCondition;
-import org.keycloak.util.JsonSerialization;
+import org.keycloak.json.KeycloakJsonMapperFactory;
/**
@@ -94,7 +94,8 @@ public class ClientPolicyBuilder extends Builder<ClientPolicyRepresentation> {
config = new ClientPolicyConditionConfigurationRepresentation();
}
try {
- condition.setConfiguration(JsonSerialization.mapper.readValue(JsonSerialization.mapper.writeValueAsBytes(config), RawJsonValue.class));
+ var mapper = KeycloakJsonMapperFactory.mapper();
+ condition.setConfiguration(mapper.readValue(mapper.writeValueAsBytes(config), RawJsonValue.class));
} catch(IOException e) {
throw new IllegalArgumentException("Invalid configuration", e);
}
diff --git a/test-framework/builders/src/main/java/org/keycloak/testframework/realm/ClientProfileBuilder.java b/test-framework/builders/src/main/java/org/keycloak/testframework/realm/ClientProfileBuilder.java
index 852aaf21ae..924ffa6d35 100644
--- a/test-framework/builders/src/main/java/org/keycloak/testframework/realm/ClientProfileBuilder.java
+++ b/test-framework/builders/src/main/java/org/keycloak/testframework/realm/ClientProfileBuilder.java
@@ -8,7 +8,7 @@ import org.keycloak.json.RawJsonValue;
import org.keycloak.representations.idm.ClientPolicyExecutorConfigurationRepresentation;
import org.keycloak.representations.idm.ClientPolicyExecutorRepresentation;
import org.keycloak.representations.idm.ClientProfileRepresentation;
-import org.keycloak.util.JsonSerialization;
+import org.keycloak.json.KeycloakJsonMapperFactory;
/**
@@ -46,7 +46,8 @@ public class ClientProfileBuilder extends Builder<ClientProfileRepresentation> {
config = new ClientPolicyExecutorConfigurationRepresentation();
}
try {
- executor.setConfiguration(JsonSerialization.mapper.readValue(JsonSerialization.mapper.writeValueAsBytes(config), RawJsonValue.class));
+ var mapper = KeycloakJsonMapperFactory.mapper();
+ executor.setConfiguration(mapper.readValue(mapper.writeValueAsBytes(config), RawJsonValue.class));
} catch (IOException e) {
throw new IllegalArgumentException("Invalid configuration", e);
}Closes keycloak#51535 Closes keycloak#51527 Signed-off-by: rmartinc <rmartinc@redhat.com>
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.adapter.servlet.SAMLServletAdapterTest#salesPostSigEmailTestKeycloak CI - Adapter IT Strict Cookies org.keycloak.testsuite.adapter.servlet.SAMLServletAdapterTest#salesPostEmptyConsumerPostURLKeycloak CI - Adapter IT Strict Cookies org.keycloak.testsuite.adapter.servlet.SAMLServletAdapterTest#testReloginWithInvalidAuthSessionCookieKeycloak CI - Adapter IT Strict Cookies |
michalvavrik
left a comment
There was a problem hiding this comment.
Thanks, I think this works for the default service. However I am not much involved in SCIM integration that is happening right now and is probably going to replace the default service soon, you will need review @shawkins to get proper context
|
Thanks @michalvavrik! The AI just detected the |
Closes #51535
Closes #51527
Adding the client secret rotation bits for the admin API v2. I also needed to change the builders to make the test work with jackson3 (configuration for policies and profiles was not serialized OK). A simple test class added to check the rotation works OK with the admin API v2.