You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by md...@apache.org on 2023/02/24 15:02:29 UTC
[syncope] branch master updated: [SYNCOPE-1733] Added OAuth20 AuthModule (#414)
This is an automated email from the ASF dual-hosted git repository.
mdisabatino 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 b591939cf1 [SYNCOPE-1733] Added OAuth20 AuthModule (#414)
b591939cf1 is described below
commit b591939cf1dd1764cb98fb6bb788cb376d2b5d0e
Author: mdisabatino <md...@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 3be8843c8c..c3ead959f2 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
@@ -28,6 +28,7 @@ import jakarta.ws.rs.core.Response;
import java.io.IOException;
import java.util.EnumSet;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
@@ -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 0c802fea5a..a5348fb32b 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
@@ -31,6 +31,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;
@@ -51,6 +52,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;
@@ -148,6 +150,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")));
+ }
}