This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 3_0_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/3_0_X by this push:
     new c3a90b7950 Fixing OIDC scope management (#498) (#499)
c3a90b7950 is described below

commit c3a90b7950a11e736edf72e95d0106a21c8fc6ed
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Tue Aug 1 16:20:31 2023 +0200

    Fixing OIDC scope management (#498) (#499)
---
 .../client/console/wizards/AttrWizardBuilder.java  |   2 +-
 .../apache/syncope/common/lib/types/OIDCScope.java |  10 +-
 .../src/test/resources/domains/MasterContent.xml   |   6 +-
 .../src/test/resources/domains/MasterContent.xml   |   6 +-
 .../syncope/client/console/pages/OIDCC4UI.java     |   4 +-
 .../panels/OIDCProvidersDirectoryPanel.java        |  10 +-
 .../console/wizards/OIDCProviderWizardBuilder.java | 124 +++++++--------------
 .../OIDCProviderWizardBuilder$OPContinue.html      |   2 +
 .../syncope/common/lib/to/OIDCC4UIProviderTO.java  |   8 ++
 ...UIEntitlement.java => OIDCC4UIEntitlement.java} |   6 +-
 .../apache/syncope/core/logic/OIDCC4UILogic.java   |  58 +++++-----
 .../syncope/core/logic/OIDCC4UIProviderLogic.java  |  12 +-
 .../syncope/core/logic/init/OIDCC4UILoader.java    |   4 +-
 .../{OIDC4UIContext.java => OIDCC4UIContext.java}  |   2 +-
 .../syncope/core/logic/oidc/OIDCClientCache.java   |  18 +--
 .../persistence/api/entity/OIDCC4UIProvider.java   |   4 +
 .../jpa/entity/JPAOIDCC4UIProvider.java            |  19 ++++
 .../java/data/OIDCC4UIProviderDataBinderImpl.java  |   2 +
 .../apache/syncope/core/logic/SAML2SP4UILogic.java |  14 +--
 .../org/apache/syncope/fit/core/BatchITCase.java   |   7 +-
 .../apache/syncope/fit/core/BpmnProcessITCase.java |   8 +-
 .../syncope/fit/core/MailTemplateITCase.java       |  16 +--
 .../org/apache/syncope/fit/core/RESTITCase.java    |  19 +---
 .../org/apache/syncope/fit/core/ReportITCase.java  |   7 +-
 fit/wa-reference/src/main/resources/log4j2.xml     |   4 +
 .../org/apache/syncope/fit/AbstractITCase.java     |  24 ++--
 .../org/apache/syncope/fit/sra/CASSRAITCase.java   |   2 +
 .../apache/syncope/fit/sra/OAUTH2SRAITCase.java    |  12 +-
 .../org/apache/syncope/fit/sra/OIDCSRAITCase.java  |  70 ++++++++++--
 .../org/apache/syncope/fit/sra/SAML2SRAITCase.java |   2 +
 .../apache/syncope/fit/ui/AbstractUIITCase.java    |   8 +-
 .../ui/{OIDC4UIITCase.java => OIDCC4UIITCase.java} |  27 +++--
 .../apache/syncope/fit/ui/SAML2SP4UIITCase.java    |  12 +-
 .../src/test/resources/sra-oidc.properties         |   1 +
 sra/src/test/resources/debug/sra-debug.properties  |   1 +
 wa/bootstrap/pom.xml                               |   8 ++
 .../wa/bootstrap/WABootstrapConfiguration.java     |  22 +++-
 .../wa/bootstrap/WAPropertySourceLocator.java      |  73 ++++++++++++
 .../apache/syncope/wa/bootstrap/WARestClient.java  |   2 +-
 .../wa/bootstrap}/mapping/AttrReleaseMapper.java   |   2 +-
 .../AttrRepoPropertySourceMapper.java              |   3 +-
 .../AuthModulePropertySourceMapper.java            |   3 +-
 .../mapping/DefaultAttrReleaseMapper.java          |   2 +-
 .../{ => mapping}/PropertySourceMapper.java        |   2 +-
 .../AuthModulePropertySourceMapperTest.java        |   1 +
 wa/starter/pom.xml                                 |   8 --
 .../syncope/wa/starter/config/WAContext.java       |  19 +---
 .../wa/starter/mapping/CASSPClientAppTOMapper.java |   4 +-
 .../wa/starter/mapping/ClientAppMapper.java        |   4 +-
 .../starter/mapping/OIDCRPClientAppTOMapper.java   |  49 ++++----
 .../starter/mapping/RegisteredServiceMapper.java   |  27 ++---
 .../starter/mapping/SAML2SPClientAppTOMapper.java  |   4 +-
 wa/starter/src/main/resources/wa.properties        |   1 +
 53 files changed, 424 insertions(+), 341 deletions(-)

diff --git 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/AttrWizardBuilder.java
 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/AttrWizardBuilder.java
index 8eb63d4ef7..16009194b5 100644
--- 
a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/AttrWizardBuilder.java
+++ 
b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/AttrWizardBuilder.java
@@ -44,7 +44,7 @@ public abstract class AttrWizardBuilder extends 
BaseAjaxWizardBuilder<Attr> {
 
     protected static class AttrStep extends WizardStep {
 
-        private static final long serialVersionUID = 1L;
+        private static final long serialVersionUID = 8145346883748040158L;
 
         AttrStep(final Attr modelObject) {
             AjaxTextFieldPanel schema = new AjaxTextFieldPanel(
diff --git 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCScope.java
 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCScope.java
index a3771db4f9..57e6b58d73 100644
--- 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCScope.java
+++ 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCScope.java
@@ -19,10 +19,10 @@
 package org.apache.syncope.common.lib.types;
 
 public enum OIDCScope {
-    OPENID,
-    PROFILE,
-    EMAIL,
-    ADDRESS,
-    PHONE
+    openid,
+    profile,
+    email,
+    address,
+    phone
 
 }
diff --git 
a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml 
b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
index d80034f400..579e6e6f0a 100644
--- a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
@@ -58,14 +58,14 @@ under the License.
 
   <!-- Attr Release Policies -->
   <AttrReleasePolicy arporder="0" name="DenyAttrReleasePolicy" 
id="219935c7-deb3-40b3-8a9a-683037e523a2"
-                     
jsonConf='{"_class":"org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf","releaseAttrs":[],"allowedAttrs":[],"excludedAttrs":[],"includeOnlyAttrs":[],"principalIdAttr":null,"principalAttrRepoConf":{"mergingStrategy":"MULTIVALUED","ignoreResolvedAttributes":false,"expiration":0,"timeUnit":"HOURS","attrRepos":[]}}'/>
+                     
jsonConf='{"_class":"org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf","releaseAttrs":{},"allowedAttrs":[],"excludedAttrs":[],"includeOnlyAttrs":[],"principalIdAttr":null,"principalAttrRepoConf":{"mergingStrategy":"MULTIVALUED","ignoreResolvedAttributes":false,"expiration":0,"timeUnit":"HOURS","attrRepos":[]}}'/>
   <AttrReleasePolicy arporder="0" name="AllowedAttrReleasePolicy" 
id="319935c7-deb3-40b3-8a9a-683037e523a2"
-                     
jsonConf='{"_class":"org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf","releaseAttrs":[],"allowedAttrs":["cn","givenName","uid"],"excludedAttrs":[],"includeOnlyAttrs":[],"principalIdAttr":null,"principalAttrRepoConf":{"mergingStrategy":"MULTIVALUED","ignoreResolvedAttributes":false,"expiration":0,"timeUnit":"HOURS","attrRepos":[]}}'/>
+                     
jsonConf='{"_class":"org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf","releaseAttrs":{},"allowedAttrs":["cn","givenName","uid"],"excludedAttrs":[],"includeOnlyAttrs":[],"principalIdAttr":null,"principalAttrRepoConf":{"mergingStrategy":"MULTIVALUED","ignoreResolvedAttributes":false,"expiration":0,"timeUnit":"HOURS","attrRepos":[]}}'/>
       
   <!-- Authentication modules -->
   <AuthModule id="DefaultLDAPAuthModule" authModuleState="ACTIVE"
               description="LDAP auth module" 
jsonConf='{"_class":"org.apache.syncope.common.lib.auth.LDAPAuthModuleConf","principalAttributeId":"cn","bindDn":
 "${testds.bindDn}", 
"bindCredential":"${testds.password}","ldapUrl":"ldap://localhost:${testds.port}","searchFilter":"cn={user}","baseDn":"ou=People,${testds.rootDn}","subtreeSearch":true}'
-              
items='[{"intAttrName":"mail","extAttrName":"email","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAttrName":"givenName","extAttrName":"firstname","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAttrName":"sn","extAttrName":"surname"
 [...]
+              
items='[{"intAttrName":"mail","extAttrName":"email","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAttrName":"givenName","extAttrName":"given_name","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAttrName":"sn","extAttrName":"family_
 [...]
   <AuthModule id="DefaultJDBCAuthModule" authModuleState="ACTIVE"
               description="JDBC auth module" 
jsonConf='{"_class":"org.apache.syncope.common.lib.auth.JDBCAuthModuleConf","sql":"SELECT
 * FROM users_table WHERE name=?", "fieldPassword": "password"}'/>
   <AuthModule id="DefaultGoogleMfaAuthModule" authModuleState="ACTIVE"
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml 
b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 243fe85447..5c7ee7b1f3 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -58,14 +58,14 @@ under the License.
 
   <!-- Attr Release Policies -->
   <AttrReleasePolicy arporder="0" name="DenyAttrReleasePolicy" 
id="219935c7-deb3-40b3-8a9a-683037e523a2"
-                     
jsonConf='{"_class":"org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf","releaseAttrs":[],"allowedAttrs":[],"excludedAttrs":[],"includeOnlyAttrs":[],"principalIdAttr":null,"principalAttrRepoConf":{"mergingStrategy":"MULTIVALUED","ignoreResolvedAttributes":false,"expiration":0,"timeUnit":"HOURS","attrRepos":[]}}'/>
+                     
jsonConf='{"_class":"org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf","releaseAttrs":{},"allowedAttrs":[],"excludedAttrs":[],"includeOnlyAttrs":[],"principalIdAttr":null,"principalAttrRepoConf":{"mergingStrategy":"MULTIVALUED","ignoreResolvedAttributes":false,"expiration":0,"timeUnit":"HOURS","attrRepos":[]}}'/>
   <AttrReleasePolicy arporder="0" name="AllowedAttrReleasePolicy" 
id="319935c7-deb3-40b3-8a9a-683037e523a2"
-                     
jsonConf='{"_class":"org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf","releaseAttrs":[],"allowedAttrs":["cn","givenName","uid"],"excludedAttrs":[],"includeOnlyAttrs":[],"principalIdAttr":null,"principalAttrRepoConf":{"mergingStrategy":"MULTIVALUED","ignoreResolvedAttributes":false,"expiration":0,"timeUnit":"HOURS","attrRepos":[]}}'/>
+                     
jsonConf='{"_class":"org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf","releaseAttrs":{},"allowedAttrs":["cn","givenName","uid"],"excludedAttrs":[],"includeOnlyAttrs":[],"principalIdAttr":null,"principalAttrRepoConf":{"mergingStrategy":"MULTIVALUED","ignoreResolvedAttributes":false,"expiration":0,"timeUnit":"HOURS","attrRepos":[]}}'/>
 
   <!-- Authentication modules -->
   <AuthModule id="DefaultLDAPAuthModule" authModuleState="ACTIVE"
               description="LDAP auth module" 
jsonConf='{"_class":"org.apache.syncope.common.lib.auth.LDAPAuthModuleConf","principalAttributeId":"cn","bindDn":
 "${testds.bindDn}", 
"bindCredential":"${testds.password}","ldapUrl":"ldap://localhost:${testds.port}","searchFilter":"cn={user}","baseDn":"ou=People,${testds.rootDn}","subtreeSearch":true}'
-              
items='[{"intAttrName":"mail","extAttrName":"email","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAttrName":"givenName","extAttrName":"firstname","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAttrName":"sn","extAttrName":"surname"
 [...]
+              
items='[{"intAttrName":"mail","extAttrName":"email","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAttrName":"givenName","extAttrName":"given_name","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAttrName":"sn","extAttrName":"family_
 [...]
   <AuthModule id="DefaultJDBCAuthModule" authModuleState="ACTIVE"
               description="JDBC auth module" 
jsonConf='{"_class":"org.apache.syncope.common.lib.auth.JDBCAuthModuleConf","sql":"SELECT
 * FROM users_table WHERE name=?", "fieldPassword": "password"}'/>
   <AuthModule id="DefaultGoogleMfaAuthModule" authModuleState="ACTIVE"
diff --git 
a/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCC4UI.java
 
b/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCC4UI.java
index 2494cd8512..11d51555c4 100644
--- 
a/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCC4UI.java
+++ 
b/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCC4UI.java
@@ -25,7 +25,7 @@ import 
org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
 import org.apache.syncope.client.console.panels.OIDCProvidersDirectoryPanel;
 import org.apache.syncope.client.console.rest.OIDCProviderRestClient;
 import org.apache.syncope.client.ui.commons.annotations.ExtPage;
-import org.apache.syncope.common.lib.types.OIDC4UIEntitlement;
+import org.apache.syncope.common.lib.types.OIDCC4UIEntitlement;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -35,7 +35,7 @@ import 
org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.spring.injection.annot.SpringBean;
 
 @ExtPage(label = "OIDC 1.0 C4UI", icon = "fab fa-openid",
-        listEntitlement = OIDC4UIEntitlement.OP_READ, priority = 300)
+        listEntitlement = OIDCC4UIEntitlement.OP_READ, priority = 300)
 public class OIDCC4UI extends BaseExtPage {
 
     private static final long serialVersionUID = -599601954212606001L;
diff --git 
a/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java
 
b/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java
index 283e5bbc48..59ec0fad51 100644
--- 
a/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java
+++ 
b/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java
@@ -51,7 +51,7 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.OIDCC4UIProviderTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.OIDC4UIEntitlement;
+import org.apache.syncope.common.lib.types.OIDCC4UIEntitlement;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import 
org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
@@ -103,7 +103,7 @@ public class OIDCProvidersDirectoryPanel extends 
DirectoryPanel<
 
         this.addNewItemPanelBuilder(new OIDCProviderWizardBuilder(
                 this, new OIDCC4UIProviderTO(), implementationRestClient, 
restClient, pageRef), true);
-        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, 
OIDC4UIEntitlement.OP_CREATE);
+        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, 
OIDCC4UIEntitlement.OP_CREATE);
 
         modal.size(Modal.Size.Large);
 
@@ -184,7 +184,7 @@ public class OIDCProvidersDirectoryPanel extends 
DirectoryPanel<
                         new AjaxWizard.EditItemActionEvent<>(object, target));
                 modal.header(Model.of(StringUtils.capitalize(("Edit " + 
object.getName()))));
             }
-        }, ActionLink.ActionType.EDIT, OIDC4UIEntitlement.OP_UPDATE);
+        }, ActionLink.ActionType.EDIT, OIDCC4UIEntitlement.OP_UPDATE);
 
         panel.add(new ActionLink<>() {
 
@@ -218,7 +218,7 @@ public class OIDCProvidersDirectoryPanel extends 
DirectoryPanel<
                 target.add(templateModal);
 
             }
-        }, ActionLink.ActionType.TEMPLATE, OIDC4UIEntitlement.OP_UPDATE);
+        }, ActionLink.ActionType.TEMPLATE, OIDCC4UIEntitlement.OP_UPDATE);
 
         panel.add(new ActionLink<>() {
 
@@ -236,7 +236,7 @@ public class OIDCProvidersDirectoryPanel extends 
DirectoryPanel<
                 }
                 ((BasePage) 
pageRef.getPage()).getNotificationPanel().refresh(target);
             }
-        }, ActionLink.ActionType.DELETE, OIDC4UIEntitlement.OP_DELETE, true);
+        }, ActionLink.ActionType.DELETE, OIDCC4UIEntitlement.OP_DELETE, true);
         return panel;
     }
 
diff --git 
a/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java
 
b/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java
index 6757241a1c..57d38a0fb1 100644
--- 
a/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java
+++ 
b/ext/oidcc4ui/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.Future;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
@@ -30,6 +31,7 @@ import 
org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.panels.OIDCProvidersDirectoryPanel;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.OIDCProviderRestClient;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
 import 
org.apache.syncope.client.console.wizards.mapping.ItemTransformersTogglePanel;
 import 
org.apache.syncope.client.console.wizards.mapping.JEXLTransformersTogglePanel;
 import 
org.apache.syncope.client.console.wizards.mapping.OIDCProviderMappingPanel;
@@ -42,6 +44,7 @@ import 
org.apache.syncope.client.ui.commons.wizards.AjaxWizardBuilder;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.OIDCC4UIProviderTO;
 import org.apache.syncope.common.lib.types.OIDCClientImplementationType;
+import org.apache.syncope.common.lib.types.OIDCScope;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.wizard.WizardModel;
@@ -107,11 +110,7 @@ public class OIDCProviderWizardBuilder extends 
AjaxWizardBuilder<OIDCC4UIProvide
     @Override
     protected WizardModel buildModelSteps(final OIDCC4UIProviderTO 
modelObject, final WizardModel wizardModel) {
         wizardModel.add(new OP(modelObject));
-        if (modelObject.getKey() == null) {
-            wizardModel.add(new OPContinue(modelObject));
-        } else {
-            wizardModel.add(new OPContinue(modelObject, true));
-        }
+        wizardModel.add(new OPContinue(modelObject, modelObject.getKey() != 
null));
 
         Mapping mapping = new Mapping();
         mapping.setOutputMarkupId(true);
@@ -145,6 +144,7 @@ public class OIDCProviderWizardBuilder extends 
AjaxWizardBuilder<OIDCC4UIProvide
     @Override
     protected Future<Pair<Serializable, Serializable>> execute(
             final Callable<Pair<Serializable, Serializable>> future) {
+
         return SyncopeConsoleSession.get().execute(future);
     }
 
@@ -200,61 +200,63 @@ public class OIDCProviderWizardBuilder extends 
AjaxWizardBuilder<OIDCC4UIProvide
 
         private static final long serialVersionUID = -7087008312629522790L;
 
-        public OPContinue(final OIDCC4UIProviderTO opTO) {
-            final WebMarkupContainer content = new 
WebMarkupContainer("content");
+        public OPContinue(final OIDCC4UIProviderTO opTO, final boolean 
readOnly) {
             this.setOutputMarkupId(true);
+
+            WebMarkupContainer content = new WebMarkupContainer("content");
             content.setOutputMarkupId(true);
             add(content);
 
             UrlValidator urlValidator = new UrlValidator();
-            final AjaxTextFieldPanel issuer = new AjaxTextFieldPanel(
+
+            AjaxTextFieldPanel issuer = new AjaxTextFieldPanel(
                     "issuer", "issuer", new PropertyModel<>(opTO, "issuer"));
             issuer.addValidator(urlValidator);
             issuer.addRequiredLabel();
-            content.add(issuer);
+            content.add(issuer.setReadOnly(readOnly));
 
-            final AjaxCheckBoxPanel hasDiscovery = new AjaxCheckBoxPanel(
+            AjaxCheckBoxPanel hasDiscovery = new AjaxCheckBoxPanel(
                     "hasDiscovery", "hasDiscovery", new PropertyModel<>(opTO, 
"hasDiscovery"));
             content.add(hasDiscovery);
 
-            final AjaxTextFieldPanel authorizationEndpoint = new 
AjaxTextFieldPanel("authorizationEndpoint",
+            AjaxTextFieldPanel authorizationEndpoint = new 
AjaxTextFieldPanel("authorizationEndpoint",
                     "authorizationEndpoint", new PropertyModel<>(opTO, 
"authorizationEndpoint"));
             authorizationEndpoint.addRequiredLabel();
             authorizationEndpoint.addValidator(urlValidator);
-            content.add(authorizationEndpoint);
+            content.add(authorizationEndpoint.setReadOnly(readOnly));
 
-            final AjaxTextFieldPanel userinfoEndpoint = new 
AjaxTextFieldPanel("userinfoEndpoint",
+            AjaxTextFieldPanel userinfoEndpoint = new 
AjaxTextFieldPanel("userinfoEndpoint",
                     "userinfoEndpoint", new PropertyModel<>(opTO, 
"userinfoEndpoint"));
             userinfoEndpoint.addValidator(urlValidator);
-            content.add(userinfoEndpoint);
+            content.add(userinfoEndpoint.setReadOnly(readOnly));
 
-            final AjaxTextFieldPanel tokenEndpoint = new 
AjaxTextFieldPanel("tokenEndpoint",
+            AjaxTextFieldPanel tokenEndpoint = new 
AjaxTextFieldPanel("tokenEndpoint",
                     "tokenEndpoint", new PropertyModel<>(opTO, 
"tokenEndpoint"));
             tokenEndpoint.addRequiredLabel();
             tokenEndpoint.addValidator(urlValidator);
-            content.add(tokenEndpoint);
+            content.add(tokenEndpoint.setReadOnly(readOnly));
 
-            final AjaxTextFieldPanel jwksUri = new 
AjaxTextFieldPanel("jwksUri",
+            AjaxTextFieldPanel jwksUri = new AjaxTextFieldPanel("jwksUri",
                     "jwksUri", new PropertyModel<>(opTO, "jwksUri"));
             jwksUri.addRequiredLabel();
             jwksUri.addValidator(urlValidator);
-            content.add(jwksUri);
+            content.add(jwksUri.setReadOnly(readOnly));
 
-            final AjaxTextFieldPanel endSessionEndpoint = new 
AjaxTextFieldPanel("endSessionEndpoint",
+            AjaxTextFieldPanel endSessionEndpoint = new 
AjaxTextFieldPanel("endSessionEndpoint",
                     "endSessionEndpoint", new PropertyModel<>(opTO, 
"endSessionEndpoint"));
             endSessionEndpoint.addValidator(urlValidator);
-            content.add(endSessionEndpoint);
+            content.add(endSessionEndpoint.setReadOnly(readOnly));
 
-            final WebMarkupContainer visibleParam = new 
WebMarkupContainer("visibleParams");
-            visibleParam.setOutputMarkupPlaceholderTag(true);
-            visibleParam.add(authorizationEndpoint);
-            visibleParam.add(userinfoEndpoint);
-            visibleParam.add(tokenEndpoint);
-            visibleParam.add(jwksUri);
-            visibleParam.add(endSessionEndpoint);
-            content.add(visibleParam);
+            WebMarkupContainer visibleParams = new 
WebMarkupContainer("visibleParams");
+            visibleParams.setOutputMarkupPlaceholderTag(true);
+            visibleParams.add(authorizationEndpoint);
+            visibleParams.add(userinfoEndpoint);
+            visibleParams.add(tokenEndpoint);
+            visibleParams.add(jwksUri);
+            visibleParams.add(endSessionEndpoint);
+            content.add(visibleParams);
 
-            showHide(hasDiscovery, visibleParam);
+            showHide(hasDiscovery, visibleParams);
 
             hasDiscovery.getField().add(new 
IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
 
@@ -262,70 +264,20 @@ public class OIDCProviderWizardBuilder extends 
AjaxWizardBuilder<OIDCC4UIProvide
 
                 @Override
                 protected void onUpdate(final AjaxRequestTarget target) {
-                    showHide(hasDiscovery, visibleParam);
-                    target.add(visibleParam);
+                    showHide(hasDiscovery, visibleParams);
+                    target.add(visibleParams);
                 }
             });
-        }
-
-        public OPContinue(final OIDCC4UIProviderTO opTO, final boolean 
readOnly) {
-            WebMarkupContainer content = new WebMarkupContainer("content");
-            this.setOutputMarkupId(true);
-            content.setOutputMarkupId(true);
-            add(content);
 
-            final AjaxTextFieldPanel issuer = new AjaxTextFieldPanel(
-                    "issuer", "issuer", new PropertyModel<>(opTO, "issuer"));
-            issuer.setReadOnly(readOnly);
-            content.add(issuer);
-
-            final AjaxCheckBoxPanel hasDiscovery = new AjaxCheckBoxPanel(
-                    "hasDiscovery", "hasDiscovery", new PropertyModel<>(opTO, 
"hasDiscovery"));
-            hasDiscovery.setReadOnly(readOnly);
-            content.add(hasDiscovery);
-
-            final AjaxTextFieldPanel authorizationEndpoint = new 
AjaxTextFieldPanel("authorizationEndpoint",
-                    "authorizationEndpoint", new PropertyModel<>(opTO, 
"authorizationEndpoint"));
-            authorizationEndpoint.setReadOnly(readOnly);
-            content.add(authorizationEndpoint);
-
-            final AjaxTextFieldPanel userinfoEndpoint = new 
AjaxTextFieldPanel("userinfoEndpoint",
-                    "userinfoEndpoint", new PropertyModel<>(opTO, 
"userinfoEndpoint"));
-            userinfoEndpoint.setReadOnly(readOnly);
-            content.add(userinfoEndpoint);
-
-            final AjaxTextFieldPanel tokenEndpoint = new 
AjaxTextFieldPanel("tokenEndpoint",
-                    "tokenEndpoint", new PropertyModel<>(opTO, 
"tokenEndpoint"));
-            tokenEndpoint.setReadOnly(readOnly);
-            content.add(tokenEndpoint);
-
-            final AjaxTextFieldPanel jwksUri = new 
AjaxTextFieldPanel("jwksUri",
-                    "jwksUri", new PropertyModel<>(opTO, "jwksUri"));
-            jwksUri.setReadOnly(readOnly);
-            content.add(jwksUri);
-
-            final AjaxTextFieldPanel endSessionEndpoint = new 
AjaxTextFieldPanel("endSessionEndpoint",
-                    "endSessionEndpoint", new PropertyModel<>(opTO, 
"endSessionEndpoint"));
-            endSessionEndpoint.setReadOnly(readOnly);
-            content.add(endSessionEndpoint);
-
-            final WebMarkupContainer visibleParam = new 
WebMarkupContainer("visibleParams");
-            visibleParam.setOutputMarkupPlaceholderTag(true);
-            visibleParam.add(authorizationEndpoint);
-            visibleParam.add(userinfoEndpoint);
-            visibleParam.add(tokenEndpoint);
-            visibleParam.add(jwksUri);
-            visibleParam.add(endSessionEndpoint);
-            content.add(visibleParam);
+            AjaxTextFieldPanel value = new AjaxTextFieldPanel("panel", 
"scopes", new Model<>());
+            
value.setChoices(Stream.of(OIDCScope.values()).map(OIDCScope::name).collect(Collectors.toList()));
+            content.add(new MultiFieldPanel.Builder<String>(
+                    new PropertyModel<>(opTO, "scopes")).build("scopes", 
"scopes", value));
         }
     }
 
     private static void showHide(final AjaxCheckBoxPanel hasDiscovery, final 
WebMarkupContainer visibleParams) {
-        if (hasDiscovery.getField().getValue().equals("false")) {
-            visibleParams.setVisible(true);
-        } else {
-            visibleParams.setVisible(false);
-        }
+        
visibleParams.setVisible("false".equals(hasDiscovery.getField().getValue()));
     }
 
     /**
diff --git 
a/ext/oidcc4ui/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html
 
b/ext/oidcc4ui/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html
index 0f8de216f4..e36e9d2eee 100644
--- 
a/ext/oidcc4ui/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html
+++ 
b/ext/oidcc4ui/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html
@@ -29,6 +29,8 @@ under the License.
         <span wicket:id="userinfoEndpoint">[userinfoEndpoint]</span>
         <span wicket:id="endSessionEndpoint">[endSessionEndpoint]</span>
       </div>
+
+      <span wicket:id="scopes"></span>
     </div>
   </wicket:panel>
 </html>
diff --git 
a/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCC4UIProviderTO.java
 
b/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCC4UIProviderTO.java
index 158f4a91b7..c082860a7d 100644
--- 
a/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCC4UIProviderTO.java
+++ 
b/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCC4UIProviderTO.java
@@ -48,6 +48,8 @@ public class OIDCC4UIProviderTO extends ItemContainer 
implements EntityTO {
 
     private String endSessionEndpoint;
 
+    private final List<String> scopes = new ArrayList<>();
+
     private boolean hasDiscovery;
 
     private boolean createUnmatching;
@@ -143,6 +145,12 @@ public class OIDCC4UIProviderTO extends ItemContainer 
implements EntityTO {
         this.endSessionEndpoint = endSessionEndpoint;
     }
 
+    @JacksonXmlElementWrapper(localName = "scopes")
+    @JacksonXmlProperty(localName = "scope")
+    public List<String> getScopes() {
+        return scopes;
+    }
+
     public UserTO getUserTemplate() {
         return userTemplate;
     }
diff --git 
a/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDC4UIEntitlement.java
 
b/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCC4UIEntitlement.java
similarity index 91%
rename from 
ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDC4UIEntitlement.java
rename to 
ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCC4UIEntitlement.java
index 3f6a0a98df..8b559ffd07 100644
--- 
a/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDC4UIEntitlement.java
+++ 
b/ext/oidcc4ui/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCC4UIEntitlement.java
@@ -24,7 +24,7 @@ import java.util.Collections;
 import java.util.Set;
 import java.util.TreeSet;
 
-public final class OIDC4UIEntitlement {
+public final class OIDCC4UIEntitlement {
 
     public static final String OP_READ = "OP_READ";
 
@@ -38,7 +38,7 @@ public final class OIDC4UIEntitlement {
 
     static {
         Set<String> values = new TreeSet<>();
-        for (Field field : OIDC4UIEntitlement.class.getDeclaredFields()) {
+        for (Field field : OIDCC4UIEntitlement.class.getDeclaredFields()) {
             if (Modifier.isStatic(field.getModifiers()) && 
String.class.equals(field.getType())) {
                 values.add(field.getName());
             }
@@ -50,7 +50,7 @@ public final class OIDC4UIEntitlement {
         return VALUES;
     }
 
-    private OIDC4UIEntitlement() {
+    private OIDCC4UIEntitlement() {
         // private constructor for static utility class
     }
 }
diff --git 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
index b47bf5f3b5..222d92564e 100644
--- 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
+++ 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UILogic.java
@@ -41,7 +41,7 @@ import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
 import org.apache.syncope.core.logic.oidc.NoOpSessionStore;
-import org.apache.syncope.core.logic.oidc.OIDC4UIContext;
+import org.apache.syncope.core.logic.oidc.OIDCC4UIContext;
 import org.apache.syncope.core.logic.oidc.OIDCClientCache;
 import org.apache.syncope.core.logic.oidc.OIDCUserManager;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
@@ -112,7 +112,7 @@ public class OIDCC4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         OidcClient oidcClient = getOidcClient(oidcClientCacheLogin, op, 
redirectURI);
 
         // 2. create OIDCRequest
-        WithLocationAction action = oidcClient.getRedirectionAction(new 
OIDC4UIContext(), NoOpSessionStore.INSTANCE).
+        WithLocationAction action = oidcClient.getRedirectionAction(new 
OIDCC4UIContext(), NoOpSessionStore.INSTANCE).
                 map(WithLocationAction.class::cast).
                 orElseThrow(() -> {
                     SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Unknown);
@@ -141,9 +141,7 @@ public class OIDCC4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
             OidcCredentials credentials = new OidcCredentials();
             credentials.setCode(new AuthorizationCode(authorizationCode));
 
-            OIDC4UIContext ctx = new OIDC4UIContext();
-
-            oidcClient.getAuthenticator().validate(credentials, ctx, 
NoOpSessionStore.INSTANCE);
+            oidcClient.getAuthenticator().validate(credentials, new 
OIDCC4UIContext(), NoOpSessionStore.INSTANCE);
 
             idToken = credentials.getIdToken().getJWTClaimsSet();
             idTokenHint = credentials.getIdToken().serialize();
@@ -155,8 +153,8 @@ public class OIDCC4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         }
 
         // 3. prepare the result
-        OIDCLoginResponse loginResponse = new OIDCLoginResponse();
-        
loginResponse.setLogoutSupported(StringUtils.isNotBlank(op.getEndSessionEndpoint()));
+        OIDCLoginResponse loginResp = new OIDCLoginResponse();
+        
loginResp.setLogoutSupported(StringUtils.isNotBlank(op.getEndSessionEndpoint()));
 
         // 3a. find matching user (if any) and return the received attributes
         String keyValue = idToken.getSubject();
@@ -164,21 +162,21 @@ public class OIDCC4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
             Attr attrTO = new Attr();
             attrTO.setSchema(item.getExtAttrName());
 
-            String value = idToken.getClaim(item.getExtAttrName()) == null
-                    ? null
-                    : idToken.getClaim(item.getExtAttrName()).toString();
+            String value = 
Optional.ofNullable(idToken.getClaim(item.getExtAttrName())).
+                    map(Object::toString).
+                    orElse(null);
             if (value != null) {
                 attrTO.getValues().add(value);
-                loginResponse.getAttrs().add(attrTO);
+                loginResp.getAttrs().add(attrTO);
                 if (item.isConnObjectKey()) {
                     keyValue = value;
                 }
             }
         }
 
-        List<String> matchingUsers = keyValue == null
-                ? List.of()
-                : userManager.findMatchingUser(keyValue, 
op.getConnObjectKeyItem().get());
+        List<String> matchingUsers = Optional.ofNullable(keyValue).
+                map(k -> userManager.findMatchingUser(k, 
op.getConnObjectKeyItem().get())).
+                orElse(List.of());
         LOG.debug("Found {} matching users for {}", matchingUsers.size(), 
keyValue);
 
         // 3b. not found: create or selfreg if configured
@@ -189,23 +187,23 @@ public class OIDCC4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
 
                 String defaultUsername = keyValue;
                 username = 
AuthContextUtils.callAsAdmin(AuthContextUtils.getDomain(),
-                        () -> userManager.create(op, loginResponse, 
defaultUsername));
+                        () -> userManager.create(op, loginResp, 
defaultUsername));
             } else if (op.isSelfRegUnmatching()) {
                 UserTO userTO = new UserTO();
 
-                userManager.fill(op, loginResponse, userTO);
+                userManager.fill(op, loginResp, userTO);
 
-                loginResponse.getAttrs().clear();
-                loginResponse.getAttrs().addAll(userTO.getPlainAttrs());
+                loginResp.getAttrs().clear();
+                loginResp.getAttrs().addAll(userTO.getPlainAttrs());
                 if (StringUtils.isNotBlank(userTO.getUsername())) {
-                    loginResponse.setUsername(userTO.getUsername());
+                    loginResp.setUsername(userTO.getUsername());
                 } else {
-                    loginResponse.setUsername(keyValue);
+                    loginResp.setUsername(keyValue);
                 }
 
-                loginResponse.setSelfReg(true);
+                loginResp.setSelfReg(true);
 
-                return loginResponse;
+                return loginResp;
             } else {
                 throw new NotFoundException(Optional.ofNullable(keyValue).
                         map(value -> "User matching the provided value " + 
value).
@@ -218,13 +216,13 @@ public class OIDCC4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
                 LOG.debug("About to update {} for {}", matchingUsers.get(0), 
keyValue);
 
                 username = 
AuthContextUtils.callAsAdmin(AuthContextUtils.getDomain(),
-                        () -> userManager.update(matchingUsers.get(0), op, 
loginResponse));
+                        () -> userManager.update(matchingUsers.get(0), op, 
loginResp));
             } else {
                 username = matchingUsers.get(0);
             }
         }
 
-        loginResponse.setUsername(username);
+        loginResp.setUsername(username);
 
         // 4. generate JWT for further access
         Map<String, Object> claims = new HashMap<>();
@@ -234,18 +232,18 @@ public class OIDCC4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         byte[] authorities = null;
         try {
             authorities = ENCRYPTOR.encode(POJOHelper.serialize(
-                    
authDataAccessor.getAuthorities(loginResponse.getUsername(), null)), 
CipherAlgorithm.AES).
+                    authDataAccessor.getAuthorities(loginResp.getUsername(), 
null)), CipherAlgorithm.AES).
                     getBytes();
         } catch (Exception e) {
             LOG.error("Could not fetch authorities", e);
         }
 
         Pair<String, OffsetDateTime> accessTokenInfo =
-                accessTokenDataBinder.create(loginResponse.getUsername(), 
claims, authorities, true);
-        loginResponse.setAccessToken(accessTokenInfo.getLeft());
-        loginResponse.setAccessTokenExpiryTime(accessTokenInfo.getRight());
+                accessTokenDataBinder.create(loginResp.getUsername(), claims, 
authorities, true);
+        loginResp.setAccessToken(accessTokenInfo.getLeft());
+        loginResp.setAccessTokenExpiryTime(accessTokenInfo.getRight());
 
-        return loginResponse;
+        return loginResp;
     }
 
     @PreAuthorize("isAuthenticated() and not(hasRole('" + 
IdRepoEntitlement.ANONYMOUS + "'))")
@@ -272,7 +270,7 @@ public class OIDCC4UILogic extends 
AbstractTransactionalLogic<EntityTO> {
         profile.setIdTokenString((String) 
claimsSet.getClaim(JWT_CLAIM_ID_TOKEN));
 
         WithLocationAction action = oidcClient.getLogoutAction(
-                new OIDC4UIContext(),
+                new OIDCC4UIContext(),
                 NoOpSessionStore.INSTANCE,
                 profile,
                 redirectURI).
diff --git 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UIProviderLogic.java
 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UIProviderLogic.java
index 5a1d9f7de7..30ceda618f 100644
--- 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UIProviderLogic.java
+++ 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/OIDCC4UIProviderLogic.java
@@ -29,7 +29,7 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.Item;
 import org.apache.syncope.common.lib.to.OIDCC4UIProviderTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.OIDC4UIEntitlement;
+import org.apache.syncope.common.lib.types.OIDCC4UIEntitlement;
 import org.apache.syncope.core.logic.oidc.OIDCClientCache;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.OIDCC4UIProviderDAO;
@@ -60,7 +60,7 @@ public class OIDCC4UIProviderLogic extends 
AbstractTransactionalLogic<OIDCC4UIPr
         this.binder = binder;
     }
 
-    @PreAuthorize("hasRole('" + OIDC4UIEntitlement.OP_CREATE + "')")
+    @PreAuthorize("hasRole('" + OIDCC4UIEntitlement.OP_CREATE + "')")
     public String createFromDiscovery(final OIDCC4UIProviderTO opTO) {
         try {
             OIDCClientCache.importMetadata(opTO);
@@ -74,7 +74,7 @@ public class OIDCC4UIProviderLogic extends 
AbstractTransactionalLogic<OIDCC4UIPr
         }
     }
 
-    @PreAuthorize("hasRole('" + OIDC4UIEntitlement.OP_CREATE + "')")
+    @PreAuthorize("hasRole('" + OIDCC4UIEntitlement.OP_CREATE + "')")
     public String create(final OIDCC4UIProviderTO opTO) {
         if (opTO.getConnObjectKeyItem() == null) {
             Item connObjectKeyItem = new Item();
@@ -94,7 +94,7 @@ public class OIDCC4UIProviderLogic extends 
AbstractTransactionalLogic<OIDCC4UIPr
         return 
opDAO.findAll().stream().map(binder::getOIDCProviderTO).collect(Collectors.toList());
     }
 
-    @PreAuthorize("hasRole('" + OIDC4UIEntitlement.OP_READ + "')")
+    @PreAuthorize("hasRole('" + OIDCC4UIEntitlement.OP_READ + "')")
     @Transactional(readOnly = true)
     public OIDCC4UIProviderTO read(final String key) {
         OIDCC4UIProvider op = Optional.ofNullable(opDAO.find(key)).
@@ -103,7 +103,7 @@ public class OIDCC4UIProviderLogic extends 
AbstractTransactionalLogic<OIDCC4UIPr
         return binder.getOIDCProviderTO(op);
     }
 
-    @PreAuthorize("hasRole('" + OIDC4UIEntitlement.OP_UPDATE + "')")
+    @PreAuthorize("hasRole('" + OIDCC4UIEntitlement.OP_UPDATE + "')")
     public void update(final OIDCC4UIProviderTO opTO) {
         OIDCC4UIProvider op = Optional.ofNullable(opDAO.find(opTO.getKey())).
                 orElseThrow(() -> new NotFoundException("OIDC Provider '" + 
opTO.getKey() + '\''));
@@ -121,7 +121,7 @@ public class OIDCC4UIProviderLogic extends 
AbstractTransactionalLogic<OIDCC4UIPr
         oidcClientCacheLogout.removeAll(op.getName());
     }
 
-    @PreAuthorize("hasRole('" + OIDC4UIEntitlement.OP_DELETE + "')")
+    @PreAuthorize("hasRole('" + OIDCC4UIEntitlement.OP_DELETE + "')")
     public void delete(final String key) {
         OIDCC4UIProvider op = Optional.ofNullable(opDAO.find(key)).
                 orElseThrow(() -> new NotFoundException("OIDC Provider '" + 
key + '\''));
diff --git 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCC4UILoader.java
 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCC4UILoader.java
index 93d240a484..d4e4f3e4d8 100644
--- 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCC4UILoader.java
+++ 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCC4UILoader.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.logic.init;
 
 import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
-import org.apache.syncope.common.lib.types.OIDC4UIEntitlement;
+import org.apache.syncope.common.lib.types.OIDCC4UIEntitlement;
 import org.apache.syncope.common.lib.types.OIDCClientImplementationType;
 import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
 import org.springframework.core.Ordered;
@@ -34,7 +34,7 @@ public class OIDCC4UILoader implements SyncopeCoreLoader {
 
     @Override
     public void load() {
-        EntitlementsHolder.getInstance().addAll(OIDC4UIEntitlement.values());
+        EntitlementsHolder.getInstance().addAll(OIDCC4UIEntitlement.values());
         
ImplementationTypesHolder.getInstance().putAll(OIDCClientImplementationType.values());
     }
 }
diff --git 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDC4UIContext.java
 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCC4UIContext.java
similarity index 98%
rename from 
ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDC4UIContext.java
rename to 
ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCC4UIContext.java
index deaed5f6d7..9ee3f8aba8 100644
--- 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDC4UIContext.java
+++ 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCC4UIContext.java
@@ -26,7 +26,7 @@ import javax.ws.rs.HttpMethod;
 import org.pac4j.core.context.Cookie;
 import org.pac4j.core.context.WebContext;
 
-public class OIDC4UIContext implements WebContext {
+public class OIDCC4UIContext implements WebContext {
 
     @Override
     public String getRequestMethod() {
diff --git 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCClientCache.java
 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCClientCache.java
index 98bffe1f80..dbda7839b6 100644
--- 
a/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCClientCache.java
+++ 
b/ext/oidcc4ui/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCClientCache.java
@@ -32,6 +32,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Function;
+import java.util.stream.Collectors;
 import org.apache.syncope.common.lib.to.OIDCC4UIProviderTO;
 import org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider;
 import org.pac4j.core.http.callback.NoParameterCallbackUrlResolver;
@@ -72,6 +73,7 @@ public class OIDCClientCache {
                 
Optional.ofNullable(metadata.getUserInfoEndpointURI()).map(URI::toASCIIString).orElse(null));
         opTO.setEndSessionEndpoint(
                 
Optional.ofNullable(metadata.getEndSessionEndpointURI()).map(URI::toASCIIString).orElse(null));
+        Optional.ofNullable(metadata.getScopes()).ifPresent(s -> 
opTO.getScopes().addAll(s.toStringList()));
     }
 
     protected final List<OidcClient> cache = Collections.synchronizedList(new 
ArrayList<>());
@@ -94,15 +96,15 @@ public class OIDCClientCache {
         metadata.setEndSessionEndpointURI(
                 
Optional.ofNullable(op.getEndSessionEndpoint()).map(URI::create).orElse(null));
 
-        OidcConfiguration config = new OidcConfiguration();
-        config.setClientId(op.getClientID());
-        config.setSecret(op.getClientSecret());
-        config.setProviderMetadata(metadata);
-        config.setScope("openid profile email address phone offline_access");
-        config.setUseNonce(false);
-        config.setLogoutHandler(new NoOpLogoutHandler());
+        OidcConfiguration cfg = new OidcConfiguration();
+        cfg.setClientId(op.getClientID());
+        cfg.setSecret(op.getClientSecret());
+        cfg.setProviderMetadata(metadata);
+        cfg.setScope(op.getScopes().stream().collect(Collectors.joining(" ")));
+        cfg.setUseNonce(false);
+        cfg.setLogoutHandler(new NoOpLogoutHandler());
 
-        OidcClient client = new OidcClient(config);
+        OidcClient client = new OidcClient(cfg);
         client.setName(op.getName());
         client.setCallbackUrlResolver(new NoParameterCallbackUrlResolver());
         client.setCallbackUrl(callbackUrl);
diff --git 
a/ext/oidcc4ui/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCC4UIProvider.java
 
b/ext/oidcc4ui/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCC4UIProvider.java
index 325ec18bee..07df700a16 100644
--- 
a/ext/oidcc4ui/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCC4UIProvider.java
+++ 
b/ext/oidcc4ui/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCC4UIProvider.java
@@ -60,6 +60,10 @@ public interface OIDCC4UIProvider extends Entity {
 
     void setEndSessionEndpoint(String endSessionEndpoint);
 
+    List<String> getScopes();
+
+    void setScopes(List<String> scopes);
+
     boolean getHasDiscovery();
 
     void setHasDiscovery(boolean hasDiscovery);
diff --git 
a/ext/oidcc4ui/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCC4UIProvider.java
 
b/ext/oidcc4ui/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCC4UIProvider.java
index 152c277b6e..4041daf646 100644
--- 
a/ext/oidcc4ui/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCC4UIProvider.java
+++ 
b/ext/oidcc4ui/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCC4UIProvider.java
@@ -22,6 +22,8 @@ import com.fasterxml.jackson.core.type.TypeReference;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import javax.persistence.Cacheable;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -47,6 +49,7 @@ import 
org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider;
 import org.apache.syncope.core.persistence.api.entity.OIDCC4UIUserTemplate;
 import 
org.apache.syncope.core.persistence.jpa.validation.entity.OIDCC4UIProviderCheck;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import org.springframework.util.CollectionUtils;
 
 @Entity
 @Table(name = JPAOIDCC4UIProvider.TABLE)
@@ -85,6 +88,8 @@ public class JPAOIDCC4UIProvider extends 
AbstractGeneratedKeyEntity implements O
     @Column(nullable = true)
     private String endSessionEndpoint;
 
+    private String scopes;
+
     @Column(nullable = false)
     private boolean hasDiscovery;
 
@@ -204,6 +209,20 @@ public class JPAOIDCC4UIProvider extends 
AbstractGeneratedKeyEntity implements O
         this.endSessionEndpoint = endSessionEndpoint;
     }
 
+    @Override
+    public List<String> getScopes() {
+        return Optional.ofNullable(scopes).
+                map(s -> Stream.of(s.split(" ")).collect(Collectors.toList())).
+                orElse(List.of());
+    }
+
+    @Override
+    public void setScopes(final List<String> scopes) {
+        this.scopes = CollectionUtils.isEmpty(scopes)
+                ? ""
+                : scopes.stream().collect(Collectors.joining(" "));
+    }
+
     @Override
     public boolean getHasDiscovery() {
         return hasDiscovery;
diff --git 
a/ext/oidcc4ui/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCC4UIProviderDataBinderImpl.java
 
b/ext/oidcc4ui/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCC4UIProviderDataBinderImpl.java
index 38e9494c48..9c7d814ec6 100644
--- 
a/ext/oidcc4ui/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCC4UIProviderDataBinderImpl.java
+++ 
b/ext/oidcc4ui/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCC4UIProviderDataBinderImpl.java
@@ -173,6 +173,7 @@ public class OIDCC4UIProviderDataBinderImpl implements 
OIDCC4UIProviderDataBinde
         op.setTokenEndpoint(opTO.getTokenEndpoint());
         op.setUserinfoEndpoint(opTO.getUserinfoEndpoint());
         op.setEndSessionEndpoint(opTO.getEndSessionEndpoint());
+        op.setScopes(opTO.getScopes());
         op.setHasDiscovery(opTO.getHasDiscovery());
         op.setCreateUnmatching(opTO.isCreateUnmatching());
         op.setSelfRegUnmatching(opTO.isSelfRegUnmatching());
@@ -243,6 +244,7 @@ public class OIDCC4UIProviderDataBinderImpl implements 
OIDCC4UIProviderDataBinde
         opTO.setTokenEndpoint(op.getTokenEndpoint());
         opTO.setUserinfoEndpoint(op.getUserinfoEndpoint());
         opTO.setEndSessionEndpoint(op.getEndSessionEndpoint());
+        opTO.getScopes().addAll(op.getScopes());
         opTO.setHasDiscovery(op.getHasDiscovery());
         opTO.setCreateUnmatching(op.isCreateUnmatching());
         opTO.setSelfRegUnmatching(op.isSelfRegUnmatching());
diff --git 
a/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
 
b/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
index f2298075c4..985ec78ae5 100644
--- 
a/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
+++ 
b/ext/saml2sp4ui/logic/src/main/java/org/apache/syncope/core/logic/SAML2SP4UILogic.java
@@ -319,10 +319,8 @@ public class SAML2SP4UILogic extends 
AbstractSAML2SP4UILogic {
     @PreAuthorize("hasRole('" + IdRepoEntitlement.ANONYMOUS + "')")
     public SAML2LoginResponse validateLoginResponse(final SAML2Response 
saml2Response) {
         // 0. look for IdP
-        SAML2SP4UIIdP idp = 
idpDAO.findByEntityID(saml2Response.getIdpEntityID());
-        if (idp == null) {
-            throw new NotFoundException("SAML 2.0 IdP '" + 
saml2Response.getIdpEntityID() + '\'');
-        }
+        SAML2SP4UIIdP idp = 
Optional.ofNullable(idpDAO.findByEntityID(saml2Response.getIdpEntityID())).
+                orElseThrow(() -> new NotFoundException("SAML 2.0 IdP '" + 
saml2Response.getIdpEntityID() + '\''));
 
         // 1. look for configured client
         SAML2Client saml2Client = getSAML2Client(
@@ -373,7 +371,7 @@ public class SAML2SP4UILogic extends 
AbstractSAML2SP4UILogic {
 
         for (SAML2Credentials.SAMLAttribute attr : 
credentials.getAttributes()) {
             if (!attr.getAttributeValues().isEmpty()) {
-                String attrName = attr.getFriendlyName() == null ? 
attr.getName() : attr.getFriendlyName();
+                String attrName = 
Optional.ofNullable(attr.getFriendlyName()).orElse(attr.getName());
                 if (connObjectKeyItem != null && 
attrName.equals(connObjectKeyItem.getExtAttrName())) {
                     keyValue = attr.getAttributeValues().get(0);
                 }
@@ -382,9 +380,9 @@ public class SAML2SP4UILogic extends 
AbstractSAML2SP4UILogic {
             }
         }
 
-        List<String> matchingUsers = keyValue == null
-                ? List.of()
-                : userManager.findMatchingUser(keyValue, idp.getKey());
+        List<String> matchingUsers = Optional.ofNullable(keyValue).
+                map(k -> userManager.findMatchingUser(k, idp.getKey())).
+                orElse(List.of());
         LOG.debug("Found {} matching users for {}", matchingUsers.size(), 
keyValue);
 
         String username;
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BatchITCase.java 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BatchITCase.java
index ea7b169748..13b83a1809 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BatchITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BatchITCase.java
@@ -28,9 +28,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.URI;
-import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -41,7 +39,6 @@ import javax.ws.rs.HttpMethod;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
-import org.apache.commons.io.IOUtils;
 import org.apache.cxf.jaxrs.client.Client;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.lib.batch.BatchRequest;
@@ -201,7 +198,7 @@ public class BatchITCase extends AbstractITCase {
         assertTrue(response.getMediaType().toString().
                 
startsWith(RESTHeaders.multipartMixedWith(boundary.substring(2))));
 
-        String body = IOUtils.toString((InputStream) response.getEntity(), 
StandardCharsets.UTF_8);
+        String body = response.readEntity(String.class);
         LOG.debug("Batch response body:\n{}", body);
 
         check(BatchPayloadParser.parse(
@@ -245,7 +242,7 @@ public class BatchITCase extends AbstractITCase {
         assertTrue(response.getMediaType().toString().
                 
startsWith(RESTHeaders.multipartMixedWith(boundary.substring(2))));
 
-        String body = IOUtils.toString((InputStream) response.getEntity(), 
StandardCharsets.UTF_8);
+        String body = response.readEntity(String.class);
         LOG.debug("Batch response body:\n{}", body);
 
         check(BatchPayloadParser.parse(
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java
index 725d8adaf6..e79b27af51 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java
@@ -25,10 +25,7 @@ import static org.junit.jupiter.api.Assumptions.assumeFalse;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
 import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
 import javax.ws.rs.core.Response;
-import org.apache.commons.io.IOUtils;
 import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
 import org.apache.syncope.common.lib.to.BpmnProcess;
 import org.apache.syncope.fit.AbstractITCase;
@@ -62,8 +59,7 @@ public class BpmnProcessITCase extends AbstractITCase {
         Response response = BPMN_PROCESS_SERVICE.get(USER_WORKFLOW_KEY);
         assertTrue(response.getMediaType().toString().
                 
startsWith(CLIENT_FACTORY.getContentType().getMediaType().toString()));
-        assertTrue(response.getEntity() instanceof InputStream);
-        String definition = IOUtils.toString((InputStream) 
response.getEntity(), StandardCharsets.UTF_8);
+        String definition = response.readEntity(String.class);
         assertNotNull(definition);
         assertFalse(definition.isEmpty());
     }
@@ -71,7 +67,7 @@ public class BpmnProcessITCase extends AbstractITCase {
     @Test
     public void updateUserWorkflowProcess() throws IOException {
         Response response = BPMN_PROCESS_SERVICE.get(USER_WORKFLOW_KEY);
-        String definition = IOUtils.toString((InputStream) 
response.getEntity(), StandardCharsets.UTF_8);
+        String definition = response.readEntity(String.class);
 
         BPMN_PROCESS_SERVICE.set(USER_WORKFLOW_KEY, definition);
     }
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MailTemplateITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MailTemplateITCase.java
index 3257e342d6..edebe001cd 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MailTemplateITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MailTemplateITCase.java
@@ -25,7 +25,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 import javax.ws.rs.core.MediaType;
@@ -89,10 +88,7 @@ public class MailTemplateITCase extends AbstractITCase {
         response = MAIL_TEMPLATE_SERVICE.getFormat(key, 
MailTemplateFormat.TEXT);
         assertEquals(200, response.getStatus());
         
assertTrue(response.getMediaType().toString().startsWith(MediaType.TEXT_PLAIN));
-        assertTrue(response.getEntity() instanceof InputStream);
-        assertEquals(
-                textTemplate,
-                IOUtils.toString((InputStream) response.getEntity(), 
StandardCharsets.UTF_8));
+        assertEquals(textTemplate, response.readEntity(String.class));
 
         // 3. set HTML
         String htmlTemplate = "<html><body>Hi there, I am 
${username}.</body></html>";
@@ -102,10 +98,7 @@ public class MailTemplateITCase extends AbstractITCase {
         response = MAIL_TEMPLATE_SERVICE.getFormat(key, 
MailTemplateFormat.HTML);
         assertEquals(200, response.getStatus());
         
assertTrue(response.getMediaType().toString().startsWith(MediaType.TEXT_HTML));
-        assertTrue(response.getEntity() instanceof InputStream);
-        assertEquals(
-                htmlTemplate,
-                IOUtils.toString((InputStream) response.getEntity(), 
StandardCharsets.UTF_8));
+        assertEquals(htmlTemplate, response.readEntity(String.class));
 
         // 4. remove HTML
         MAIL_TEMPLATE_SERVICE.removeFormat(key, MailTemplateFormat.HTML);
@@ -120,10 +113,7 @@ public class MailTemplateITCase extends AbstractITCase {
         response = MAIL_TEMPLATE_SERVICE.getFormat(key, 
MailTemplateFormat.TEXT);
         assertEquals(200, response.getStatus());
         
assertTrue(response.getMediaType().toString().startsWith(MediaType.TEXT_PLAIN));
-        assertTrue(response.getEntity() instanceof InputStream);
-        assertEquals(
-                textTemplate,
-                IOUtils.toString((InputStream) response.getEntity(), 
StandardCharsets.UTF_8));
+        assertEquals(textTemplate, response.readEntity(String.class));
 
         // 5. remove mail template
         MAIL_TEMPLATE_SERVICE.delete(key);
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RESTITCase.java 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RESTITCase.java
index e3378b530d..6a8c168b05 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RESTITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RESTITCase.java
@@ -25,8 +25,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
 import java.security.AccessControlException;
 import java.util.List;
 import javax.ws.rs.ForbiddenException;
@@ -36,7 +34,6 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.jaxrs.client.WebClient;
@@ -108,9 +105,7 @@ public class RESTITCase extends AbstractITCase {
         Response response = noContentService.create(groupCR);
         assertEquals(Response.Status.CREATED.getStatusCode(), 
response.getStatus());
         assertEquals(Preference.RETURN_NO_CONTENT.toString(), 
response.getHeaderString(RESTHeaders.PREFERENCE_APPLIED));
-        assertEquals(
-                StringUtils.EMPTY,
-                IOUtils.toString((InputStream) response.getEntity(), 
StandardCharsets.UTF_8));
+        assertEquals(StringUtils.EMPTY, response.readEntity(String.class));
 
         GroupTO group = getObject(response.getLocation(), GroupService.class, 
GroupTO.class);
         assertNotNull(group);
@@ -122,16 +117,12 @@ public class RESTITCase extends AbstractITCase {
         response = noContentService.update(groupUR);
         assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
         assertEquals(Preference.RETURN_NO_CONTENT.toString(), 
response.getHeaderString(RESTHeaders.PREFERENCE_APPLIED));
-        assertEquals(
-                StringUtils.EMPTY,
-                IOUtils.toString((InputStream) response.getEntity(), 
StandardCharsets.UTF_8));
+        assertEquals(StringUtils.EMPTY, response.readEntity(String.class));
 
         response = noContentService.delete(group.getKey());
         assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
         assertEquals(Preference.RETURN_NO_CONTENT.toString(), 
response.getHeaderString(RESTHeaders.PREFERENCE_APPLIED));
-        assertEquals(
-                StringUtils.EMPTY,
-                IOUtils.toString((InputStream) response.getEntity(), 
StandardCharsets.UTF_8));
+        assertEquals(StringUtils.EMPTY, response.readEntity(String.class));
     }
 
     @Test
@@ -203,9 +194,7 @@ public class RESTITCase extends AbstractITCase {
         String contentDisposition = 
response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION);
         assertNotNull(contentDisposition);
 
-        Object entity = response.getEntity();
-        assertTrue(entity instanceof InputStream);
-        String configExport = IOUtils.toString((InputStream) entity, 
StandardCharsets.UTF_8.name());
+        String configExport = response.readEntity(String.class);
         assertFalse(configExport.isEmpty());
         assertTrue(configExport.length() > 1000);
     }
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
index 4a726321a5..110cadc546 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
@@ -26,8 +26,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
 import java.time.OffsetDateTime;
 import java.util.List;
 import java.util.Set;
@@ -35,7 +33,6 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
-import org.apache.commons.io.IOUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ExecTO;
 import org.apache.syncope.common.lib.to.ReportTO;
@@ -158,9 +155,7 @@ public class ReportITCase extends AbstractITCase {
         
assertNotNull(response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION));
         
assertTrue(response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION).endsWith(".pdf"));
 
-        Object entity = response.getEntity();
-        assertTrue(entity instanceof InputStream);
-        assertFalse(IOUtils.toString((InputStream) entity, 
StandardCharsets.UTF_8.name()).isEmpty());
+        assertFalse(response.readEntity(String.class).isEmpty());
     }
 
     @Test
diff --git a/fit/wa-reference/src/main/resources/log4j2.xml 
b/fit/wa-reference/src/main/resources/log4j2.xml
index 9254c8ecab..e1468f37ed 100644
--- a/fit/wa-reference/src/main/resources/log4j2.xml
+++ b/fit/wa-reference/src/main/resources/log4j2.xml
@@ -52,6 +52,10 @@ under the License.
       <appender-ref ref="main"/>
     </asyncLogger>
 
+    <asyncLogger name="io.micrometer" additivity="false" level="ERROR">
+      <appender-ref ref="main"/>
+    </asyncLogger>
+
     <asyncLogger name="org.springframework" additivity="false" level="INFO">
       <appender-ref ref="main"/>
     </asyncLogger>
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index af705c303e..188d516894 100644
--- a/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/wa-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -22,10 +22,7 @@ import static org.awaitility.Awaitility.await;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import com.nimbusds.jose.util.IOUtils;
 import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
@@ -53,6 +50,7 @@ import 
org.apache.syncope.common.rest.api.service.SRARouteService;
 import org.apache.syncope.common.rest.api.service.UserService;
 import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
 import org.apache.syncope.fit.sra.AbstractSRAITCase;
+import org.apereo.cas.oidc.OidcConstants;
 import org.jsoup.Connection;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.FormElement;
@@ -117,26 +115,22 @@ public abstract class AbstractITCase {
         await().atMost(60, TimeUnit.SECONDS).pollInterval(20, 
TimeUnit.SECONDS).until(() -> {
             boolean refreshed = false;
             try {
-                String metadata = IOUtils.readInputStreamToString(
-                        (InputStream) WebClient.create(
-                                WA_ADDRESS + 
"/idp/metadata").get().getEntity(),
-                        StandardCharsets.UTF_8);
+                String metadata = WebClient.create(
+                        WA_ADDRESS + 
"/idp/metadata").get().readEntity(String.class);
                 if (metadata.contains("localhost:8080")) {
                     
WA_CONFIG_SERVICE.pushToWA(WAConfigService.PushSubject.conf, List.of());
                     throw new IllegalStateException();
                 }
-                metadata = IOUtils.readInputStreamToString(
-                        (InputStream) WebClient.create(
-                                WA_ADDRESS + 
"/oidc/.well-known/openid-configuration").get().getEntity(),
-                        StandardCharsets.UTF_8);
+                metadata = WebClient.create(
+                        WA_ADDRESS + "/oidc/" + 
OidcConstants.WELL_KNOWN_OPENID_CONFIGURATION_URL).
+                        get().readEntity(String.class);
                 if (metadata.contains("localhost:8080")) {
                     
WA_CONFIG_SERVICE.pushToWA(WAConfigService.PushSubject.conf, List.of());
                     throw new IllegalStateException();
                 }
-                metadata = IOUtils.readInputStreamToString(
-                        (InputStream) WebClient.create(
-                                WA_ADDRESS + "/actuator/registeredServices", 
"anonymous", "anonymousKey", null).
-                                get().getEntity(), StandardCharsets.UTF_8);
+                metadata = WebClient.create(
+                        WA_ADDRESS + "/actuator/registeredServices", 
"anonymous", "anonymousKey", null).
+                        get().readEntity(String.class);
                 if (metadata.contains("localhost:8080/syncope-wa")) {
                     
WA_CONFIG_SERVICE.pushToWA(WAConfigService.PushSubject.conf, List.of());
                     throw new IllegalStateException();
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/CASSRAITCase.java 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/CASSRAITCase.java
index cfa3cf3321..bb2a7d4d3f 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/CASSRAITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/CASSRAITCase.java
@@ -45,6 +45,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.EntityUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.CASSPClientAppTO;
 import org.apache.syncope.common.lib.types.ClientAppType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
@@ -71,6 +72,7 @@ public class CASSRAITCase extends AbstractSRAITCase {
                 orElseGet(() -> {
                     CASSPClientAppTO app = new CASSPClientAppTO();
                     app.setName(appName);
+                    app.setRealm(SyncopeConstants.ROOT_REALM);
                     app.setClientAppId(4L);
                     app.setServiceId("http://127.0.0.1:8080/.*";);
 
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
index bcd7369cc0..4f6cec2040 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OAUTH2SRAITCase.java
@@ -19,16 +19,13 @@
 package org.apache.syncope.fit.sra;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.fail;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
-import com.fasterxml.jackson.databind.JsonNode;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
-import java.text.ParseException;
 import java.util.Properties;
 import java.util.concurrent.TimeoutException;
 import org.apache.http.HttpStatus;
@@ -54,6 +51,8 @@ public class OAUTH2SRAITCase extends OIDCSRAITCase {
         } catch (Exception e) {
             fail("Could not load /sra-oauth2.properties", e);
         }
+        SRA_REGISTRATION_ID = "OAUTH2";
+        CLIENT_APP_ID = 2L;
         CLIENT_ID = props.getProperty("sra.oauth2.client-id");
         assertNotNull(CLIENT_ID);
         CLIENT_SECRET = props.getProperty("sra.oauth2.client-secret");
@@ -61,7 +60,8 @@ public class OAUTH2SRAITCase extends OIDCSRAITCase {
         TOKEN_URI = props.getProperty("sra.oauth2.tokenUri");
         assertNotNull(TOKEN_URI);
 
-        oidcClientAppSetup(OAUTH2SRAITCase.class.getName(), "OAUTH2", 2L, 
CLIENT_ID, CLIENT_SECRET);
+        oidcClientAppSetup(
+                OAUTH2SRAITCase.class.getName(), SRA_REGISTRATION_ID, 
CLIENT_APP_ID, CLIENT_ID, CLIENT_SECRET);
     }
 
     @Override
@@ -70,7 +70,7 @@ public class OAUTH2SRAITCase extends OIDCSRAITCase {
     }
 
     @Override
-    protected void checkIdToken(final JsonNode json) throws ParseException {
-        assertFalse(json.has("id_token"));
+    protected boolean checkIdToken() {
+        return false;
     }
 }
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
index 9736e3b070..12fdbb7717 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/OIDCSRAITCase.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.fit.sra;
 
+import static org.awaitility.Awaitility.await;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.oneOf;
@@ -40,6 +41,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import javax.ws.rs.core.Form;
 import javax.ws.rs.core.HttpHeaders;
@@ -59,17 +61,25 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.EntityUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.OIDCRPClientAppTO;
 import org.apache.syncope.common.lib.types.ClientAppType;
+import org.apache.syncope.common.lib.types.OIDCGrantType;
+import org.apache.syncope.common.lib.types.OIDCScope;
 import org.apache.syncope.common.lib.types.OIDCSubjectType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
+import org.apereo.cas.oidc.OidcConstants;
 import org.jsoup.Jsoup;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
 public class OIDCSRAITCase extends AbstractSRAITCase {
 
+    protected static String SRA_REGISTRATION_ID;
+
+    protected static Long CLIENT_APP_ID;
+
     protected static String CLIENT_ID;
 
     protected static String CLIENT_SECRET;
@@ -97,6 +107,7 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
                 orElseGet(() -> {
                     OIDCRPClientAppTO app = new OIDCRPClientAppTO();
                     app.setName(appName);
+                    app.setRealm(SyncopeConstants.ROOT_REALM);
                     app.setClientAppId(clientAppId);
                     app.setClientId(clientId);
                     app.setClientSecret(clientSecret);
@@ -121,8 +132,30 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
         clientApp.setLogoutUri(SRA_ADDRESS + "/logout");
         clientApp.setAuthPolicy(getAuthPolicy().getKey());
         clientApp.setAttrReleasePolicy(getAttrReleasePolicy().getKey());
+        clientApp.getScopes().add(OIDCScope.openid);
+        clientApp.getScopes().add(OIDCScope.profile);
+        clientApp.getScopes().add(OIDCScope.email);
+        clientApp.getSupportedGrantTypes().add(OIDCGrantType.password);
+        
clientApp.getSupportedGrantTypes().add(OIDCGrantType.authorization_code);
 
         CLIENT_APP_SERVICE.update(ClientAppType.OIDCRP, clientApp);
+
+        await().atMost(60, TimeUnit.SECONDS).pollInterval(20, 
TimeUnit.SECONDS).until(() -> {
+            try {
+                String metadata = WebClient.create(
+                        WA_ADDRESS + "/oidc/" + 
OidcConstants.WELL_KNOWN_OPENID_CONFIGURATION_URL).
+                        get().readEntity(String.class);
+                if (!metadata.contains("groups")) {
+                    
WA_CONFIG_SERVICE.pushToWA(WAConfigService.PushSubject.conf, List.of());
+                    throw new IllegalStateException();
+                }
+
+                return true;
+            } catch (Exception e) {
+                // ignore
+            }
+            return false;
+        });
         WA_CONFIG_SERVICE.pushToWA(WAConfigService.PushSubject.clientApps, 
List.of());
     }
 
@@ -136,13 +169,16 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
         } catch (Exception e) {
             fail("Could not load /sra-oidc.properties", e);
         }
+        SRA_REGISTRATION_ID = "OIDC";
+        CLIENT_APP_ID = 1L;
         CLIENT_ID = props.getProperty("sra.oidc.client-id");
         assertNotNull(CLIENT_ID);
         CLIENT_SECRET = props.getProperty("sra.oidc.client-secret");
         assertNotNull(CLIENT_SECRET);
         TOKEN_URI = WA_ADDRESS + "/oidc/accessToken";
 
-        oidcClientAppSetup(OIDCSRAITCase.class.getName(), "OIDC", 1L, 
CLIENT_ID, CLIENT_SECRET);
+        oidcClientAppSetup(
+                OIDCSRAITCase.class.getName(), SRA_REGISTRATION_ID, 
CLIENT_APP_ID, CLIENT_ID, CLIENT_SECRET);
     }
 
     @Test
@@ -222,11 +258,15 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
         checkLogout(response);
     }
 
-    protected void checkIdToken(final JsonNode json) throws ParseException {
-        SignedJWT idToken = SignedJWT.parse(json.get("id_token").asText());
-        assertNotNull(idToken);
-        JWTClaimsSet idTokenClaimsSet = idToken.getJWTClaimsSet();
-        assertEquals("verdi", 
idTokenClaimsSet.getStringClaim("preferred_username"));
+    private void checkJWT(final String token, final boolean idToken) throws 
ParseException {
+        assertNotNull(token);
+        SignedJWT jwt = SignedJWT.parse(token);
+        assertNotNull(jwt);
+        JWTClaimsSet idTokenClaimsSet = jwt.getJWTClaimsSet();
+        assertEquals("verdi", idTokenClaimsSet.getSubject());
+        if (idToken) {
+            assertEquals("verdi", 
idTokenClaimsSet.getStringClaim("preferred_username"));
+        }
         assertEquals("[email protected]", 
idTokenClaimsSet.getStringClaim("email"));
         assertEquals("Verdi", idTokenClaimsSet.getStringClaim("family_name"));
         assertEquals("Giuseppe", 
idTokenClaimsSet.getStringClaim("given_name"));
@@ -234,6 +274,10 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
         assertEquals(Set.of("root", "child", "citizen"), 
Set.of(idTokenClaimsSet.getStringArrayClaim("groups")));
     }
 
+    protected boolean checkIdToken() {
+        return true;
+    }
+
     @Test
     public void rest() throws IOException, ParseException {
         // 0. access public route
@@ -249,19 +293,23 @@ public class OIDCSRAITCase extends AbstractSRAITCase {
                 param("client_secret", CLIENT_SECRET).
                 param("username", "verdi").
                 param("password", "password").
-                param("scope", "openid profile email address phone 
offline_access syncope");
+                param("scope", "openid profile email syncope");
         response = WebClient.create(TOKEN_URI).post(form);
         assertEquals(HttpStatus.SC_OK, response.getStatus());
         
assertTrue(response.getHeaderString(HttpHeaders.CONTENT_TYPE).startsWith(MediaType.APPLICATION_JSON));
 
         JsonNode json = MAPPER.readTree(response.readEntity(String.class));
 
-        // 1a. verify id_token
-        checkIdToken(json);
+        if (checkIdToken()) {
+            // 1a. take and verify id_token
+            String idToken = json.get("id_token").asText();
+            assertNotNull(idToken);
+            checkJWT(idToken, true);
+        }
 
-        // 1b. take access_token
+        // 1b. take and verify access_token
         String accessToken = json.get("access_token").asText();
-        assertNotNull(accessToken);
+        checkJWT(accessToken, false);
 
         // 2. access protected route
         client = WebClient.create(SRA_ADDRESS + "/protected/post").
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/SAML2SRAITCase.java 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/SAML2SRAITCase.java
index 8497326e81..63243f5890 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/SAML2SRAITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/sra/SAML2SRAITCase.java
@@ -46,6 +46,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.EntityUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.SAML2SPClientAppTO;
 import org.apache.syncope.common.lib.types.ClientAppType;
 import org.apache.syncope.common.lib.types.SAML2SPNameId;
@@ -73,6 +74,7 @@ public class SAML2SRAITCase extends AbstractSRAITCase {
                 orElseGet(() -> {
                     SAML2SPClientAppTO app = new SAML2SPClientAppTO();
                     app.setName(appName);
+                    app.setRealm(SyncopeConstants.ROOT_REALM);
                     app.setClientAppId(3L);
                     app.setEntityId(SRA_ADDRESS);
                     app.setMetadataLocation(SRA_ADDRESS + "/saml2/metadata");
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/AbstractUIITCase.java
 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/AbstractUIITCase.java
index bdbf909069..a30dfd4551 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/AbstractUIITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/AbstractUIITCase.java
@@ -84,10 +84,10 @@ public abstract class AbstractUIITCase extends 
AbstractITCase {
                     DefaultAttrReleasePolicyConf policyConf = new 
DefaultAttrReleasePolicyConf();
                     
policyConf.getPrincipalAttrRepoConf().getAttrRepos().add(stubAttrRepo);
                     policyConf.getReleaseAttrs().put("attr1", "identifier");
-                    policyConf.getReleaseAttrs().put("firstname", "givenName");
-                    policyConf.getReleaseAttrs().put("surname", "sn");
-                    policyConf.getReleaseAttrs().put("fullname", "cn");
-                    policyConf.getReleaseAttrs().put("email", "mail");
+                    policyConf.getReleaseAttrs().put("firstname", 
"given_name");
+                    policyConf.getReleaseAttrs().put("surname", "family_name");
+                    policyConf.getReleaseAttrs().put("fullname", "name");
+                    policyConf.getReleaseAttrs().put("email", "email");
 
                     AttrReleasePolicyTO policy = new AttrReleasePolicyTO();
                     policy.setName(description);
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/OIDC4UIITCase.java 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/OIDCC4UIITCase.java
similarity index 91%
rename from 
fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/OIDC4UIITCase.java
rename to 
fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/OIDCC4UIITCase.java
index 2b40a82e24..9abaeedccc 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/OIDC4UIITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/OIDCC4UIITCase.java
@@ -28,6 +28,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.apache.http.Consts;
@@ -45,18 +47,20 @@ import org.apache.http.impl.client.HttpClients;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.EntityUtils;
 import org.apache.syncope.client.ui.commons.panels.OIDCC4UIConstants;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.Item;
 import org.apache.syncope.common.lib.to.OIDCC4UIProviderTO;
 import org.apache.syncope.common.lib.to.OIDCRPClientAppTO;
 import org.apache.syncope.common.lib.types.ClientAppType;
 import org.apache.syncope.common.lib.types.OIDCResponseType;
+import org.apache.syncope.common.lib.types.OIDCScope;
 import org.apache.syncope.common.lib.types.OIDCSubjectType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
 import org.jsoup.Jsoup;
 import org.junit.jupiter.api.BeforeAll;
 
-public class OIDC4UIITCase extends AbstractUIITCase {
+public class OIDCC4UIITCase extends AbstractUIITCase {
 
     private static void clientAppSetup(final String appName, final String 
baseAddress, final long appId) {
         OIDCRPClientAppTO clientApp = 
CLIENT_APP_SERVICE.list(ClientAppType.OIDCRP).stream().
@@ -66,6 +70,7 @@ public class OIDC4UIITCase extends AbstractUIITCase {
                 orElseGet(() -> {
                     OIDCRPClientAppTO app = new OIDCRPClientAppTO();
                     app.setName(appName);
+                    app.setRealm(SyncopeConstants.ROOT_REALM);
                     app.setClientAppId(appId);
                     app.setClientId(appName);
                     app.setClientSecret(appName);
@@ -92,6 +97,9 @@ public class OIDC4UIITCase extends AbstractUIITCase {
                 Set.of(OIDCResponseType.CODE, OIDCResponseType.ID_TOKEN_TOKEN, 
OIDCResponseType.TOKEN));
         clientApp.setAuthPolicy(getAuthPolicy().getKey());
         clientApp.setAttrReleasePolicy(getAttrReleasePolicy().getKey());
+        clientApp.getScopes().add(OIDCScope.openid);
+        clientApp.getScopes().add(OIDCScope.profile);
+        clientApp.getScopes().add(OIDCScope.email);
 
         CLIENT_APP_SERVICE.update(ClientAppType.OIDCRP, clientApp);
         WA_CONFIG_SERVICE.pushToWA(WAConfigService.PushSubject.clientApps, 
List.of());
@@ -99,8 +107,8 @@ public class OIDC4UIITCase extends AbstractUIITCase {
 
     private static String getAppName(final String address) {
         return CONSOLE_ADDRESS.equals(address)
-                ? OIDC4UIITCase.class.getName() + "_Console"
-                : OIDC4UIITCase.class.getName() + "_Enduser";
+                ? OIDCC4UIITCase.class.getName() + "_Console"
+                : OIDCC4UIITCase.class.getName() + "_Enduser";
     }
 
     @BeforeAll
@@ -134,6 +142,9 @@ public class OIDC4UIITCase extends AbstractUIITCase {
             cas.setUserinfoEndpoint(cas.getIssuer() + "/profile");
             cas.setEndSessionEndpoint(cas.getIssuer() + "/logout");
 
+            
cas.getScopes().addAll(Stream.of(OIDCScope.values()).map(OIDCScope::name).collect(Collectors.toList()));
+            cas.getScopes().add("syncope");
+
             cas.setCreateUnmatching(createUnmatching);
             cas.setSelfRegUnmatching(selfRegUnmatching);
 
@@ -145,27 +156,27 @@ public class OIDC4UIITCase extends AbstractUIITCase {
 
             item = new Item();
             item.setIntAttrName("email");
-            item.setExtAttrName("mail");
+            item.setExtAttrName("email");
             cas.add(item);
 
             item = new Item();
             item.setIntAttrName("userId");
-            item.setExtAttrName("mail");
+            item.setExtAttrName("email");
             cas.add(item);
 
             item = new Item();
             item.setIntAttrName("firstname");
-            item.setExtAttrName("givenName");
+            item.setExtAttrName("given_name");
             cas.add(item);
 
             item = new Item();
             item.setIntAttrName("surname");
-            item.setExtAttrName("sn");
+            item.setExtAttrName("family_name");
             cas.add(item);
 
             item = new Item();
             item.setIntAttrName("fullname");
-            item.setExtAttrName("cn");
+            item.setExtAttrName("name");
             cas.add(item);
 
             OIDCC4UI_PROVIDER_SERVICE.create(cas);
diff --git 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
index 2c63604369..caf1aae069 100644
--- 
a/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
+++ 
b/fit/wa-reference/src/test/java/org/apache/syncope/fit/ui/SAML2SP4UIITCase.java
@@ -48,6 +48,7 @@ import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.EntityUtils;
 import org.apache.syncope.client.ui.commons.SAML2SP4UIConstants;
 import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.Item;
 import org.apache.syncope.common.lib.to.SAML2SP4UIIdPTO;
 import org.apache.syncope.common.lib.to.SAML2SPClientAppTO;
@@ -68,6 +69,7 @@ public class SAML2SP4UIITCase extends AbstractUIITCase {
                 orElseGet(() -> {
                     SAML2SPClientAppTO app = new SAML2SPClientAppTO();
                     app.setName(appName);
+                    app.setRealm(SyncopeConstants.ROOT_REALM);
                     app.setClientAppId(appId);
                     app.setEntityId(entityId);
                     app.setMetadataLocation(entityId + 
SAML2SP4UIConstants.URL_CONTEXT + "/metadata");
@@ -136,27 +138,27 @@ public class SAML2SP4UIITCase extends AbstractUIITCase {
 
         item = new Item();
         item.setIntAttrName("email");
-        item.setExtAttrName("mail");
+        item.setExtAttrName("email");
         cas.add(item);
 
         item = new Item();
         item.setIntAttrName("userId");
-        item.setExtAttrName("mail");
+        item.setExtAttrName("email");
         cas.add(item);
 
         item = new Item();
         item.setIntAttrName("firstname");
-        item.setExtAttrName("givenName");
+        item.setExtAttrName("given_name");
         cas.add(item);
 
         item = new Item();
         item.setIntAttrName("surname");
-        item.setExtAttrName("sn");
+        item.setExtAttrName("family_name");
         cas.add(item);
 
         item = new Item();
         item.setIntAttrName("fullname");
-        item.setExtAttrName("cn");
+        item.setExtAttrName("name");
         cas.add(item);
 
         SAML2SP4UI_IDP_SERVICE.update(cas);
diff --git a/fit/wa-reference/src/test/resources/sra-oidc.properties 
b/fit/wa-reference/src/test/resources/sra-oidc.properties
index 9f7b8f3ea3..c4a60b99ba 100644
--- a/fit/wa-reference/src/test/resources/sra-oidc.properties
+++ b/fit/wa-reference/src/test/resources/sra-oidc.properties
@@ -22,5 +22,6 @@ sra.am-type=OIDC
 sra.oidc.configuration=https://localhost:9443/syncope-wa/oidc
 sra.oidc.client-id=oidcTestClientId
 sra.oidc.client-secret=oidcTestClientSecret
+sra.oidc.scopes=openid,profile,email
 
 sra.global.postLogout=http://localhost:8080/logout
diff --git a/sra/src/test/resources/debug/sra-debug.properties 
b/sra/src/test/resources/debug/sra-debug.properties
index f73cd07e94..a95b6b9538 100644
--- a/sra/src/test/resources/debug/sra-debug.properties
+++ b/sra/src/test/resources/debug/sra-debug.properties
@@ -22,6 +22,7 @@ sra.am-type=OIDC
 sra.oidc.configuration=https://localhost:9443/syncope-wa/oidc
 sra.oidc.client-id=oidcTestClientId
 sra.oidc.client-secret=oidcTestClientSecret
+sra.oidc.scopes=openid,profile,email
 
 #sra.am-type=OAUTH2
 #sra.oauth2.tokenUri=https://localhost:9443/syncope-wa/oauth2.0/accessToken
diff --git a/wa/bootstrap/pom.xml b/wa/bootstrap/pom.xml
index 5cf252bd37..0127400461 100644
--- a/wa/bootstrap/pom.xml
+++ b/wa/bootstrap/pom.xml
@@ -57,6 +57,14 @@ under the License.
       <groupId>org.apereo.cas</groupId>
       <artifactId>cas-server-core-util-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apereo.cas</groupId>
+      <artifactId>cas-server-core-authentication-attributes</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apereo.cas</groupId>
+      <artifactId>cas-server-support-oidc-core</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>org.slf4j</groupId>
diff --git 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java
 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java
index f470e9a778..dcd0fb7a21 100644
--- 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java
+++ 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java
@@ -18,6 +18,10 @@
  */
 package org.apache.syncope.wa.bootstrap;
 
+import org.apache.syncope.wa.bootstrap.mapping.AttrReleaseMapper;
+import org.apache.syncope.wa.bootstrap.mapping.AttrRepoPropertySourceMapper;
+import org.apache.syncope.wa.bootstrap.mapping.AuthModulePropertySourceMapper;
+import org.apache.syncope.wa.bootstrap.mapping.DefaultAttrReleaseMapper;
 import 
org.apereo.cas.configuration.support.CasConfigurationJasyptCipherExecutor;
 import org.apereo.cas.util.crypto.CipherExecutor;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -58,8 +62,8 @@ public class WABootstrapConfiguration {
     @Configuration(proxyBeanMethods = false)
     public static class PropertySourceConfiguration {
 
-        @Bean
         @ConditionalOnMissingBean(name = "waConfigurationCipher")
+        @Bean
         public CipherExecutor<String, String> waConfigurationCipher(final 
Environment environment) {
             return new CasConfigurationJasyptCipherExecutor(environment);
         }
@@ -76,17 +80,27 @@ public class WABootstrapConfiguration {
             return new AttrRepoPropertySourceMapper(waRestClient);
         }
 
+        @ConditionalOnMissingBean
+        @Bean
+        public AttrReleaseMapper attrReleaseMapper() {
+            return new DefaultAttrReleaseMapper();
+        }
+
         @Bean
         public PropertySourceLocator configPropertySourceLocator(
                 @Qualifier("waConfigurationCipher")
                 final CipherExecutor<String, String> waConfigurationCipher,
                 final WARestClient waRestClient,
                 final AuthModulePropertySourceMapper 
authModulePropertySourceMapper,
-                final AttrRepoPropertySourceMapper 
attrRepoPropertySourceMapper) {
+                final AttrRepoPropertySourceMapper 
attrRepoPropertySourceMapper,
+                final AttrReleaseMapper attrReleaseMapper) {
 
             return new WAPropertySourceLocator(
-                    waRestClient, authModulePropertySourceMapper,
-                    attrRepoPropertySourceMapper, waConfigurationCipher);
+                    waRestClient,
+                    authModulePropertySourceMapper,
+                    attrRepoPropertySourceMapper,
+                    attrReleaseMapper,
+                    waConfigurationCipher);
         }
     }
 }
diff --git 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java
 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java
index 21b8ff3c2f..96e372a8a9 100644
--- 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java
+++ 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java
@@ -19,16 +19,35 @@
 package org.apache.syncope.wa.bootstrap;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.to.OIDCRPClientAppTO;
+import org.apache.syncope.common.lib.types.OIDCScope;
 import org.apache.syncope.common.rest.api.service.AttrRepoService;
 import org.apache.syncope.common.rest.api.service.AuthModuleService;
+import org.apache.syncope.common.rest.api.service.wa.WAClientAppService;
 import org.apache.syncope.common.rest.api.service.wa.WAConfigService;
+import org.apache.syncope.wa.bootstrap.mapping.AttrReleaseMapper;
+import org.apache.syncope.wa.bootstrap.mapping.AttrRepoPropertySourceMapper;
+import org.apache.syncope.wa.bootstrap.mapping.AuthModulePropertySourceMapper;
+import org.apereo.cas.configuration.model.support.oidc.OidcDiscoveryProperties;
+import org.apereo.cas.oidc.claims.OidcAddressScopeAttributeReleasePolicy;
+import org.apereo.cas.oidc.claims.OidcEmailScopeAttributeReleasePolicy;
+import org.apereo.cas.oidc.claims.OidcPhoneScopeAttributeReleasePolicy;
+import org.apereo.cas.oidc.claims.OidcProfileScopeAttributeReleasePolicy;
+import org.apereo.cas.services.BaseMappedAttributeReleasePolicy;
+import org.apereo.cas.services.ChainingAttributeReleasePolicy;
+import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
+import org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy;
 import org.apereo.cas.util.crypto.CipherExecutor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,17 +68,21 @@ public class WAPropertySourceLocator implements 
PropertySourceLocator {
 
     protected final AttrRepoPropertySourceMapper attrRepoPropertySourceMapper;
 
+    protected final AttrReleaseMapper attrReleaseMapper;
+
     protected final CipherExecutor<String, String> configurationCipher;
 
     public WAPropertySourceLocator(
             final WARestClient waRestClient,
             final AuthModulePropertySourceMapper 
authModulePropertySourceMapper,
             final AttrRepoPropertySourceMapper attrRepoPropertySourceMapper,
+            final AttrReleaseMapper attrReleaseMapper,
             final CipherExecutor<String, String> configurationCipher) {
 
         this.waRestClient = waRestClient;
         this.authModulePropertySourceMapper = authModulePropertySourceMapper;
         this.attrRepoPropertySourceMapper = attrRepoPropertySourceMapper;
+        this.attrReleaseMapper = attrReleaseMapper;
         this.configurationCipher = configurationCipher;
     }
 
@@ -109,6 +132,56 @@ public class WAPropertySourceLocator implements 
PropertySourceLocator {
             properties.putAll(index(map, prefixes));
         });
 
+        Set<String> customClaims = 
syncopeClient.getService(WAClientAppService.class).list().stream().
+                filter(clientApp -> clientApp.getAttrReleasePolicy() != null
+                && clientApp.getClientAppTO() instanceof OIDCRPClientAppTO).
+                flatMap(clientApp -> {
+                    OIDCRPClientAppTO rp = 
OIDCRPClientAppTO.class.cast(clientApp.getClientAppTO());
+
+                    RegisteredServiceAttributeReleasePolicy 
attributeReleasePolicy =
+                            
attrReleaseMapper.build(clientApp.getAttrReleasePolicy());
+
+                    Set<String> claims = new HashSet<>();
+                    if (attributeReleasePolicy instanceof 
BaseMappedAttributeReleasePolicy) {
+                        claims.addAll(((BaseMappedAttributeReleasePolicy) 
attributeReleasePolicy).
+                                getAllowedAttributes().values().stream().
+                                
map(Objects::toString).collect(Collectors.toSet()));
+                    } else if (attributeReleasePolicy instanceof 
ReturnAllowedAttributeReleasePolicy) {
+                        claims.addAll(((ReturnAllowedAttributeReleasePolicy) 
attributeReleasePolicy).
+                                
getAllowedAttributes().stream().collect(Collectors.toSet()));
+                    } else if (attributeReleasePolicy instanceof 
ChainingAttributeReleasePolicy) {
+                        ((ChainingAttributeReleasePolicy) 
attributeReleasePolicy).getPolicies().stream().
+                                
filter(ReturnAllowedAttributeReleasePolicy.class::isInstance).
+                                
findFirst().map(ReturnAllowedAttributeReleasePolicy.class::cast).
+                                map(p -> 
p.getAllowedAttributes().stream().collect(Collectors.toSet())).
+                                ifPresent(claims::addAll);
+                    }
+                    if (rp.getScopes().contains(OIDCScope.profile)) {
+                        
claims.removeAll(OidcProfileScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
+                    }
+                    if (rp.getScopes().contains(OIDCScope.address)) {
+                        
claims.removeAll(OidcAddressScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
+                    }
+                    if (rp.getScopes().contains(OIDCScope.email)) {
+                        
claims.removeAll(OidcEmailScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
+                    }
+                    if (rp.getScopes().contains(OIDCScope.phone)) {
+                        
claims.removeAll(OidcPhoneScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
+                    }
+
+                    return claims.stream();
+                }).collect(Collectors.toSet());
+        if (!customClaims.isEmpty()) {
+            Stream.concat(new OidcDiscoveryProperties().getClaims().stream(), 
customClaims.stream()).
+                    collect(Collectors.joining(","));
+
+            properties.put("cas.authn.oidc.discovery.claims",
+                    Stream.concat(new 
OidcDiscoveryProperties().getClaims().stream(), customClaims.stream()).
+                            collect(Collectors.joining(",")));
+            properties.put("cas.authn.oidc.core.user-defined-scopes.syncope",
+                    customClaims.stream().collect(Collectors.joining(",")));
+        }
+
         syncopeClient.getService(WAConfigService.class).list().forEach(attr -> 
properties.put(
                 attr.getSchema(), 
attr.getValues().stream().collect(Collectors.joining(","))));
 
diff --git 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java
index 8d48df5a02..cd7c227782 100644
--- 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java
+++ 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WARestClient.java
@@ -89,7 +89,7 @@ public class WARestClient {
         return Optional.empty();
     }
 
-    protected SyncopeClient getSyncopeClient() {
+    public SyncopeClient getSyncopeClient() {
         synchronized (this) {
             if (client == null) {
                 getCore().ifPresent(core -> {
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AttrReleaseMapper.java
 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/AttrReleaseMapper.java
similarity index 96%
rename from 
wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AttrReleaseMapper.java
rename to 
wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/AttrReleaseMapper.java
index 7b54d36734..021968582a 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/AttrReleaseMapper.java
+++ 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/AttrReleaseMapper.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.wa.starter.mapping;
+package org.apache.syncope.wa.bootstrap.mapping;
 
 import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf;
 import org.apache.syncope.common.lib.policy.AttrReleasePolicyTO;
diff --git 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/AttrRepoPropertySourceMapper.java
 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/AttrRepoPropertySourceMapper.java
similarity index 98%
rename from 
wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/AttrRepoPropertySourceMapper.java
rename to 
wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/AttrRepoPropertySourceMapper.java
index 28e0e239ea..cbdf8bd665 100644
--- 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/AttrRepoPropertySourceMapper.java
+++ 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/AttrRepoPropertySourceMapper.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.wa.bootstrap;
+package org.apache.syncope.wa.bootstrap.mapping;
 
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -29,6 +29,7 @@ import org.apache.syncope.common.lib.attr.StubAttrRepoConf;
 import org.apache.syncope.common.lib.attr.SyncopeAttrRepoConf;
 import org.apache.syncope.common.lib.to.AttrRepoTO;
 import org.apache.syncope.common.lib.to.Item;
+import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apereo.cas.configuration.CasCoreConfigurationUtils;
 import 
org.apereo.cas.configuration.model.core.authentication.AttributeRepositoryStates;
 import 
org.apereo.cas.configuration.model.core.authentication.StubPrincipalAttributesProperties;
diff --git 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/AuthModulePropertySourceMapper.java
 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/AuthModulePropertySourceMapper.java
similarity index 99%
rename from 
wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/AuthModulePropertySourceMapper.java
rename to 
wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/AuthModulePropertySourceMapper.java
index c723556ed0..e3c4c876a4 100644
--- 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/AuthModulePropertySourceMapper.java
+++ 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/AuthModulePropertySourceMapper.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.wa.bootstrap;
+package org.apache.syncope.wa.bootstrap.mapping;
 
 import java.util.Map;
 import java.util.Optional;
@@ -45,6 +45,7 @@ import org.apache.syncope.common.lib.auth.U2FAuthModuleConf;
 import org.apache.syncope.common.lib.to.AuthModuleTO;
 import org.apache.syncope.common.lib.to.Item;
 import org.apache.syncope.common.lib.types.AuthModuleState;
+import org.apache.syncope.wa.bootstrap.WARestClient;
 import org.apereo.cas.configuration.CasCoreConfigurationUtils;
 import 
org.apereo.cas.configuration.model.core.authentication.AuthenticationHandlerStates;
 import 
org.apereo.cas.configuration.model.support.generic.AcceptAuthenticationProperties;
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAttrReleaseMapper.java
 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/DefaultAttrReleaseMapper.java
similarity index 99%
rename from 
wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAttrReleaseMapper.java
rename to 
wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/DefaultAttrReleaseMapper.java
index 5279c15232..aa03074c32 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/DefaultAttrReleaseMapper.java
+++ 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/DefaultAttrReleaseMapper.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.wa.starter.mapping;
+package org.apache.syncope.wa.bootstrap.mapping;
 
 import java.util.HashSet;
 import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf;
diff --git 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/PropertySourceMapper.java
 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PropertySourceMapper.java
similarity index 99%
rename from 
wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/PropertySourceMapper.java
rename to 
wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PropertySourceMapper.java
index 1cf4f6cd98..ce2f3ac627 100644
--- 
a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/PropertySourceMapper.java
+++ 
b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PropertySourceMapper.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.wa.bootstrap;
+package org.apache.syncope.wa.bootstrap.mapping;
 
 import java.util.Map;
 import java.util.Optional;
diff --git 
a/wa/bootstrap/src/test/java/org/apache/syncope/wa/bootstrap/AuthModulePropertySourceMapperTest.java
 
b/wa/bootstrap/src/test/java/org/apache/syncope/wa/bootstrap/AuthModulePropertySourceMapperTest.java
index b495d3c642..f1288c7e0a 100644
--- 
a/wa/bootstrap/src/test/java/org/apache/syncope/wa/bootstrap/AuthModulePropertySourceMapperTest.java
+++ 
b/wa/bootstrap/src/test/java/org/apache/syncope/wa/bootstrap/AuthModulePropertySourceMapperTest.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import org.apache.syncope.common.lib.auth.OAuth20AuthModuleConf;
 import org.apache.syncope.common.lib.auth.SimpleMfaAuthModuleConf;
 import org.apache.syncope.common.lib.to.AuthModuleTO;
+import org.apache.syncope.wa.bootstrap.mapping.AuthModulePropertySourceMapper;
 import org.junit.jupiter.api.Test;
 
 public class AuthModulePropertySourceMapperTest {
diff --git a/wa/starter/pom.xml b/wa/starter/pom.xml
index af48c5318c..494494a7be 100644
--- a/wa/starter/pom.xml
+++ b/wa/starter/pom.xml
@@ -186,10 +186,6 @@ under the License.
       <groupId>org.apereo.cas</groupId>
       <artifactId>cas-server-support-oidc-core-api</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.apereo.cas</groupId>
-      <artifactId>cas-server-support-oidc-core</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.apereo.cas</groupId>
       <artifactId>cas-server-support-oauth-services</artifactId>
@@ -306,10 +302,6 @@ under the License.
       <groupId>org.apereo.cas</groupId>
       <artifactId>cas-server-support-swagger</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.apereo.cas</groupId>
-      <artifactId>cas-server-core-authentication-attributes</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.apereo.cas</groupId>
       <artifactId>cas-server-core-services-authentication</artifactId>
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java
index 8871cfb159..122597d506 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java
@@ -36,6 +36,7 @@ import 
org.apache.syncope.common.keymaster.client.api.startstop.KeymasterStart;
 import org.apache.syncope.common.keymaster.client.api.startstop.KeymasterStop;
 import org.apache.syncope.wa.bootstrap.WAProperties;
 import org.apache.syncope.wa.bootstrap.WARestClient;
+import org.apache.syncope.wa.bootstrap.mapping.AttrReleaseMapper;
 import org.apache.syncope.wa.starter.actuate.SyncopeCoreHealthIndicator;
 import org.apache.syncope.wa.starter.actuate.SyncopeWAInfoContributor;
 import org.apache.syncope.wa.starter.audit.WAAuditTrailManager;
@@ -43,12 +44,10 @@ import 
org.apache.syncope.wa.starter.events.WAEventRepository;
 import org.apache.syncope.wa.starter.gauth.WAGoogleMfaAuthCredentialRepository;
 import org.apache.syncope.wa.starter.gauth.WAGoogleMfaAuthTokenRepository;
 import org.apache.syncope.wa.starter.mapping.AccessMapper;
-import org.apache.syncope.wa.starter.mapping.AttrReleaseMapper;
 import org.apache.syncope.wa.starter.mapping.AuthMapper;
 import org.apache.syncope.wa.starter.mapping.CASSPClientAppTOMapper;
 import org.apache.syncope.wa.starter.mapping.ClientAppMapper;
 import org.apache.syncope.wa.starter.mapping.DefaultAccessMapper;
-import org.apache.syncope.wa.starter.mapping.DefaultAttrReleaseMapper;
 import org.apache.syncope.wa.starter.mapping.DefaultAuthMapper;
 import org.apache.syncope.wa.starter.mapping.DefaultTicketExpirationMapper;
 import org.apache.syncope.wa.starter.mapping.HttpRequestAccessMapper;
@@ -159,19 +158,13 @@ public class WAContext {
 
     @ConditionalOnMissingBean
     @Bean
-    public AttrReleaseMapper defaultAttrReleaseMapper() {
-        return new DefaultAttrReleaseMapper();
-    }
-
-    @ConditionalOnMissingBean
-    @Bean
-    public AuthMapper defaultAuthMapper() {
+    public AuthMapper authMapper() {
         return new DefaultAuthMapper();
     }
 
     @ConditionalOnMissingBean
     @Bean
-    public TicketExpirationMapper defaultTicketExpirationMapper() {
+    public TicketExpirationMapper ticketExpirationMapper() {
         return new DefaultTicketExpirationMapper();
     }
 
@@ -204,8 +197,7 @@ public class WAContext {
             final List<AccessMapper> accessMappers,
             final List<AttrReleaseMapper> attrReleaseMappers,
             final List<TicketExpirationMapper> ticketExpirationMappers,
-            final List<ClientAppMapper> clientAppMappers,
-            final CasConfigurationProperties properties) {
+            final List<ClientAppMapper> clientAppMappers) {
 
         return new RegisteredServiceMapper(
                 
Optional.ofNullable(casProperties.getAuthn().getPac4j().getCore().getName()).
@@ -216,8 +208,7 @@ public class WAContext {
                 accessMappers,
                 attrReleaseMappers,
                 ticketExpirationMappers,
-                clientAppMappers,
-                properties);
+                clientAppMappers);
     }
 
     @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/CASSPClientAppTOMapper.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/CASSPClientAppTOMapper.java
index 26b8042b80..02f3fd505f 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/CASSPClientAppTOMapper.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/CASSPClientAppTOMapper.java
@@ -21,7 +21,6 @@ package org.apache.syncope.wa.starter.mapping;
 import org.apache.syncope.common.lib.to.CASSPClientAppTO;
 import org.apache.syncope.common.lib.to.ClientAppTO;
 import org.apache.syncope.common.lib.wa.WAClientApp;
-import org.apereo.cas.configuration.CasConfigurationProperties;
 import org.apereo.cas.services.CasRegisteredService;
 import org.apereo.cas.services.RegisteredService;
 import org.apereo.cas.services.RegisteredServiceAccessStrategy;
@@ -50,8 +49,7 @@ public class CASSPClientAppTOMapper extends 
AbstractClientAppMapper {
             final RegisteredServiceTicketGrantingTicketExpirationPolicy 
tgtExpirationPolicy,
             final RegisteredServiceServiceTicketExpirationPolicy 
stExpirationPolicy,
             final RegisteredServiceProxyGrantingTicketExpirationPolicy 
tgtProxyExpirationPolicy,
-            final RegisteredServiceProxyTicketExpirationPolicy 
stProxyExpirationPolicy,
-            final CasConfigurationProperties properties) {
+            final RegisteredServiceProxyTicketExpirationPolicy 
stProxyExpirationPolicy) {
 
         CASSPClientAppTO cas = 
CASSPClientAppTO.class.cast(clientApp.getClientAppTO());
 
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java
index e9fb97a459..79cf79a6de 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/ClientAppMapper.java
@@ -20,7 +20,6 @@ package org.apache.syncope.wa.starter.mapping;
 
 import org.apache.syncope.common.lib.to.ClientAppTO;
 import org.apache.syncope.common.lib.wa.WAClientApp;
-import org.apereo.cas.configuration.CasConfigurationProperties;
 import org.apereo.cas.services.RegisteredService;
 import org.apereo.cas.services.RegisteredServiceAccessStrategy;
 import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
@@ -44,6 +43,5 @@ public interface ClientAppMapper {
             RegisteredServiceTicketGrantingTicketExpirationPolicy 
tgtExpirationPolicy,
             RegisteredServiceServiceTicketExpirationPolicy stExpirationPolicy,
             RegisteredServiceProxyGrantingTicketExpirationPolicy 
tgtProxyExpirationPolicy,
-            RegisteredServiceProxyTicketExpirationPolicy 
stProxyExpirationPolicy,
-            CasConfigurationProperties properties);
+            RegisteredServiceProxyTicketExpirationPolicy 
stProxyExpirationPolicy);
 }
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPClientAppTOMapper.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPClientAppTOMapper.java
index e3f3a881ad..3f8a4970d0 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPClientAppTOMapper.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/OIDCRPClientAppTOMapper.java
@@ -19,18 +19,16 @@
 package org.apache.syncope.wa.starter.mapping;
 
 import java.util.HashSet;
-import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 import org.apache.syncope.common.lib.to.ClientAppTO;
 import org.apache.syncope.common.lib.to.OIDCRPClientAppTO;
 import org.apache.syncope.common.lib.types.OIDCGrantType;
 import org.apache.syncope.common.lib.types.OIDCResponseType;
 import org.apache.syncope.common.lib.types.OIDCScope;
 import org.apache.syncope.common.lib.wa.WAClientApp;
-import org.apereo.cas.configuration.CasConfigurationProperties;
 import org.apereo.cas.oidc.claims.OidcAddressScopeAttributeReleasePolicy;
 import org.apereo.cas.oidc.claims.OidcCustomScopeAttributeReleasePolicy;
 import org.apereo.cas.oidc.claims.OidcEmailScopeAttributeReleasePolicy;
@@ -70,8 +68,7 @@ public class OIDCRPClientAppTOMapper extends 
AbstractClientAppMapper {
             final RegisteredServiceTicketGrantingTicketExpirationPolicy 
tgtExpirationPolicy,
             final RegisteredServiceServiceTicketExpirationPolicy 
stExpirationPolicy,
             final RegisteredServiceProxyGrantingTicketExpirationPolicy 
tgtProxyExpirationPolicy,
-            final RegisteredServiceProxyTicketExpirationPolicy 
stProxyExpirationPolicy,
-            final CasConfigurationProperties properties) {
+            final RegisteredServiceProxyTicketExpirationPolicy 
stProxyExpirationPolicy) {
 
         OIDCRPClientAppTO rp = 
OIDCRPClientAppTO.class.cast(clientApp.getClientAppTO());
         OidcRegisteredService service = new OidcRegisteredService();
@@ -89,37 +86,37 @@ public class OIDCRPClientAppTOMapper extends 
AbstractClientAppMapper {
         service.setJwtAccessToken(rp.isJwtAccessToken());
         service.setBypassApprovalPrompt(rp.isBypassApprovalPrompt());
         service.setSupportedGrantTypes(rp.getSupportedGrantTypes().stream().
-                
map(OIDCGrantType::name).collect(Collectors.toCollection(HashSet::new)));
+                map(OIDCGrantType::name).collect(Collectors.toSet()));
         
service.setSupportedResponseTypes(rp.getSupportedResponseTypes().stream().
-                
map(OIDCResponseType::getExternalForm).collect(Collectors.toCollection(HashSet::new)));
-        if (rp.getSubjectType() != null) {
-            service.setSubjectType(rp.getSubjectType().name());
-        }
+                
map(OIDCResponseType::getExternalForm).collect(Collectors.toSet()));
+        Optional.ofNullable(rp.getSubjectType()).ifPresent(st -> 
service.setSubjectType(st.name()));
         service.setLogoutUrl(rp.getLogoutUri());
 
+        service.setScopes(rp.getScopes().stream().
+                map(OIDCScope::name).
+                collect(Collectors.toSet()));
+
         ChainingAttributeReleasePolicy chain;
         if (attributeReleasePolicy instanceof ChainingAttributeReleasePolicy) {
             chain = (ChainingAttributeReleasePolicy) attributeReleasePolicy;
         } else {
             chain = new ChainingAttributeReleasePolicy();
-            if (attributeReleasePolicy != null) {
-                chain.addPolicies(attributeReleasePolicy);
-            }
+            
Optional.ofNullable(attributeReleasePolicy).ifPresent(chain::addPolicies);
         }
 
-        if (rp.getScopes().contains(OIDCScope.OPENID)) {
+        if (rp.getScopes().contains(OIDCScope.openid)) {
             chain.addPolicies(new OidcOpenIdScopeAttributeReleasePolicy());
         }
-        if (rp.getScopes().contains(OIDCScope.PROFILE)) {
+        if (rp.getScopes().contains(OIDCScope.profile)) {
             chain.addPolicies(new OidcProfileScopeAttributeReleasePolicy());
         }
-        if (rp.getScopes().contains(OIDCScope.ADDRESS)) {
+        if (rp.getScopes().contains(OIDCScope.address)) {
             chain.addPolicies(new OidcAddressScopeAttributeReleasePolicy());
         }
-        if (rp.getScopes().contains(OIDCScope.EMAIL)) {
+        if (rp.getScopes().contains(OIDCScope.email)) {
             chain.addPolicies(new OidcEmailScopeAttributeReleasePolicy());
         }
-        if (rp.getScopes().contains(OIDCScope.PHONE)) {
+        if (rp.getScopes().contains(OIDCScope.phone)) {
             chain.addPolicies(new OidcPhoneScopeAttributeReleasePolicy());
         }
 
@@ -138,25 +135,21 @@ public class OIDCRPClientAppTOMapper extends 
AbstractClientAppMapper {
                     map(p -> 
p.getAllowedAttributes().stream().collect(Collectors.toSet())).
                     ifPresent(customClaims::addAll);
         }
-        if (rp.getScopes().contains(OIDCScope.PROFILE)) {
+        if (rp.getScopes().contains(OIDCScope.profile)) {
             
customClaims.removeAll(OidcProfileScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
         }
-        if (rp.getScopes().contains(OIDCScope.ADDRESS)) {
+        if (rp.getScopes().contains(OIDCScope.address)) {
             
customClaims.removeAll(OidcAddressScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
         }
-        if (rp.getScopes().contains(OIDCScope.EMAIL)) {
+        if (rp.getScopes().contains(OIDCScope.email)) {
             
customClaims.removeAll(OidcEmailScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
         }
-        if (rp.getScopes().contains(OIDCScope.PHONE)) {
+        if (rp.getScopes().contains(OIDCScope.phone)) {
             
customClaims.removeAll(OidcPhoneScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
         }
+
         if (!customClaims.isEmpty()) {
-            List<String> supportedClaims = 
properties.getAuthn().getOidc().getDiscovery().getClaims();
-            if (!supportedClaims.containsAll(customClaims)) {
-                properties.getAuthn().getOidc().getDiscovery().setClaims(
-                        Stream.concat(supportedClaims.stream(), 
customClaims.stream()).
-                                distinct().collect(Collectors.toList()));
-            }
+            service.getScopes().add(CUSTOM_SCOPE);
 
             chain.addPolicies(new OidcCustomScopeAttributeReleasePolicy(
                     CUSTOM_SCOPE, 
customClaims.stream().collect(Collectors.toList())));
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java
index c7e8ca34e9..536147167e 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/RegisteredServiceMapper.java
@@ -23,9 +23,9 @@ import java.util.Optional;
 import org.apache.syncope.common.lib.policy.AttrReleasePolicyTO;
 import org.apache.syncope.common.lib.policy.DefaultAttrReleasePolicyConf;
 import org.apache.syncope.common.lib.wa.WAClientApp;
+import org.apache.syncope.wa.bootstrap.mapping.AttrReleaseMapper;
 import org.apereo.cas.authentication.AuthenticationEventExecutionPlan;
 import org.apereo.cas.authentication.MultifactorAuthenticationProvider;
-import org.apereo.cas.configuration.CasConfigurationProperties;
 import org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy;
 import org.apereo.cas.services.RegisteredService;
 import org.apereo.cas.services.RegisteredServiceAccessStrategy;
@@ -43,7 +43,7 @@ import org.springframework.beans.factory.ObjectProvider;
 
 public class RegisteredServiceMapper {
 
-    private static final Logger LOG = 
LoggerFactory.getLogger(RegisteredServiceMapper.class);
+    protected static final Logger LOG = 
LoggerFactory.getLogger(RegisteredServiceMapper.class);
 
     protected final String pac4jCoreName;
 
@@ -61,8 +61,6 @@ public class RegisteredServiceMapper {
 
     protected final List<ClientAppMapper> clientAppMappers;
 
-    protected final CasConfigurationProperties properties;
-
     public RegisteredServiceMapper(
             final String pac4jCoreName,
             final ObjectProvider<AuthenticationEventExecutionPlan> 
authEventExecPlan,
@@ -71,8 +69,7 @@ public class RegisteredServiceMapper {
             final List<AccessMapper> accessMappers,
             final List<AttrReleaseMapper> attrReleaseMappers,
             final List<TicketExpirationMapper> ticketExpirationMappers,
-            final List<ClientAppMapper> clientAppMappers,
-            final CasConfigurationProperties properties) {
+            final List<ClientAppMapper> clientAppMappers) {
 
         this.pac4jCoreName = pac4jCoreName;
         this.authEventExecPlan = authEventExecPlan;
@@ -82,19 +79,20 @@ public class RegisteredServiceMapper {
         this.attrReleaseMappers = attrReleaseMappers;
         this.ticketExpirationMappers = ticketExpirationMappers;
         this.clientAppMappers = clientAppMappers;
-        this.properties = properties;
     }
 
     public RegisteredService toRegisteredService(final WAClientApp clientApp) {
-        ClientAppMapper clientAppMapper = clientAppMappers.stream().
+        return clientAppMappers.stream().
                 filter(m -> m.supports(clientApp.getClientAppTO())).
                 findFirst().
-                orElse(null);
-        if (clientAppMapper == null) {
-            LOG.warn("Unable to locate ClientAppMapper for {}", 
clientApp.getClientAppTO().getClass().getName());
-            return null;
-        }
+                map(clientAppMapper -> toRegisteredService(clientApp, 
clientAppMapper)).
+                orElseGet(() -> {
+                    LOG.warn("Unable to locate mapper for {}", 
clientApp.getClientAppTO().getClass().getName());
+                    return null;
+                });
+    }
 
+    public RegisteredService toRegisteredService(final WAClientApp clientApp, 
final ClientAppMapper clientAppMapper) {
         RegisteredServiceAuthenticationPolicy authPolicy = null;
         RegisteredServiceMultifactorPolicy mfaPolicy = null;
         RegisteredServiceDelegatedAuthenticationPolicy delegatedAuthPolicy = 
null;
@@ -168,7 +166,6 @@ public class RegisteredServiceMapper {
                 tgtExpirationPolicy,
                 stExpirationPolicy,
                 tgtProxyExpirationPolicy,
-                stProxyExpirationPolicy,
-                properties);
+                stProxyExpirationPolicy);
     }
 }
diff --git 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java
 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java
index 4510592800..97cec97d6f 100644
--- 
a/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java
+++ 
b/wa/starter/src/main/java/org/apache/syncope/wa/starter/mapping/SAML2SPClientAppTOMapper.java
@@ -23,7 +23,6 @@ import java.util.stream.Collectors;
 import org.apache.syncope.common.lib.to.ClientAppTO;
 import org.apache.syncope.common.lib.to.SAML2SPClientAppTO;
 import org.apache.syncope.common.lib.wa.WAClientApp;
-import org.apereo.cas.configuration.CasConfigurationProperties;
 import org.apereo.cas.services.RegisteredService;
 import org.apereo.cas.services.RegisteredServiceAccessStrategy;
 import org.apereo.cas.services.RegisteredServiceAttributeReleasePolicy;
@@ -53,8 +52,7 @@ public class SAML2SPClientAppTOMapper extends 
AbstractClientAppMapper {
             final RegisteredServiceTicketGrantingTicketExpirationPolicy 
tgtExpirationPolicy,
             final RegisteredServiceServiceTicketExpirationPolicy 
stExpirationPolicy,
             final RegisteredServiceProxyGrantingTicketExpirationPolicy 
tgtProxyExpirationPolicy,
-            final RegisteredServiceProxyTicketExpirationPolicy 
stProxyExpirationPolicy,
-            final CasConfigurationProperties properties) {
+            final RegisteredServiceProxyTicketExpirationPolicy 
stProxyExpirationPolicy) {
 
         SAML2SPClientAppTO sp = 
SAML2SPClientAppTO.class.cast(clientApp.getClientAppTO());
         SamlRegisteredService service = new SamlRegisteredService();
diff --git a/wa/starter/src/main/resources/wa.properties 
b/wa/starter/src/main/resources/wa.properties
index a0e0b6a38c..48593af3d8 100644
--- a/wa/starter/src/main/resources/wa.properties
+++ b/wa/starter/src/main/resources/wa.properties
@@ -82,6 +82,7 @@ 
cas.authn.saml-idp.metadata.http.metadata-backup-location=file:${syncope.conf.di
 cas.authn.oidc.core.issuer=${cas.server.prefix}/oidc
 
cas.authn.oidc.discovery.id-token-signing-alg-values-supported=RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512,HS256,HS384,HS512
 
cas.authn.oidc.discovery.user-info-signing-alg-values-supported=RS256,RS384,RS512,PS256,PS384,PS512,ES256,ES384,ES512,HS256,HS384,HS512
+cas.authn.oidc.discovery.scopes=openid,profile,email,address,phone,syncope
 cas.authn.oauth.core.user-profile-view-type=FLAT
 
 # Disable access to the login endpoint

Reply via email to