You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2023/03/10 13:26:43 UTC
[syncope] branch 3_0_X updated: WA: better scope management for OIDC RP client application (#423)
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 32df251f21 WA: better scope management for OIDC RP client application (#423)
32df251f21 is described below
commit 32df251f211bbfa1f06cd5ed51cd6b8411851504
Author: Francesco Chicchiriccò <il...@users.noreply.github.com>
AuthorDate: Fri Mar 10 14:26:37 2023 +0100
WA: better scope management for OIDC RP client application (#423)
---
.../clientapps/ClientAppModalPanelBuilder.java | 4 +-
.../syncope/common/lib/to/OIDCRPClientAppTO.java | 19 +++++
.../syncope/common/lib/types/OIDCGrantType.java | 3 +-
.../syncope/common/lib/types/OIDCResponseType.java | 4 +-
pom.xml | 2 +-
.../starter/mapping/OIDCRPClientAppTOMapper.java | 82 ++++++++++++++--------
6 files changed, 77 insertions(+), 37 deletions(-)
diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/ClientAppModalPanelBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/ClientAppModalPanelBuilder.java
index 3ce93ab3b9..d4515ae480 100644
--- a/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/ClientAppModalPanelBuilder.java
+++ b/client/am/console/src/main/java/org/apache/syncope/client/console/clientapps/ClientAppModalPanelBuilder.java
@@ -180,7 +180,7 @@ public class ClientAppModalPanelBuilder<T extends ClientAppTO> extends AbstractM
fields.add(new AjaxTextFieldPanel(
"field", Constants.DESCRIPTION_FIELD_NAME,
new PropertyModel<>(clientAppTO, Constants.DESCRIPTION_FIELD_NAME), false));
-
+
fields.add(new AjaxTextFieldPanel(
"field", "logo",
new PropertyModel<>(clientAppTO, "logo"), false));
@@ -252,7 +252,6 @@ public class ClientAppModalPanelBuilder<T extends ClientAppTO> extends AbstractM
fields.add(subjectType);
AjaxTextFieldPanel redirectUri = new AjaxTextFieldPanel("panel", "redirectUris", new Model<>());
- redirectUri.addValidator(new UrlValidator());
fields.add(new MultiFieldPanel.Builder<String>(
new PropertyModel<>(clientAppTO, "redirectUris")).build(
"field",
@@ -278,7 +277,6 @@ public class ClientAppModalPanelBuilder<T extends ClientAppTO> extends AbstractM
case SAML2SP:
AjaxTextFieldPanel entityId = new AjaxTextFieldPanel(
"field", "entityId", new PropertyModel<>(clientAppTO, "entityId"), false);
- entityId.addValidator(new UrlValidator());
fields.add(entityId.setRequired(true));
fields.add(new AjaxTextFieldPanel("field", "metadataLocation",
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/OIDCRPClientAppTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/OIDCRPClientAppTO.java
index a40eae7aac..480ff8edc4 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/OIDCRPClientAppTO.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/OIDCRPClientAppTO.java
@@ -35,6 +35,15 @@ public class OIDCRPClientAppTO extends ClientAppTO {
private static final long serialVersionUID = -6370888503924521351L;
+ public enum SCOPE {
+ OPENID,
+ PROFILE,
+ EMAIL,
+ ADDRESS,
+ PHONE
+
+ }
+
private String clientId;
private String clientSecret;
@@ -53,6 +62,8 @@ public class OIDCRPClientAppTO extends ClientAppTO {
private String logoutUri;
+ private final List<SCOPE> scopes = new ArrayList<>();
+
private boolean bypassApprovalPrompt = true;
@JacksonXmlProperty(localName = "_class", isAttribute = true)
@@ -130,6 +141,12 @@ public class OIDCRPClientAppTO extends ClientAppTO {
this.jwtAccessToken = jwtAccessToken;
}
+ @JacksonXmlElementWrapper(localName = "scopes")
+ @JacksonXmlProperty(localName = "scope")
+ public List<SCOPE> getScopes() {
+ return scopes;
+ }
+
public boolean isBypassApprovalPrompt() {
return bypassApprovalPrompt;
}
@@ -161,6 +178,7 @@ public class OIDCRPClientAppTO extends ClientAppTO {
.append(this.supportedResponseTypes, rhs.supportedResponseTypes)
.append(this.logoutUri, rhs.logoutUri)
.append(this.jwtAccessToken, rhs.jwtAccessToken)
+ .append(this.scopes, rhs.scopes)
.append(this.bypassApprovalPrompt, rhs.bypassApprovalPrompt)
.isEquals();
}
@@ -178,6 +196,7 @@ public class OIDCRPClientAppTO extends ClientAppTO {
.append(supportedResponseTypes)
.append(logoutUri)
.append(jwtAccessToken)
+ .append(scopes)
.append(bypassApprovalPrompt)
.toHashCode();
}
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCGrantType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCGrantType.java
index c1471b1010..837f80ec3d 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCGrantType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCGrantType.java
@@ -22,6 +22,7 @@ public enum OIDCGrantType {
authorization_code,
password,
client_credentials,
- refresh_token;
+ refresh_token,
+ device_code;
}
diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCResponseType.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCResponseType.java
index 2ccffa9c21..7e2b8cb90f 100644
--- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCResponseType.java
+++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/OIDCResponseType.java
@@ -21,7 +21,9 @@ package org.apache.syncope.common.lib.types;
public enum OIDCResponseType {
CODE("code"),
TOKEN("token"),
- ID_TOKEN_TOKEN("id_token token");
+ ID_TOKEN("id_token"),
+ ID_TOKEN_TOKEN("id_token token"),
+ DEVICE_CODE("device_code");
private final String externalForm;
diff --git a/pom.xml b/pom.xml
index b896c9cd44..4d9ba1432e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1737,7 +1737,7 @@ under the License.
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
- <version>10.8.0</version>
+ <version>10.8.1</version>
</dependency>
</dependencies>
<configuration>
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 290e9762c5..884cd5243c 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
@@ -32,6 +32,7 @@ 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;
+import org.apereo.cas.oidc.claims.OidcOpenIdScopeAttributeReleasePolicy;
import org.apereo.cas.oidc.claims.OidcPhoneScopeAttributeReleasePolicy;
import org.apereo.cas.oidc.claims.OidcProfileScopeAttributeReleasePolicy;
import org.apereo.cas.services.BaseMappedAttributeReleasePolicy;
@@ -91,43 +92,62 @@ public class OIDCRPClientAppTOMapper extends AbstractClientAppMapper {
if (attributeReleasePolicy != null) {
chain.addPolicies(attributeReleasePolicy);
}
+ }
- chain.addPolicies(new OidcProfileScopeAttributeReleasePolicy(),
- new OidcEmailScopeAttributeReleasePolicy(),
- new OidcAddressScopeAttributeReleasePolicy(),
- new OidcPhoneScopeAttributeReleasePolicy());
+ if (rp.getScopes().contains(OIDCRPClientAppTO.SCOPE.OPENID)) {
+ chain.addPolicies(new OidcOpenIdScopeAttributeReleasePolicy());
+ }
+ if (rp.getScopes().contains(OIDCRPClientAppTO.SCOPE.PROFILE)) {
+ chain.addPolicies(new OidcProfileScopeAttributeReleasePolicy());
+ }
+ if (rp.getScopes().contains(OIDCRPClientAppTO.SCOPE.ADDRESS)) {
+ chain.addPolicies(new OidcAddressScopeAttributeReleasePolicy());
+ }
+ if (rp.getScopes().contains(OIDCRPClientAppTO.SCOPE.EMAIL)) {
+ chain.addPolicies(new OidcEmailScopeAttributeReleasePolicy());
+ }
+ if (rp.getScopes().contains(OIDCRPClientAppTO.SCOPE.PHONE)) {
+ chain.addPolicies(new OidcPhoneScopeAttributeReleasePolicy());
+ }
- Set<String> customClaims = new HashSet<>();
- if (attributeReleasePolicy instanceof BaseMappedAttributeReleasePolicy) {
- customClaims.addAll(((BaseMappedAttributeReleasePolicy) attributeReleasePolicy).
- getAllowedAttributes().values().stream().
- map(Objects::toString).collect(Collectors.toSet()));
- } else if (attributeReleasePolicy instanceof ReturnAllowedAttributeReleasePolicy) {
- customClaims.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(customClaims::addAll);
- }
+ Set<String> customClaims = new HashSet<>();
+ if (attributeReleasePolicy instanceof BaseMappedAttributeReleasePolicy) {
+ customClaims.addAll(((BaseMappedAttributeReleasePolicy) attributeReleasePolicy).
+ getAllowedAttributes().values().stream().
+ map(Objects::toString).collect(Collectors.toSet()));
+ } else if (attributeReleasePolicy instanceof ReturnAllowedAttributeReleasePolicy) {
+ customClaims.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(customClaims::addAll);
+ }
+ if (rp.getScopes().contains(OIDCRPClientAppTO.SCOPE.PROFILE)) {
customClaims.removeAll(OidcProfileScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
- customClaims.removeAll(OidcEmailScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
+ }
+ if (rp.getScopes().contains(OIDCRPClientAppTO.SCOPE.ADDRESS)) {
customClaims.removeAll(OidcAddressScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
+ }
+ if (rp.getScopes().contains(OIDCRPClientAppTO.SCOPE.EMAIL)) {
+ customClaims.removeAll(OidcEmailScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
+ }
+ if (rp.getScopes().contains(OIDCRPClientAppTO.SCOPE.PHONE)) {
customClaims.removeAll(OidcPhoneScopeAttributeReleasePolicy.ALLOWED_CLAIMS);
- if (!customClaims.isEmpty()) {
- CasConfigurationProperties properties = ctx.getBean(CasConfigurationProperties.class);
- 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()));
- }
-
- chain.addPolicies(new OidcCustomScopeAttributeReleasePolicy(
- CUSTOM_SCOPE, customClaims.stream().collect(Collectors.toList())));
+ }
+ if (!customClaims.isEmpty()) {
+ CasConfigurationProperties properties = ctx.getBean(CasConfigurationProperties.class);
+ 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()));
}
+
+ chain.addPolicies(new OidcCustomScopeAttributeReleasePolicy(
+ CUSTOM_SCOPE, customClaims.stream().collect(Collectors.toList())));
}
setPolicies(service, authPolicy, mfaPolicy, accessStrategy, chain);