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

mdisabatino 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 54f0304156 [SYNCOPE-1733] Added OAuth20 AuthModule (#414)
54f0304156 is described below

commit 54f030415641f46ee4c92e3e4c61d62a644ea03f
Author: mdisabatino <mdisabat...@apache.org>
AuthorDate: Fri Feb 24 13:32:43 2023 +0100

    [SYNCOPE-1733] Added OAuth20 AuthModule (#414)
    
    * [SYNCOPE-1733] Added OAuth20 AuthModule
    
    * [SYNCOPE-1733] Fix code scanning
    
    * [SYNCOPE-1733] Fix code scanning
---
 .../lib/auth/AbstractOIDCAuthModuleConf.java       | 121 +++++++++++++++++++++
 .../syncope/common/lib/auth/AuthModuleConf.java    |   2 +
 .../common/lib/auth/OAuth20AuthModuleConf.java     |  93 ++++++++++++++++
 .../common/lib/auth/OIDCAuthModuleConf.java        |  78 +------------
 .../src/test/resources/domains/MasterContent.xml   |   3 +
 .../src/test/resources/domains/MasterContent.xml   |   2 +
 .../apache/syncope/fit/core/AuthModuleITCase.java  |  59 +++++++++-
 .../bootstrap/AuthModulePropertySourceMapper.java  |  23 ++++
 .../AuthModulePropertySourceMapperTest.java        |  28 +++++
 9 files changed, 331 insertions(+), 78 deletions(-)

diff --git 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AbstractOIDCAuthModuleConf.java
 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AbstractOIDCAuthModuleConf.java
new file mode 100644
index 0000000000..9d4b577437
--- /dev/null
+++ 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/AbstractOIDCAuthModuleConf.java
@@ -0,0 +1,121 @@
+/*
+ * 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.LinkedHashMap;
+import java.util.Map;
+
+public abstract class AbstractOIDCAuthModuleConf extends Pac4jAuthModuleConf {
+    
+    protected String clientId;
+
+    protected String clientSecret;
+
+    protected String clientName;
+
+    protected boolean enabled;
+    
+    protected Map<String, String> customParams = new LinkedHashMap<>();
+
+    protected String tokenUrl;
+
+    protected String responseType = "code";
+
+    protected String scope;
+
+    protected String userIdAttribute;
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public void setId(final String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getClientSecret() {
+        return clientSecret;
+    }
+
+    public void setClientSecret(final String clientSecret) {
+        this.clientSecret = clientSecret;
+    }
+
+    @Override
+    public String getClientName() {
+        return clientName;
+    }
+
+    @Override
+    public void setClientName(final String clientName) {
+        this.clientName = clientName;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(final boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public Map<String, String> getCustomParams() {
+        return customParams;
+    }
+
+    public void setCustomParams(final Map<String, String> customParams) {
+        this.customParams = customParams;
+    }
+
+    public String getTokenUrl() {
+        return tokenUrl;
+    }
+
+    public void setTokenUrl(final String tokenUrl) {
+        this.tokenUrl = tokenUrl;
+    }
+
+    public String getResponseType() {
+        return responseType;
+    }
+
+    public void setResponseType(final String responseType) {
+        this.responseType = responseType;
+    }
+
+    public String getScope() {
+        return scope;
+    }
+
+    public void setScope(final String scope) {
+        this.scope = scope;
+    }
+
+    public void setClientId(final String clientId) {
+        this.clientId = clientId;
+    }
+
+    public String getUserIdAttribute() {
+        return userIdAttribute;
+    }
+
+    public void setUserIdAttribute(final String userIdAttribute) {
+        this.userIdAttribute = userIdAttribute;
+    }
+}
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 bb08dc9c14..c41588b85d 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
@@ -49,6 +49,8 @@ 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, Mapper mapper);
diff --git 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/OAuth20AuthModuleConf.java
 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/OAuth20AuthModuleConf.java
new file mode 100644
index 0000000000..097016a995
--- /dev/null
+++ 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/OAuth20AuthModuleConf.java
@@ -0,0 +1,93 @@
+/*
+ * 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.LinkedHashMap;
+import java.util.Map;
+import org.apache.syncope.common.lib.to.AuthModuleTO;
+
+public class OAuth20AuthModuleConf extends AbstractOIDCAuthModuleConf 
implements AuthModuleConf {
+
+    private static final long serialVersionUID = 299820485764241682L;
+
+    protected String authUrl;
+    
+    protected String profileUrl;
+    
+    protected Map<String, String> profileAttrs = new LinkedHashMap<>();
+
+    protected boolean withState;
+
+    protected String profilePath;
+
+    protected String profileVerb = "POST";
+
+    public String getAuthUrl() {
+        return authUrl;
+    }
+
+    public void setAuthUrl(final String authUrl) {
+        this.authUrl = authUrl;
+    }
+
+    public Map<String, String> getProfileAttrs() {
+        return profileAttrs;
+    }
+
+    public void setProfileAttrs(final Map<String, String> profileAttrs) {
+        this.profileAttrs = profileAttrs;
+    }
+
+    public boolean isWithState() {
+        return withState;
+    }
+
+    public void setWithState(final boolean withState) {
+        this.withState = withState;
+    }
+
+    public String getProfilePath() {
+        return profilePath;
+    }
+
+    public void setProfilePath(final String profilePath) {
+        this.profilePath = profilePath;
+    }
+
+    public String getProfileUrl() {
+        return profileUrl;
+    }
+
+    public void setProfileUrl(final String profileUrl) {
+        this.profileUrl = profileUrl;
+    }
+
+    public String getProfileVerb() {
+        return profileVerb;
+    }
+
+    public void setProfileVerb(final String profileVerb) {
+        this.profileVerb = profileVerb;
+    }
+
+    @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/OIDCAuthModuleConf.java
 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/OIDCAuthModuleConf.java
index b4899dec51..1419e87730 100644
--- 
a/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/OIDCAuthModuleConf.java
+++ 
b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/OIDCAuthModuleConf.java
@@ -18,29 +18,13 @@
  */
 package org.apache.syncope.common.lib.auth;
 
-import java.util.HashMap;
 import java.util.Map;
 import org.apache.syncope.common.lib.to.AuthModuleTO;
 
-public class OIDCAuthModuleConf extends Pac4jAuthModuleConf implements 
AuthModuleConf {
+public class OIDCAuthModuleConf extends AbstractOIDCAuthModuleConf implements 
AuthModuleConf {
 
     private static final long serialVersionUID = -471527731042579422L;
 
-    /**
-     * The client id.
-     */
-    protected String clientId;
-
-    /**
-     * The client secret.
-     */
-    protected String clientSecret;
-
-    /**
-     * The attribute value that should be used for the authenticated username, 
upon a successful authentication attempt.
-     */
-    protected String userIdAttribute;
-
     protected String discoveryUri;
 
     /**
@@ -49,11 +33,6 @@ public class OIDCAuthModuleConf extends Pac4jAuthModuleConf 
implements AuthModul
      */
     protected boolean useNonce;
 
-    /**
-     * Requested scope(s).
-     */
-    protected String scope;
-
     /**
      * The JWS algorithm to use forcefully when validating ID tokens.
      * If none is defined, the first algorithm from metadata will be used.
@@ -65,47 +44,12 @@ public class OIDCAuthModuleConf extends Pac4jAuthModuleConf 
implements AuthModul
      */
     protected String maxClockSkew;
 
-    /**
-     * Custom parameters to send along in authZ requests, etc.
-     */
-    protected final Map<String, String> customParams = new HashMap<>(0);
-
     /**
      * The response mode specifies how the result of the authorization request 
is formatted.
      * Possible values includes "query", "fragment", "form_post", or 
"web_message"
      */
     protected String responseMode;
 
-    /**
-     * The response type tells the authorization server which grant to execute.
-     * Possibles values includes "code", "token" or "id_token".
-     */
-    protected String responseType;
-
-    public String getClientId() {
-        return clientId;
-    }
-
-    public void setClientId(final String clientId) {
-        this.clientId = clientId;
-    }
-
-    public String getClientSecret() {
-        return clientSecret;
-    }
-
-    public void setClientSecret(final String clientSecret) {
-        this.clientSecret = clientSecret;
-    }
-
-    public String getUserIdAttribute() {
-        return userIdAttribute;
-    }
-
-    public void setUserIdAttribute(final String userIdAttribute) {
-        this.userIdAttribute = userIdAttribute;
-    }
-
     public String getDiscoveryUri() {
         return discoveryUri;
     }
@@ -122,14 +66,6 @@ public class OIDCAuthModuleConf extends Pac4jAuthModuleConf 
implements AuthModul
         this.useNonce = useNonce;
     }
 
-    public String getScope() {
-        return scope;
-    }
-
-    public void setScope(final String scope) {
-        this.scope = scope;
-    }
-
     public String getPreferredJwsAlgorithm() {
         return preferredJwsAlgorithm;
     }
@@ -146,10 +82,6 @@ public class OIDCAuthModuleConf extends Pac4jAuthModuleConf 
implements AuthModul
         this.maxClockSkew = maxClockSkew;
     }
 
-    public Map<String, String> getCustomParams() {
-        return customParams;
-    }
-
     public String getResponseMode() {
         return responseMode;
     }
@@ -158,14 +90,6 @@ public class OIDCAuthModuleConf extends Pac4jAuthModuleConf 
implements AuthModul
         this.responseMode = responseMode;
     }
 
-    public String getResponseType() {
-        return responseType;
-    }
-
-    public void setResponseType(final String responseType) {
-        this.responseType = responseType;
-    }
-
     @Override
     public Map<String, Object> map(final AuthModuleTO authModule, final Mapper 
mapper) {
         return mapper.map(authModule, this);
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 e2fba179a1..d778a528c7 100644
--- a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
@@ -87,6 +87,9 @@ under the License.
               
items='[{"intAttrName":"syncopeUserAttr_surname","extAttrName":"family_name","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAttrName":"syncopeUserAttr_fullname","extAttrName":"name","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAtt
 [...]
   <AuthModule id="DefaultU2FAuthModule" authModuleState="ACTIVE"
               description="U2F auth module" 
jsonConf='{"_class":"org.apache.syncope.common.lib.auth.U2FAuthModuleConf","expireDevices":40}'/>
+  <AuthModule id="DefaultOAuth20AuthModule" description="OAuth20 auth module" 
authModuleOrder="0" 
+              
jsonConf='{"_class":"org.apache.syncope.common.lib.auth.OAuth20AuthModuleConf","clientName":"oauth20","clientId":"OAUTH20","clientSecret":"secret","enabled":true,"customParams":{},"tokenUrl":"https://localhost/oauth2/token","responseType":"code","scope":"oauth
 
test","userIdAttribute":"username","authUrl":"https://localhost/oauth2/auth","profileUrl":"https://localhost/oauth2/profile","profileAttrs":{},"withState":false,"profilePath":null,"profileVerb":"POST"}'
 authModuleStat [...]
+
 
   <!-- Attribute repositories -->
   <AttrRepo id="DefaultLDAPAttrRepo" attrRepoState="ACTIVE"
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml 
b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index abfbc39271..f804bf8eda 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -87,6 +87,8 @@ under the License.
               
items='[{"intAttrName":"syncopeUserAttr_surname","extAttrName":"family_name","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAttrName":"syncopeUserAttr_fullname","extAttrName":"name","connObjectKey":false,"password":false,"mandatoryCondition":"false","purpose":"NONE","propagationJEXLTransformer":null,"pullJEXLTransformer":null,"transformers":[]},{"intAtt
 [...]
   <AuthModule id="DefaultU2FAuthModule" authModuleState="ACTIVE"
               description="U2F auth module" 
jsonConf='{"_class":"org.apache.syncope.common.lib.auth.U2FAuthModuleConf","expireDevices":40}'/>
+  <AuthModule id="DefaultOAuth20AuthModule" description="OAuth20 auth module" 
authModuleOrder="0"
+              
jsonConf='{"_class":"org.apache.syncope.common.lib.auth.OAuth20AuthModuleConf","clientName":"oauth20","clientId":"OAUTH20","clientSecret":"secret","enabled":true,"customParams":{},"tokenUrl":"https://localhost/oauth2/token","responseType":"code","scope":"oauth
 
test","userIdAttribute":"username","authUrl":"https://localhost/oauth2/auth","profileUrl":"https://localhost/oauth2/profile","profileAttrs":{},"withState":false,"profilePath":null,"profileVerb":"POST"}'
 authModuleStat [...]
 
   <!-- Attribute repositories -->
   <AttrRepo id="DefaultLDAPAttrRepo" attrRepoState="ACTIVE"
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthModuleITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthModuleITCase.java
index feac556db6..0785f8d3cb 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthModuleITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthModuleITCase.java
@@ -27,6 +27,7 @@ import static org.junit.jupiter.api.Assertions.fail;
 import java.io.IOException;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.ClassUtils;
@@ -39,6 +40,7 @@ import 
org.apache.syncope.common.lib.auth.GoogleMfaAuthModuleConf;
 import org.apache.syncope.common.lib.auth.JDBCAuthModuleConf;
 import org.apache.syncope.common.lib.auth.JaasAuthModuleConf;
 import org.apache.syncope.common.lib.auth.LDAPAuthModuleConf;
+import org.apache.syncope.common.lib.auth.OAuth20AuthModuleConf;
 import org.apache.syncope.common.lib.auth.OIDCAuthModuleConf;
 import org.apache.syncope.common.lib.auth.SAML2IdPAuthModuleConf;
 import org.apache.syncope.common.lib.auth.StaticAuthModuleConf;
@@ -62,7 +64,8 @@ public class AuthModuleITCase extends AbstractITCase {
         JAAS,
         JDBC,
         U2F,
-        OIDC;
+        OIDC,
+        OAUTH20;
 
     };
 
@@ -138,6 +141,24 @@ public class AuthModuleITCase extends AbstractITCase {
                 OIDCAuthModuleConf.class.cast(conf).setScope("openid email 
profile");
                 break;
 
+            case OAUTH20:
+                conf = new OAuth20AuthModuleConf();
+                
OAuth20AuthModuleConf.class.cast(conf).setClientId("OAUTH20TestId");
+                
OAuth20AuthModuleConf.class.cast(conf).setClientSecret("secret");
+                
OAuth20AuthModuleConf.class.cast(conf).setClientName("oauth20");
+                OAuth20AuthModuleConf.class.cast(conf).setEnabled(true);
+                
OAuth20AuthModuleConf.class.cast(conf).setCustomParams(Map.of("param1", 
"param1"));
+                
OAuth20AuthModuleConf.class.cast(conf).setAuthUrl("https://localhost/oauth2/auth";);
+                
OAuth20AuthModuleConf.class.cast(conf).setProfileAttrs(Map.of("uid", "id"));
+                
OAuth20AuthModuleConf.class.cast(conf).setProfileUrl("https://localhost/oauth2/profile";);
+                OAuth20AuthModuleConf.class.cast(conf).setProfilePath("/info");
+                
OAuth20AuthModuleConf.class.cast(conf).setTokenUrl("https://localhost/oauth2/token";);
+                OAuth20AuthModuleConf.class.cast(conf).setResponseType("code");
+                OAuth20AuthModuleConf.class.cast(conf).setScope("oauth test");
+                
OAuth20AuthModuleConf.class.cast(conf).setUserIdAttribute("username");
+                OAuth20AuthModuleConf.class.cast(conf).setWithState(true);
+                break;
+
             case SAML2_IDP:
                 conf = new SAML2IdPAuthModuleConf();
                 
SAML2IdPAuthModuleConf.class.cast(conf).setServiceProviderEntityId("testEntityId");
@@ -216,6 +237,9 @@ public class AuthModuleITCase extends AbstractITCase {
         assertTrue(authModuleTOs.stream().anyMatch(
                 authModule -> isSpecificConf(authModule.getConf(), 
U2FAuthModuleConf.class)
                 && authModule.getKey().equals("DefaultU2FAuthModule")));
+        assertTrue(authModuleTOs.stream().anyMatch(
+                authModule -> isSpecificConf(authModule.getConf(), 
OAuth20AuthModuleConf.class)
+                        && 
authModule.getKey().equals("DefaultOAuth20AuthModule")));
     }
 
     @Test
@@ -267,6 +291,16 @@ public class AuthModuleITCase extends AbstractITCase {
         assertFalse(isSpecificConf(authModuleTO.getConf(), 
SAML2IdPAuthModuleConf.class));
     }
 
+    @Test
+    public void getOAuth20AuthModule() {
+        AuthModuleTO authModuleTO = 
AUTH_MODULE_SERVICE.read("DefaultOAuth20AuthModule");
+
+        assertNotNull(authModuleTO);
+        assertTrue(StringUtils.isNotBlank(authModuleTO.getDescription()));
+        assertTrue(isSpecificConf(authModuleTO.getConf(), 
OAuth20AuthModuleConf.class));
+        assertFalse(isSpecificConf(authModuleTO.getConf(), 
SAML2IdPAuthModuleConf.class));
+    }
+
     @Test
     public void getSAML2IdPAuthModule() {
         AuthModuleTO authModuleTO = 
AUTH_MODULE_SERVICE.read("DefaultSAML2IdPAuthModule");
@@ -443,6 +477,29 @@ public class AuthModuleITCase extends AbstractITCase {
         assertEquals("newCode", 
OIDCAuthModuleConf.class.cast(conf).getResponseType());
     }
 
+    @Test
+    public void updateOAuth20AuthModule() {
+        AuthModuleTO oauth20AuthModuleTO = 
AUTH_MODULE_SERVICE.read("DefaultOAuth20AuthModule");
+        assertNotNull(oauth20AuthModuleTO);
+
+        AuthModuleTO newoauth20AuthModuleTO = 
buildAuthModuleTO(AuthModuleSupportedType.OAUTH20);
+        newoauth20AuthModuleTO = createAuthModule(newoauth20AuthModuleTO);
+        assertNotNull(newoauth20AuthModuleTO);
+
+        AuthModuleConf conf = oauth20AuthModuleTO.getConf();
+        assertNotNull(conf);
+        OAuth20AuthModuleConf.class.cast(conf).setClientName("OAUTH APP");
+        newoauth20AuthModuleTO.setConf(conf);
+
+        // update new auth module
+        AUTH_MODULE_SERVICE.update(newoauth20AuthModuleTO);
+        newoauth20AuthModuleTO = 
AUTH_MODULE_SERVICE.read(newoauth20AuthModuleTO.getKey());
+        assertNotNull(newoauth20AuthModuleTO);
+
+        conf = newoauth20AuthModuleTO.getConf();
+        assertEquals("OAUTH APP", 
OAuth20AuthModuleConf.class.cast(conf).getClientName());
+    }
+
     @Test
     public void updateJDBCAuthModule() {
         AuthModuleTO jdbcAuthModuleTO = 
AUTH_MODULE_SERVICE.read("DefaultJDBCAuthModule");
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 b14c7fe137..7f2e9886f0 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
@@ -30,6 +30,7 @@ import 
org.apache.syncope.common.lib.auth.GoogleMfaAuthModuleConf;
 import org.apache.syncope.common.lib.auth.JDBCAuthModuleConf;
 import org.apache.syncope.common.lib.auth.JaasAuthModuleConf;
 import org.apache.syncope.common.lib.auth.LDAPAuthModuleConf;
+import org.apache.syncope.common.lib.auth.OAuth20AuthModuleConf;
 import org.apache.syncope.common.lib.auth.OIDCAuthModuleConf;
 import org.apache.syncope.common.lib.auth.SAML2IdPAuthModuleConf;
 import org.apache.syncope.common.lib.auth.SimpleMfaAuthModuleConf;
@@ -50,6 +51,7 @@ import 
org.apereo.cas.configuration.model.support.mfa.gauth.GoogleAuthenticatorM
 import 
org.apereo.cas.configuration.model.support.mfa.gauth.LdapGoogleAuthenticatorMultifactorProperties;
 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.Pac4jGenericOidcClientProperties;
 import 
org.apereo.cas.configuration.model.support.pac4j.oidc.Pac4jOidcClientProperties;
 import 
org.apereo.cas.configuration.model.support.pac4j.saml.Pac4jSamlClientProperties;
@@ -147,6 +149,27 @@ public class AuthModulePropertySourceMapper extends 
PropertySourceMapper impleme
         return prefix("cas.authn.pac4j.oidc[].generic.", 
CasCoreConfigurationUtils.asMap(props));
     }
 
+    @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.setProfileAttrs(conf.getProfileAttrs());
+        props.setProfilePath(conf.getProfilePath());
+        props.setProfileUrl(conf.getProfileUrl());
+        props.setTokenUrl(conf.getTokenUrl());
+        props.setResponseType(conf.getResponseType());
+        props.setScope(conf.getScope());
+        props.setPrincipalAttributeId(conf.getUserIdAttribute());
+        props.setWithState(conf.isWithState());
+        
+        return prefix("cas.authn.pac4j.oauth2[].", 
CasCoreConfigurationUtils.asMap(props));
+    }
+
     @Override
     public Map<String, Object> map(final AuthModuleTO authModuleTO, final 
SAML2IdPAuthModuleConf conf) {
         Pac4jSamlClientProperties props = new Pac4jSamlClientProperties();
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 a5175ebe98..37d6165323 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
@@ -21,6 +21,7 @@ package org.apache.syncope.wa.bootstrap;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 
 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.junit.jupiter.api.Test;
@@ -46,4 +47,31 @@ public class AuthModulePropertySourceMapperTest {
         Map<String, Object> map = new 
AuthModulePropertySourceMapper(null).map(authModuleTO, conf);
         assertFalse(map.keySet().stream().anyMatch(k -> 
k.endsWith("defined")));
     }
+
+    @Test
+    public void mapOAuth20AuthModuleConf() {
+        AuthModuleTO authModuleTO = new AuthModuleTO();
+        authModuleTO.setKey("oauth20");
+        authModuleTO.setOrder(0);
+
+        OAuth20AuthModuleConf conf = new OAuth20AuthModuleConf();
+
+        conf.setClientId("1000");
+        conf.setClientSecret("secret");
+        conf.setClientName("oauth20");
+        conf.setEnabled(true);
+        conf.setCustomParams(Map.of("param1", "param1"));
+        conf.setAuthUrl("https://localhost/oauth2/auth";);
+        conf.setProfileAttrs(Map.of("uid", "id"));
+        conf.setProfileUrl("https://localhost/oauth2/profile";);
+        conf.setProfilePath("/info");
+        conf.setTokenUrl("https://localhost/oauth2/token";);
+        conf.setResponseType("code");
+        conf.setScope("cns");
+        conf.setUserIdAttribute("uid");
+        conf.setWithState(true);
+
+        Map<String, Object> map = new 
AuthModulePropertySourceMapper(null).map(authModuleTO, conf);
+        assertFalse(map.keySet().stream().anyMatch(k -> 
k.endsWith("defined")));
+    }
 }

Reply via email to