Repository navigation
Follow-up to #54382 and #54463 - Require manage-realm to set vault expressions in identity provider configuration - #55102
Draft
Conversation
…nfiguration Vault keys are shared by all components of a realm. A user with only manage-identity-providers could set an identity provider client secret to the vault expression of a client and make Keycloak send the resolved secret to a token URL controlled by that user. Creating an identity provider, or changing an existing vault expression in its configuration, now requires the manage-realm role. Unchanged vault expressions on existing identity providers are still accepted, so existing configurations keep working. Closes keycloak#54979 Signed-off-by: Jimmy Chakkalakal <jimmy.chakkalakal@ibm.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
A critical authorization gap lets an IdP manager without manage-realm retain a vault-backed client secret while changing tokenUrl, causing login to send the resolved secret to an attacker-controlled endpoint.
1 open issue
What changed in this PR
This follow-up to #54382 and #54463 restricts vault expressions in identity provider configuration to reduce cross-component secret disclosure by delegated administrators.
Changes:
- Requires
manage-realmto introduce or change vault expressions during identity provider creation and updates. - Preserves unchanged stored vault expressions.
- Adds integration tests for delegated-admin restrictions and realm-admin access.
| File | Description |
|---|---|
tests/base/src/test/java/org/keycloak/tests/vault/VaultCrossComponentSecretDisclosureTest.java |
Adds permission and secret-disclosure regression tests with a file-backed vault. |
services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java |
Applies vault-expression authorization during creation. |
services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java |
Defines the shared authorization check and applies it during updates. |
Review effort: Balanced
| } | ||
| } | ||
|
|
||
| requireManageRealmForVaultExpressions(auth, providerRep.getConfig(), identityProviderModel.getConfig()); |
mposolda
marked this pull request as ready for review
November 12, 2026 15:46
jimmychakkalakal
marked this pull request as draft
November 12, 2026 15:53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
A ${vault.} expression resolves to the same secret in every vault-enabled field of a realm, whichever component the secret was provisioned for. A user holding only manage-identity-providers could therefore set an identity provider's clientSecret to the vault expression used by a client they cannot manage, and Keycloak would send the resolved value to the identity provider's token URL.
Changes
Other paths that can reference vault keys already require manage-realm: components (LDAP bind credential, key providers), authenticator configuration, realm settings (SMTP) and partial import.