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

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


The following commit(s) were added to refs/heads/master by this push:
     new 4268571d17 [SYNCOPE-1771] Adding support for delegated auth via 
Google, Keycloak and Apple ID
4268571d17 is described below

commit 4268571d172d3bb936cdfa79f93a70cd5d3df111
Author: Francesco Chicchiriccò <ilgro...@users.noreply.github.com>
AuthorDate: Fri Jul 21 14:17:46 2023 +0200

    [SYNCOPE-1771] Adding support for delegated auth via Google, Keycloak and 
Apple ID
---
 .../common/lib/auth/AppleOIDCAuthModuleConf.java   |  88 ++++++++++++++
 .../syncope/common/lib/auth/AuthModuleConf.java    |  14 ++-
 ...oduleConf.java => AzureOIDCAuthModuleConf.java} |   3 +-
 ...duleConf.java => GoogleOIDCAuthModuleConf.java} |  21 +---
 ...leConf.java => KeycloakOIDCAuthModuleConf.java} |  33 +++--
 .../bootstrap/AuthModulePropertySourceMapper.java  | 134 ++++++++++++++-------
 6 files changed, 209 insertions(+), 84 deletions(-)

diff --git 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AppleOIDCAuthModuleConf.java
 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AppleOIDCAuthModuleConf.java
new file mode 100644
index 0000000000..cc1ce7a80d
--- /dev/null
+++ 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AppleOIDCAuthModuleConf.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.lib.auth;
+
+import java.util.Map;
+import org.apache.syncope.common.lib.to.AuthModuleTO;
+
+public class AppleOIDCAuthModuleConf extends AbstractOIDCAuthModuleConf 
implements AuthModuleConf {
+
+    private static final long serialVersionUID = -471527731042579522L;
+
+    /**
+     * Client secret expiration timeout.
+     * This settings supports the java.time.Duration syntax.
+     */
+    protected String timeout = "PT30S";
+
+    /**
+     * Apple team identifier.
+     * Usually, 10 character string given to you by Apple.
+     */
+    protected String teamId;
+
+    /**
+     * Private key obtained from Apple.
+     * Must point to a resource that resolved to an elliptic curve (EC) 
private key.
+     */
+    protected String privateKey;
+
+    /**
+     * The identifier for the private key.
+     * Usually the 10 character Key ID of the private key you create in Apple.
+     */
+    protected String privateKeyId;
+
+    public String getTimeout() {
+        return timeout;
+    }
+
+    public void setTimeout(final String timeout) {
+        this.timeout = timeout;
+    }
+
+    public String getPrivateKey() {
+        return privateKey;
+    }
+
+    public void setPrivateKey(final String privateKey) {
+        this.privateKey = privateKey;
+    }
+
+    public String getPrivateKeyId() {
+        return privateKeyId;
+    }
+
+    public void setPrivateKeyId(final String privateKeyId) {
+        this.privateKeyId = privateKeyId;
+    }
+
+    public String getTeamId() {
+        return teamId;
+    }
+
+    public void setTeamId(final String teamId) {
+        this.teamId = teamId;
+    }
+
+    @Override
+    public Map<String, Object> map(final AuthModuleTO authModule, final Mapper 
mapper) {
+        return mapper.map(authModule, this);
+    }
+}
diff --git 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AuthModuleConf.java
 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AuthModuleConf.java
index 2cca813cdf..8bc5a4fa6d 100644
--- 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AuthModuleConf.java
+++ 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AuthModuleConf.java
@@ -36,8 +36,18 @@ public interface AuthModuleConf extends BaseBean {
 
         Map<String, Object> map(AuthModuleTO authModule, JaasAuthModuleConf 
conf);
 
+        Map<String, Object> map(AuthModuleTO authModule, OAuth20AuthModuleConf 
conf);
+
         Map<String, Object> map(AuthModuleTO authModule, OIDCAuthModuleConf 
conf);
 
+        Map<String, Object> map(AuthModuleTO authModule, 
AzureOIDCAuthModuleConf conf);
+
+        Map<String, Object> map(AuthModuleTO authModule, 
GoogleOIDCAuthModuleConf conf);
+
+        Map<String, Object> map(AuthModuleTO authModule, 
KeycloakOIDCAuthModuleConf conf);
+
+        Map<String, Object> map(AuthModuleTO authModule, 
AppleOIDCAuthModuleConf conf);
+
         Map<String, Object> map(AuthModuleTO authModule, 
SAML2IdPAuthModuleConf conf);
 
         Map<String, Object> map(AuthModuleTO authModule, SyncopeAuthModuleConf 
conf);
@@ -49,10 +59,6 @@ public interface AuthModuleConf extends BaseBean {
         Map<String, Object> map(AuthModuleTO authModule, U2FAuthModuleConf 
conf);
 
         Map<String, Object> map(AuthModuleTO authModule, 
SimpleMfaAuthModuleConf conf);
-
-        Map<String, Object> map(AuthModuleTO authModule, OAuth20AuthModuleConf 
conf);
-
-        Map<String, Object> map(AuthModuleTO authModule, AzureAuthModuleConf 
conf);
     }
 
     Map<String, Object> map(AuthModuleTO authModule, Mapper mapper);
diff --git 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureAuthModuleConf.java
 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureOIDCAuthModuleConf.java
similarity index 94%
copy from 
common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureAuthModuleConf.java
copy to 
common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureOIDCAuthModuleConf.java
index c5cb26a85d..f1cd5b73f1 100644
--- 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureAuthModuleConf.java
+++ 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureOIDCAuthModuleConf.java
@@ -21,7 +21,7 @@ package org.apache.syncope.common.lib.auth;
 import java.util.Map;
 import org.apache.syncope.common.lib.to.AuthModuleTO;
 
-public class AzureAuthModuleConf extends AbstractOIDCAuthModuleConf implements 
AuthModuleConf {
+public class AzureOIDCAuthModuleConf extends AbstractOIDCAuthModuleConf 
implements AuthModuleConf {
 
     private static final long serialVersionUID = -471527731042579522L;
 
@@ -47,5 +47,4 @@ public class AzureAuthModuleConf extends 
AbstractOIDCAuthModuleConf implements A
     public Map<String, Object> map(final AuthModuleTO authModule, final Mapper 
mapper) {
         return mapper.map(authModule, this);
     }
-
 }
diff --git 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureAuthModuleConf.java
 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/GoogleOIDCAuthModuleConf.java
similarity index 61%
copy from 
common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureAuthModuleConf.java
copy to 
common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/GoogleOIDCAuthModuleConf.java
index c5cb26a85d..f848f450a7 100644
--- 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureAuthModuleConf.java
+++ 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/GoogleOIDCAuthModuleConf.java
@@ -21,31 +21,12 @@ package org.apache.syncope.common.lib.auth;
 import java.util.Map;
 import org.apache.syncope.common.lib.to.AuthModuleTO;
 
-public class AzureAuthModuleConf extends AbstractOIDCAuthModuleConf implements 
AuthModuleConf {
+public class GoogleOIDCAuthModuleConf extends AbstractOIDCAuthModuleConf 
implements AuthModuleConf {
 
     private static final long serialVersionUID = -471527731042579522L;
 
-    /**
-     * Azure AD tenant name. After tenant is configured, #getDiscoveryUri() 
property will be overridden.
-     *
-     * Azure AD tenant name can take 4 different values:
-     * - organizations: Only users with work or school accounts from Azure AD 
can sign in.
-     * - consumers: Only users with a personal Microsoft account can sign in.
-     * - Specific tenant domain name or ID: Only user with account under that 
the specified tenant can login
-     */
-    protected String tenant;
-
-    public String getTenant() {
-        return tenant;
-    }
-
-    public void setTenant(final String tenant) {
-        this.tenant = tenant;
-    }
-
     @Override
     public Map<String, Object> map(final AuthModuleTO authModule, final Mapper 
mapper) {
         return mapper.map(authModule, this);
     }
-
 }
diff --git 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureAuthModuleConf.java
 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/KeycloakOIDCAuthModuleConf.java
similarity index 62%
rename from 
common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureAuthModuleConf.java
rename to 
common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/KeycloakOIDCAuthModuleConf.java
index c5cb26a85d..a4f464c157 100644
--- 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AzureAuthModuleConf.java
+++ 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/KeycloakOIDCAuthModuleConf.java
@@ -21,31 +21,38 @@ package org.apache.syncope.common.lib.auth;
 import java.util.Map;
 import org.apache.syncope.common.lib.to.AuthModuleTO;
 
-public class AzureAuthModuleConf extends AbstractOIDCAuthModuleConf implements 
AuthModuleConf {
+public class KeycloakOIDCAuthModuleConf extends AbstractOIDCAuthModuleConf 
implements AuthModuleConf {
 
     private static final long serialVersionUID = -471527731042579522L;
 
     /**
-     * Azure AD tenant name. After tenant is configured, #getDiscoveryUri() 
property will be overridden.
-     *
-     * Azure AD tenant name can take 4 different values:
-     * - organizations: Only users with work or school accounts from Azure AD 
can sign in.
-     * - consumers: Only users with a personal Microsoft account can sign in.
-     * - Specific tenant domain name or ID: Only user with account under that 
the specified tenant can login
+     * Keycloak realm used to construct metadata discovery URI.
      */
-    protected String tenant;
+    protected String realm;
 
-    public String getTenant() {
-        return tenant;
+    /**
+     * Keycloak base URL used to construct metadata discovery URI.
+     */
+    protected String baseUri;
+
+    public String getRealm() {
+        return realm;
+    }
+
+    public void setRealm(final String realm) {
+        this.realm = realm;
+    }
+
+    public String getBaseUri() {
+        return baseUri;
     }
 
-    public void setTenant(final String tenant) {
-        this.tenant = tenant;
+    public void setBaseUri(final String baseUri) {
+        this.baseUri = baseUri;
     }
 
     @Override
     public Map<String, Object> map(final AuthModuleTO authModule, final Mapper 
mapper) {
         return mapper.map(authModule, this);
     }
-
 }
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/AuthModulePropertySourceMapper.java
index a40b63086e..0efbff13b5 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/AuthModulePropertySourceMapper.java
@@ -25,12 +25,16 @@ import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.auth.AbstractOIDCAuthModuleConf;
+import org.apache.syncope.common.lib.auth.AppleOIDCAuthModuleConf;
 import org.apache.syncope.common.lib.auth.AuthModuleConf;
-import org.apache.syncope.common.lib.auth.AzureAuthModuleConf;
+import org.apache.syncope.common.lib.auth.AzureOIDCAuthModuleConf;
 import org.apache.syncope.common.lib.auth.DuoMfaAuthModuleConf;
 import org.apache.syncope.common.lib.auth.GoogleMfaAuthModuleConf;
+import org.apache.syncope.common.lib.auth.GoogleOIDCAuthModuleConf;
 import org.apache.syncope.common.lib.auth.JDBCAuthModuleConf;
 import org.apache.syncope.common.lib.auth.JaasAuthModuleConf;
+import org.apache.syncope.common.lib.auth.KeycloakOIDCAuthModuleConf;
 import org.apache.syncope.common.lib.auth.LDAPAuthModuleConf;
 import org.apache.syncope.common.lib.auth.OAuth20AuthModuleConf;
 import org.apache.syncope.common.lib.auth.OIDCAuthModuleConf;
@@ -56,8 +60,12 @@ import 
org.apereo.cas.configuration.model.support.mfa.gauth.LdapGoogleAuthentica
 import 
org.apereo.cas.configuration.model.support.mfa.simple.CasSimpleMultifactorAuthenticationProperties;
 import 
org.apereo.cas.configuration.model.support.mfa.u2f.U2FMultifactorAuthenticationProperties;
 import 
org.apereo.cas.configuration.model.support.pac4j.oauth.Pac4jOAuth20ClientProperties;
+import 
org.apereo.cas.configuration.model.support.pac4j.oidc.BasePac4jOidcClientProperties;
+import 
org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jAppleOidcClientProperties;
 import 
org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jAzureOidcClientProperties;
 import 
org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jGenericOidcClientProperties;
+import 
org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jGoogleOidcClientProperties;
+import 
org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jKeyCloakOidcClientProperties;
 import 
org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jOidcClientProperties;
 import 
org.apereo.cas.configuration.model.support.pac4j.saml.Pac4jSamlClientProperties;
 import 
org.apereo.cas.configuration.model.support.syncope.SyncopeAuthenticationProperties;
@@ -149,8 +157,32 @@ public class AuthModulePropertySourceMapper extends 
PropertySourceMapper impleme
     }
 
     @Override
-    public Map<String, Object> map(final AuthModuleTO authModuleTO, final 
OIDCAuthModuleConf conf) {
-        Pac4jGenericOidcClientProperties props = new 
Pac4jGenericOidcClientProperties();
+    public Map<String, Object> map(final AuthModuleTO authModuleTO, final 
OAuth20AuthModuleConf conf) {
+        Pac4jOAuth20ClientProperties props = new 
Pac4jOAuth20ClientProperties();
+        props.setId(conf.getClientId());
+        props.setSecret(conf.getClientSecret());
+        
props.setClientName(Optional.ofNullable(conf.getClientName()).orElse(authModuleTO.getKey()));
+        props.setEnabled(authModuleTO.getState() == AuthModuleState.ACTIVE);
+        props.setCustomParams(conf.getCustomParams());
+        props.setAuthUrl(conf.getAuthUrl());
+        props.setProfileVerb(conf.getProfileVerb());
+        props.setProfileUrl(conf.getProfileUrl());
+        props.setTokenUrl(conf.getTokenUrl());
+        props.setResponseType(conf.getResponseType());
+        props.setScope(conf.getScope());
+        props.setPrincipalIdAttribute(conf.getUserIdAttribute());
+        props.setWithState(conf.isWithState());
+        props.setProfileAttrs(authModuleTO.getItems().stream().
+                collect(Collectors.toMap(Item::getIntAttrName, 
Item::getExtAttrName)));
+
+        return prefix("cas.authn.pac4j.oauth2[].", 
CasCoreConfigurationUtils.asMap(props));
+    }
+
+    protected void map(
+            final AuthModuleTO authModuleTO,
+            final BasePac4jOidcClientProperties props,
+            final AbstractOIDCAuthModuleConf conf) {
+
         props.setId(conf.getClientId());
         props.setSecret(conf.getClientSecret());
         
props.setClientName(Optional.ofNullable(conf.getClientName()).orElse(authModuleTO.getKey()));
@@ -165,6 +197,13 @@ public class AuthModulePropertySourceMapper extends 
PropertySourceMapper impleme
         props.setPrincipalIdAttribute(conf.getUserIdAttribute());
         props.setExpireSessionWithToken(conf.isExpireSessionWithToken());
         props.setTokenExpirationAdvance(conf.getTokenExpirationAdvance());
+    }
+
+    @Override
+    public Map<String, Object> map(final AuthModuleTO authModuleTO, final 
OIDCAuthModuleConf conf) {
+        Pac4jGenericOidcClientProperties props = new 
Pac4jGenericOidcClientProperties();
+        map(authModuleTO, props, conf);
+
         Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
         client.setGeneric(props);
 
@@ -172,25 +211,54 @@ public class AuthModulePropertySourceMapper extends 
PropertySourceMapper impleme
     }
 
     @Override
-    public Map<String, Object> map(final AuthModuleTO authModuleTO, final 
OAuth20AuthModuleConf conf) {
-        Pac4jOAuth20ClientProperties props = new 
Pac4jOAuth20ClientProperties();
-        props.setId(conf.getClientId());
-        props.setSecret(conf.getClientSecret());
-        
props.setClientName(Optional.ofNullable(conf.getClientName()).orElse(authModuleTO.getKey()));
-        props.setEnabled(authModuleTO.getState() == AuthModuleState.ACTIVE);
-        props.setCustomParams(conf.getCustomParams());
-        props.setAuthUrl(conf.getAuthUrl());
-        props.setProfileVerb(conf.getProfileVerb());
-        props.setProfileUrl(conf.getProfileUrl());
-        props.setTokenUrl(conf.getTokenUrl());
-        props.setResponseType(conf.getResponseType());
-        props.setScope(conf.getScope());
-        props.setPrincipalIdAttribute(conf.getUserIdAttribute());
-        props.setWithState(conf.isWithState());
-        props.setProfileAttrs(authModuleTO.getItems().stream().
-                collect(Collectors.toMap(Item::getIntAttrName, 
Item::getExtAttrName)));
+    public Map<String, Object> map(final AuthModuleTO authModuleTO, final 
AzureOIDCAuthModuleConf conf) {
+        Pac4jAzureOidcClientProperties props = new 
Pac4jAzureOidcClientProperties();
+        map(authModuleTO, props, conf);
+        props.setTenant(conf.getTenant());
 
-        return prefix("cas.authn.pac4j.oauth2[].", 
CasCoreConfigurationUtils.asMap(props));
+        Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
+        client.setAzure(props);
+
+        return prefix("cas.authn.pac4j.oidc[].azure.", 
CasCoreConfigurationUtils.asMap(props));
+    }
+
+    @Override
+    public Map<String, Object> map(final AuthModuleTO authModuleTO, final 
GoogleOIDCAuthModuleConf conf) {
+        Pac4jGoogleOidcClientProperties props = new 
Pac4jGoogleOidcClientProperties();
+        map(authModuleTO, props, conf);
+
+        Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
+        client.setGoogle(props);
+
+        return prefix("cas.authn.pac4j.oidc[].google.", 
CasCoreConfigurationUtils.asMap(props));
+    }
+
+    @Override
+    public Map<String, Object> map(final AuthModuleTO authModuleTO, final 
KeycloakOIDCAuthModuleConf conf) {
+        Pac4jKeyCloakOidcClientProperties props = new 
Pac4jKeyCloakOidcClientProperties();
+        map(authModuleTO, props, conf);
+        props.setRealm(conf.getRealm());
+        props.setBaseUri(conf.getBaseUri());
+
+        Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
+        client.setKeycloak(props);
+
+        return prefix("cas.authn.pac4j.oidc[].keycloak.", 
CasCoreConfigurationUtils.asMap(props));
+    }
+
+    @Override
+    public Map<String, Object> map(final AuthModuleTO authModuleTO, final 
AppleOIDCAuthModuleConf conf) {
+        Pac4jAppleOidcClientProperties props = new 
Pac4jAppleOidcClientProperties();
+        map(authModuleTO, props, conf);
+        props.setTimeout(conf.getTimeout());
+        props.setPrivateKey(conf.getPrivateKey());
+        props.setPrivateKeyId(conf.getPrivateKeyId());
+        props.setTeamId(conf.getTeamId());
+
+        Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
+        client.setApple(props);
+
+        return prefix("cas.authn.pac4j.oidc[].apple.", 
CasCoreConfigurationUtils.asMap(props));
     }
 
     @Override
@@ -315,28 +383,4 @@ public class AuthModulePropertySourceMapper extends 
PropertySourceMapper impleme
 
         return prefix("cas.authn.mfa.simple.", 
CasCoreConfigurationUtils.asMap(props));
     }
-
-    @Override
-    public Map<String, Object> map(final AuthModuleTO authModuleTO, final 
AzureAuthModuleConf conf) {
-        Pac4jAzureOidcClientProperties props = new 
Pac4jAzureOidcClientProperties();
-        props.setId(conf.getClientId());
-        props.setSecret(conf.getClientSecret());
-        
props.setClientName(Optional.ofNullable(conf.getClientName()).orElse(authModuleTO.getKey()));
-        props.setEnabled(authModuleTO.getState() == AuthModuleState.ACTIVE);
-        props.setCustomParams(conf.getCustomParams());
-        props.setDiscoveryUri(conf.getDiscoveryUri());
-        props.setMaxClockSkew(conf.getMaxClockSkew());
-        props.setPreferredJwsAlgorithm(conf.getPreferredJwsAlgorithm());
-        props.setResponseMode(conf.getResponseMode());
-        props.setResponseType(conf.getResponseType());
-        props.setScope(conf.getScope());
-        props.setPrincipalIdAttribute(conf.getUserIdAttribute());
-        props.setExpireSessionWithToken(conf.isExpireSessionWithToken());
-        props.setTokenExpirationAdvance(conf.getTokenExpirationAdvance());
-        props.setTenant(conf.getTenant());
-        Pac4jOidcClientProperties client = new Pac4jOidcClientProperties();
-        client.setAzure(props);
-
-        return prefix("cas.authn.pac4j.oidc[].azure.", 
CasCoreConfigurationUtils.asMap(props));
-    }
 }

Reply via email to