From 3315ea718a9811de922724c6d7bed8000809f60e Mon Sep 17 00:00:00 2001 From: Thomas Darimont Date: Thu, 31 Oct 2024 01:32:59 +0100 Subject: [PATCH] Add ability to enable OID4VCI Verifiable Credentials per realm (#34524) - Added new realm property verifiableCredentialsEnabled - Updated RealmRepresentation - Guarded route to Oid4VCI page - Add boolean switch to Realm settings page to control Verifiable Credentials enablement - We now only show the Verifiable Credentials page in the nave if the "Verifiable Credentials" realm setting is enabled. Fixes #34524 Signed-off-by: Thomas Darimont --- .../idm/RealmRepresentation.java | 10 ++++++++++ js/apps/account-ui/src/routes.tsx | 2 +- .../admin/messages/messages_en.properties | 2 ++ .../admin-ui/src/realm-settings/GeneralTab.tsx | 9 ++++++++- .../src/defs/realmRepresentation.ts | 1 + .../models/cache/infinispan/RealmAdapter.java | 17 +++++++++++++++++ .../cache/infinispan/entities/CachedRealm.java | 6 ++++++ .../org/keycloak/models/jpa/RealmAdapter.java | 10 ++++++++++ .../models/jpa/entities/RealmAttributes.java | 2 ++ .../datastore/DefaultExportImportManager.java | 4 ++++ .../models/utils/ModelToRepresentation.java | 1 + .../models/utils/RealmModelDelegate.java | 10 ++++++++++ .../util/IdentityBrokerStateTestHelpers.java | 9 +++++++++ .../java/org/keycloak/models/RealmModel.java | 4 ++++ .../resources/account/AccountConsole.java | 2 +- 15 files changed, 86 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java index 064544fa9b..ae28d8e41f 100755 --- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java @@ -218,6 +218,8 @@ public class RealmRepresentation { protected Boolean organizationsEnabled; private List organizations; + protected Boolean verifiableCredentialsEnabled; + @Deprecated protected Boolean social; @Deprecated @@ -1440,6 +1442,14 @@ public class RealmRepresentation { this.organizationsEnabled = organizationsEnabled; } + public Boolean isVerifiableCredentialsEnabled() { + return verifiableCredentialsEnabled; + } + + public void setVerifiableCredentialsEnabled(Boolean verifiableCredentialsEnabled) { + this.verifiableCredentialsEnabled = verifiableCredentialsEnabled; + } + @JsonIgnore public Map getAttributesOrEmpty() { return (Map) (attributes == null ? Collections.emptyMap() : attributes); diff --git a/js/apps/account-ui/src/routes.tsx b/js/apps/account-ui/src/routes.tsx index 2b9fcb55c1..c43ea32277 100644 --- a/js/apps/account-ui/src/routes.tsx +++ b/js/apps/account-ui/src/routes.tsx @@ -84,7 +84,7 @@ export const RootRoute: RouteObject = { PersonalInfoRoute, ResourcesRoute, ContentRoute, - Oid4VciRoute, + ...(environment.features.isOid4VciEnabled ? [Oid4VciRoute] : []), ], }; diff --git a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties index dee176cac3..3249e1aa2e 100644 --- a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties +++ b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties @@ -3165,6 +3165,8 @@ logo=Logo avatarImage=Avatar image organizationsEnabled=Organizations organizationsEnabledHelp=If enabled, allows managing organizations. Otherwise, existing organizations are still kept but you will not be able to manage them anymore or authenticate their members. +verifiableCredentialsEnabled=Verifiable Credentials +verifiableCredentialsEnabledHelp=If enabled, allows managing verifiable credentials in this realm. organizations=Organizations organizationDetails=Organization details organizationsList=Organizations diff --git a/js/apps/admin-ui/src/realm-settings/GeneralTab.tsx b/js/apps/admin-ui/src/realm-settings/GeneralTab.tsx index d54487401f..6aaef12574 100644 --- a/js/apps/admin-ui/src/realm-settings/GeneralTab.tsx +++ b/js/apps/admin-ui/src/realm-settings/GeneralTab.tsx @@ -227,6 +227,13 @@ function RealmSettingsGeneralTabForm({ labelIcon={t("organizationsEnabledHelp")} /> )} + {isOpenid4vciEnabled && ( + + )} - {isOpenid4vciEnabled && ( + {isOpenid4vciEnabled && realm.verifiableCredentialsEnabled && ( (rep.getSupportedLocales())); } @@ -771,6 +774,7 @@ public class DefaultExportImportManager implements ExportImportManager { if (rep.isResetPasswordAllowed() != null) realm.setResetPasswordAllowed(rep.isResetPasswordAllowed()); if (rep.isEditUsernameAllowed() != null) realm.setEditUsernameAllowed(rep.isEditUsernameAllowed()); if (rep.isOrganizationsEnabled() != null) realm.setOrganizationsEnabled(rep.isOrganizationsEnabled()); + if (rep.isVerifiableCredentialsEnabled() != null) realm.setVerifiableCredentialsEnabled(rep.isVerifiableCredentialsEnabled()); if (rep.getSslRequired() != null) realm.setSslRequired(SslRequired.valueOf(rep.getSslRequired().toUpperCase())); if (rep.getAccessCodeLifespan() != null) realm.setAccessCodeLifespan(rep.getAccessCodeLifespan()); if (rep.getAccessCodeLifespanUserAction() != null) diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java index 50d765c7d4..cbd047333e 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java @@ -404,6 +404,7 @@ public class ModelToRepresentation { rep.setResetPasswordAllowed(realm.isResetPasswordAllowed()); rep.setEditUsernameAllowed(realm.isEditUsernameAllowed()); rep.setOrganizationsEnabled(realm.isOrganizationsEnabled()); + rep.setVerifiableCredentialsEnabled(realm.isVerifiableCredentialsEnabled()); rep.setDefaultSignatureAlgorithm(realm.getDefaultSignatureAlgorithm()); rep.setRevokeRefreshToken(realm.isRevokeRefreshToken()); rep.setRefreshTokenMaxReuse(realm.getRefreshTokenMaxReuse()); diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RealmModelDelegate.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RealmModelDelegate.java index 19ee9f883c..aa847e949e 100644 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/RealmModelDelegate.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RealmModelDelegate.java @@ -1160,4 +1160,14 @@ public class RealmModelDelegate implements RealmModel { public void setOrganizationsEnabled(boolean organizationsEnabled) { delegate.setOrganizationsEnabled(organizationsEnabled); } + + @Override + public boolean isVerifiableCredentialsEnabled() { + return delegate.isVerifiableCredentialsEnabled(); + } + + @Override + public void setVerifiableCredentialsEnabled(boolean verifiableCredentialsEnabled) { + delegate.setVerifiableCredentialsEnabled(verifiableCredentialsEnabled); + } } diff --git a/server-spi-private/src/test/java/org/keycloak/broker/provider/util/IdentityBrokerStateTestHelpers.java b/server-spi-private/src/test/java/org/keycloak/broker/provider/util/IdentityBrokerStateTestHelpers.java index 5f3403e6fd..20dab14a12 100644 --- a/server-spi-private/src/test/java/org/keycloak/broker/provider/util/IdentityBrokerStateTestHelpers.java +++ b/server-spi-private/src/test/java/org/keycloak/broker/provider/util/IdentityBrokerStateTestHelpers.java @@ -1818,5 +1818,14 @@ public class IdentityBrokerStateTestHelpers { @Override public void setOrganizationsEnabled(boolean organizationsEnabled) { } + + @Override + public boolean isVerifiableCredentialsEnabled() { + return false; + } + + @Override + public void setVerifiableCredentialsEnabled(boolean verifiableCredentialsEnabled) { + } } } diff --git a/server-spi/src/main/java/org/keycloak/models/RealmModel.java b/server-spi/src/main/java/org/keycloak/models/RealmModel.java index d24c5c4494..30fcdc7f95 100755 --- a/server-spi/src/main/java/org/keycloak/models/RealmModel.java +++ b/server-spi/src/main/java/org/keycloak/models/RealmModel.java @@ -110,6 +110,10 @@ public interface RealmModel extends RoleContainerModel { void setOrganizationsEnabled(boolean organizationsEnabled); + boolean isVerifiableCredentialsEnabled(); + + void setVerifiableCredentialsEnabled(boolean verifiableCredentialsEnabled); + void setAttribute(String name, String value); default void setAttribute(String name, Boolean value) { setAttribute(name, value.toString()); diff --git a/services/src/main/java/org/keycloak/services/resources/account/AccountConsole.java b/services/src/main/java/org/keycloak/services/resources/account/AccountConsole.java index e5ba51814e..f6a0293bc0 100644 --- a/services/src/main/java/org/keycloak/services/resources/account/AccountConsole.java +++ b/services/src/main/java/org/keycloak/services/resources/account/AccountConsole.java @@ -185,7 +185,7 @@ public class AccountConsole implements AccountResourceProvider { map.put("isViewGroupsEnabled", isViewGroupsEnabled); map.put("isViewOrganizationsEnabled", realm.isOrganizationsEnabled()); - map.put("isOid4VciEnabled", Profile.isFeatureEnabled(Profile.Feature.OID4VC_VCI)); + map.put("isOid4VciEnabled", realm.isVerifiableCredentialsEnabled()); map.put("updateEmailFeatureEnabled", Profile.isFeatureEnabled(Profile.Feature.UPDATE_EMAIL)); RequiredActionProviderModel updateEmailActionProvider = realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.UPDATE_EMAIL.name());