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