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 <thomas.darimont@googlemail.com>
This commit is contained in:
parent
f229790ba5
commit
3315ea718a
15 changed files with 86 additions and 3 deletions
|
@ -218,6 +218,8 @@ public class RealmRepresentation {
|
||||||
protected Boolean organizationsEnabled;
|
protected Boolean organizationsEnabled;
|
||||||
private List<OrganizationRepresentation> organizations;
|
private List<OrganizationRepresentation> organizations;
|
||||||
|
|
||||||
|
protected Boolean verifiableCredentialsEnabled;
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected Boolean social;
|
protected Boolean social;
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -1440,6 +1442,14 @@ public class RealmRepresentation {
|
||||||
this.organizationsEnabled = organizationsEnabled;
|
this.organizationsEnabled = organizationsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean isVerifiableCredentialsEnabled() {
|
||||||
|
return verifiableCredentialsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVerifiableCredentialsEnabled(Boolean verifiableCredentialsEnabled) {
|
||||||
|
this.verifiableCredentialsEnabled = verifiableCredentialsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public Map<String, String> getAttributesOrEmpty() {
|
public Map<String, String> getAttributesOrEmpty() {
|
||||||
return (Map<String, String>) (attributes == null ? Collections.emptyMap() : attributes);
|
return (Map<String, String>) (attributes == null ? Collections.emptyMap() : attributes);
|
||||||
|
|
|
@ -84,7 +84,7 @@ export const RootRoute: RouteObject = {
|
||||||
PersonalInfoRoute,
|
PersonalInfoRoute,
|
||||||
ResourcesRoute,
|
ResourcesRoute,
|
||||||
ContentRoute,
|
ContentRoute,
|
||||||
Oid4VciRoute,
|
...(environment.features.isOid4VciEnabled ? [Oid4VciRoute] : []),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3165,6 +3165,8 @@ logo=Logo
|
||||||
avatarImage=Avatar image
|
avatarImage=Avatar image
|
||||||
organizationsEnabled=Organizations
|
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.
|
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
|
organizations=Organizations
|
||||||
organizationDetails=Organization details
|
organizationDetails=Organization details
|
||||||
organizationsList=Organizations
|
organizationsList=Organizations
|
||||||
|
|
|
@ -227,6 +227,13 @@ function RealmSettingsGeneralTabForm({
|
||||||
labelIcon={t("organizationsEnabledHelp")}
|
labelIcon={t("organizationsEnabledHelp")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{isOpenid4vciEnabled && (
|
||||||
|
<DefaultSwitchControl
|
||||||
|
name="verifiableCredentialsEnabled"
|
||||||
|
label={t("verifiableCredentialsEnabled")}
|
||||||
|
labelIcon={t("verifiableCredentialsEnabledHelp")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<SelectControl
|
<SelectControl
|
||||||
name="unmanagedAttributePolicy"
|
name="unmanagedAttributePolicy"
|
||||||
label={t("unmanagedAttributes")}
|
label={t("unmanagedAttributes")}
|
||||||
|
@ -266,7 +273,7 @@ function RealmSettingsGeneralTabForm({
|
||||||
title={t("samlIdentityProviderMetadata")}
|
title={t("samlIdentityProviderMetadata")}
|
||||||
/>
|
/>
|
||||||
</StackItem>
|
</StackItem>
|
||||||
{isOpenid4vciEnabled && (
|
{isOpenid4vciEnabled && realm.verifiableCredentialsEnabled && (
|
||||||
<StackItem>
|
<StackItem>
|
||||||
<FormattedLink
|
<FormattedLink
|
||||||
href={`${addTrailingSlash(
|
href={`${addTrailingSlash(
|
||||||
|
|
|
@ -83,6 +83,7 @@ export default interface RealmRepresentation {
|
||||||
offlineSessionMaxLifespan?: number;
|
offlineSessionMaxLifespan?: number;
|
||||||
offlineSessionMaxLifespanEnabled?: boolean;
|
offlineSessionMaxLifespanEnabled?: boolean;
|
||||||
organizationsEnabled?: boolean;
|
organizationsEnabled?: boolean;
|
||||||
|
verifiableCredentialsEnabled?: boolean;
|
||||||
otpPolicyAlgorithm?: string;
|
otpPolicyAlgorithm?: string;
|
||||||
otpPolicyDigits?: number;
|
otpPolicyDigits?: number;
|
||||||
otpPolicyInitialCounter?: number;
|
otpPolicyInitialCounter?: number;
|
||||||
|
|
|
@ -1821,8 +1821,25 @@ public class RealmAdapter implements CachedRealmModel {
|
||||||
updated.setOrganizationsEnabled(organizationsEnabled);
|
updated.setOrganizationsEnabled(organizationsEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVerifiableCredentialsEnabled() {
|
||||||
|
if (isUpdated()) return featureVerifiableCredentialsEnabled(updated.isVerifiableCredentialsEnabled());
|
||||||
|
return featureVerifiableCredentialsEnabled(cached.isVerifiableCredentialsEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVerifiableCredentialsEnabled(boolean verifiableCredentialsEnabled) {
|
||||||
|
getDelegateForUpdate();
|
||||||
|
updated.setVerifiableCredentialsEnabled(verifiableCredentialsEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean featureAwareIsOrganizationsEnabled(boolean isOrganizationsEnabled) {
|
private boolean featureAwareIsOrganizationsEnabled(boolean isOrganizationsEnabled) {
|
||||||
if (!Profile.isFeatureEnabled(Profile.Feature.ORGANIZATION)) return false;
|
if (!Profile.isFeatureEnabled(Profile.Feature.ORGANIZATION)) return false;
|
||||||
return isOrganizationsEnabled;
|
return isOrganizationsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean featureVerifiableCredentialsEnabled(boolean isVerifiableCredentialsEnabled) {
|
||||||
|
if (!Profile.isFeatureEnabled(Profile.Feature.OID4VC_VCI)) return false;
|
||||||
|
return isVerifiableCredentialsEnabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,7 @@ public class CachedRealm extends AbstractExtendableRevisioned {
|
||||||
protected boolean identityFederationEnabled;
|
protected boolean identityFederationEnabled;
|
||||||
protected boolean editUsernameAllowed;
|
protected boolean editUsernameAllowed;
|
||||||
protected boolean organizationsEnabled;
|
protected boolean organizationsEnabled;
|
||||||
|
protected boolean verifiableCredentialsEnabled;
|
||||||
//--- brute force settings
|
//--- brute force settings
|
||||||
protected boolean bruteForceProtected;
|
protected boolean bruteForceProtected;
|
||||||
protected boolean permanentLockout;
|
protected boolean permanentLockout;
|
||||||
|
@ -191,6 +192,7 @@ public class CachedRealm extends AbstractExtendableRevisioned {
|
||||||
resetPasswordAllowed = model.isResetPasswordAllowed();
|
resetPasswordAllowed = model.isResetPasswordAllowed();
|
||||||
editUsernameAllowed = model.isEditUsernameAllowed();
|
editUsernameAllowed = model.isEditUsernameAllowed();
|
||||||
organizationsEnabled = model.isOrganizationsEnabled();
|
organizationsEnabled = model.isOrganizationsEnabled();
|
||||||
|
verifiableCredentialsEnabled = model.isVerifiableCredentialsEnabled();
|
||||||
//--- brute force settings
|
//--- brute force settings
|
||||||
bruteForceProtected = model.isBruteForceProtected();
|
bruteForceProtected = model.isBruteForceProtected();
|
||||||
permanentLockout = model.isPermanentLockout();
|
permanentLockout = model.isPermanentLockout();
|
||||||
|
@ -431,6 +433,10 @@ public class CachedRealm extends AbstractExtendableRevisioned {
|
||||||
return organizationsEnabled;
|
return organizationsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isVerifiableCredentialsEnabled() {
|
||||||
|
return verifiableCredentialsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
public String getDefaultSignatureAlgorithm() {
|
public String getDefaultSignatureAlgorithm() {
|
||||||
return defaultSignatureAlgorithm;
|
return defaultSignatureAlgorithm;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1199,6 +1199,16 @@ public class RealmAdapter implements StorageProviderRealmModel, JpaModel<RealmEn
|
||||||
setAttribute(RealmAttributes.ORGANIZATIONS_ENABLED, organizationsEnabled);
|
setAttribute(RealmAttributes.ORGANIZATIONS_ENABLED, organizationsEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVerifiableCredentialsEnabled() {
|
||||||
|
return getAttribute(RealmAttributes.VERIFIABLE_CREDENTIALS_ENABLED, Boolean.FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVerifiableCredentialsEnabled(boolean verifiableCredentialsEnabled) {
|
||||||
|
setAttribute(RealmAttributes.VERIFIABLE_CREDENTIALS_ENABLED, verifiableCredentialsEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientModel getMasterAdminClient() {
|
public ClientModel getMasterAdminClient() {
|
||||||
String masterAdminClientId = realm.getMasterAdminClient();
|
String masterAdminClientId = realm.getMasterAdminClient();
|
||||||
|
|
|
@ -56,5 +56,7 @@ public interface RealmAttributes {
|
||||||
|
|
||||||
String FIRST_BROKER_LOGIN_FLOW_ID = "firstBrokerLoginFlowId";
|
String FIRST_BROKER_LOGIN_FLOW_ID = "firstBrokerLoginFlowId";
|
||||||
|
|
||||||
|
String VERIFIABLE_CREDENTIALS_ENABLED = "verifiableCredentialsEnabled";
|
||||||
|
|
||||||
String ORGANIZATIONS_ENABLED = "organizationsEnabled";
|
String ORGANIZATIONS_ENABLED = "organizationsEnabled";
|
||||||
}
|
}
|
||||||
|
|
|
@ -459,6 +459,9 @@ public class DefaultExportImportManager implements ExportImportManager {
|
||||||
if (rep.isInternationalizationEnabled() != null) {
|
if (rep.isInternationalizationEnabled() != null) {
|
||||||
newRealm.setInternationalizationEnabled(rep.isInternationalizationEnabled());
|
newRealm.setInternationalizationEnabled(rep.isInternationalizationEnabled());
|
||||||
}
|
}
|
||||||
|
if (rep.isVerifiableCredentialsEnabled() != null) {
|
||||||
|
newRealm.setVerifiableCredentialsEnabled(rep.isVerifiableCredentialsEnabled());
|
||||||
|
}
|
||||||
if (rep.getSupportedLocales() != null) {
|
if (rep.getSupportedLocales() != null) {
|
||||||
newRealm.setSupportedLocales(new HashSet<String>(rep.getSupportedLocales()));
|
newRealm.setSupportedLocales(new HashSet<String>(rep.getSupportedLocales()));
|
||||||
}
|
}
|
||||||
|
@ -771,6 +774,7 @@ public class DefaultExportImportManager implements ExportImportManager {
|
||||||
if (rep.isResetPasswordAllowed() != null) realm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
|
if (rep.isResetPasswordAllowed() != null) realm.setResetPasswordAllowed(rep.isResetPasswordAllowed());
|
||||||
if (rep.isEditUsernameAllowed() != null) realm.setEditUsernameAllowed(rep.isEditUsernameAllowed());
|
if (rep.isEditUsernameAllowed() != null) realm.setEditUsernameAllowed(rep.isEditUsernameAllowed());
|
||||||
if (rep.isOrganizationsEnabled() != null) realm.setOrganizationsEnabled(rep.isOrganizationsEnabled());
|
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.getSslRequired() != null) realm.setSslRequired(SslRequired.valueOf(rep.getSslRequired().toUpperCase()));
|
||||||
if (rep.getAccessCodeLifespan() != null) realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
|
if (rep.getAccessCodeLifespan() != null) realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
|
||||||
if (rep.getAccessCodeLifespanUserAction() != null)
|
if (rep.getAccessCodeLifespanUserAction() != null)
|
||||||
|
|
|
@ -404,6 +404,7 @@ public class ModelToRepresentation {
|
||||||
rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
|
rep.setResetPasswordAllowed(realm.isResetPasswordAllowed());
|
||||||
rep.setEditUsernameAllowed(realm.isEditUsernameAllowed());
|
rep.setEditUsernameAllowed(realm.isEditUsernameAllowed());
|
||||||
rep.setOrganizationsEnabled(realm.isOrganizationsEnabled());
|
rep.setOrganizationsEnabled(realm.isOrganizationsEnabled());
|
||||||
|
rep.setVerifiableCredentialsEnabled(realm.isVerifiableCredentialsEnabled());
|
||||||
rep.setDefaultSignatureAlgorithm(realm.getDefaultSignatureAlgorithm());
|
rep.setDefaultSignatureAlgorithm(realm.getDefaultSignatureAlgorithm());
|
||||||
rep.setRevokeRefreshToken(realm.isRevokeRefreshToken());
|
rep.setRevokeRefreshToken(realm.isRevokeRefreshToken());
|
||||||
rep.setRefreshTokenMaxReuse(realm.getRefreshTokenMaxReuse());
|
rep.setRefreshTokenMaxReuse(realm.getRefreshTokenMaxReuse());
|
||||||
|
|
|
@ -1160,4 +1160,14 @@ public class RealmModelDelegate implements RealmModel {
|
||||||
public void setOrganizationsEnabled(boolean organizationsEnabled) {
|
public void setOrganizationsEnabled(boolean organizationsEnabled) {
|
||||||
delegate.setOrganizationsEnabled(organizationsEnabled);
|
delegate.setOrganizationsEnabled(organizationsEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVerifiableCredentialsEnabled() {
|
||||||
|
return delegate.isVerifiableCredentialsEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVerifiableCredentialsEnabled(boolean verifiableCredentialsEnabled) {
|
||||||
|
delegate.setVerifiableCredentialsEnabled(verifiableCredentialsEnabled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1818,5 +1818,14 @@ public class IdentityBrokerStateTestHelpers {
|
||||||
@Override
|
@Override
|
||||||
public void setOrganizationsEnabled(boolean organizationsEnabled) {
|
public void setOrganizationsEnabled(boolean organizationsEnabled) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVerifiableCredentialsEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVerifiableCredentialsEnabled(boolean verifiableCredentialsEnabled) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,10 @@ public interface RealmModel extends RoleContainerModel {
|
||||||
|
|
||||||
void setOrganizationsEnabled(boolean organizationsEnabled);
|
void setOrganizationsEnabled(boolean organizationsEnabled);
|
||||||
|
|
||||||
|
boolean isVerifiableCredentialsEnabled();
|
||||||
|
|
||||||
|
void setVerifiableCredentialsEnabled(boolean verifiableCredentialsEnabled);
|
||||||
|
|
||||||
void setAttribute(String name, String value);
|
void setAttribute(String name, String value);
|
||||||
default void setAttribute(String name, Boolean value) {
|
default void setAttribute(String name, Boolean value) {
|
||||||
setAttribute(name, value.toString());
|
setAttribute(name, value.toString());
|
||||||
|
|
|
@ -185,7 +185,7 @@ public class AccountConsole implements AccountResourceProvider {
|
||||||
|
|
||||||
map.put("isViewGroupsEnabled", isViewGroupsEnabled);
|
map.put("isViewGroupsEnabled", isViewGroupsEnabled);
|
||||||
map.put("isViewOrganizationsEnabled", realm.isOrganizationsEnabled());
|
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));
|
map.put("updateEmailFeatureEnabled", Profile.isFeatureEnabled(Profile.Feature.UPDATE_EMAIL));
|
||||||
RequiredActionProviderModel updateEmailActionProvider = realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.UPDATE_EMAIL.name());
|
RequiredActionProviderModel updateEmailActionProvider = realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.UPDATE_EMAIL.name());
|
||||||
|
|
Loading…
Reference in a new issue