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 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 @@ interface Mapper { Map map(AuthModuleTO authModule, JaasAuthModuleConf conf); + Map map(AuthModuleTO authModule, OAuth20AuthModuleConf conf); + Map map(AuthModuleTO authModule, OIDCAuthModuleConf conf); + Map map(AuthModuleTO authModule, AzureOIDCAuthModuleConf conf); + + Map map(AuthModuleTO authModule, GoogleOIDCAuthModuleConf conf); + + Map map(AuthModuleTO authModule, KeycloakOIDCAuthModuleConf conf); + + Map map(AuthModuleTO authModule, AppleOIDCAuthModuleConf conf); + Map map(AuthModuleTO authModule, SAML2IdPAuthModuleConf conf); Map map(AuthModuleTO authModule, SyncopeAuthModuleConf conf); @@ -49,10 +59,6 @@ interface Mapper { Map map(AuthModuleTO authModule, U2FAuthModuleConf conf); Map map(AuthModuleTO authModule, SimpleMfaAuthModuleConf conf); - - Map map(AuthModuleTO authModule, OAuth20AuthModuleConf conf); - - Map map(AuthModuleTO authModule, AzureAuthModuleConf conf); } Map 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% 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/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 @@ 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 void setTenant(final String tenant) { public Map 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/GoogleOIDCAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/GoogleOIDCAuthModuleConf.java new file mode 100644 index 0000000000..f848f450a7 --- /dev/null +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/GoogleOIDCAuthModuleConf.java @@ -0,0 +1,32 @@ +/* + * 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 GoogleOIDCAuthModuleConf extends AbstractOIDCAuthModuleConf implements AuthModuleConf { + + private static final long serialVersionUID = -471527731042579522L; + + @Override + public Map 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/KeycloakOIDCAuthModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/KeycloakOIDCAuthModuleConf.java new file mode 100644 index 0000000000..a4f464c157 --- /dev/null +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/auth/KeycloakOIDCAuthModuleConf.java @@ -0,0 +1,58 @@ +/* + * 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 KeycloakOIDCAuthModuleConf extends AbstractOIDCAuthModuleConf implements AuthModuleConf { + + private static final long serialVersionUID = -471527731042579522L; + + /** + * Keycloak realm used to construct metadata discovery URI. + */ + protected String realm; + + /** + * 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 setBaseUri(final String baseUri) { + this.baseUri = baseUri; + } + + @Override + public Map 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 49331813d7..c723556ed0 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 @@ -24,12 +24,16 @@ 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; @@ -55,8 +59,12 @@ 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; @@ -148,8 +156,33 @@ public Map map(final AuthModuleTO authModuleTO, final JaasAuthMo } @Override - public Map map(final AuthModuleTO authModuleTO, final OIDCAuthModuleConf conf) { - Pac4jGenericOidcClientProperties props = new Pac4jGenericOidcClientProperties(); + public Map 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.setProfilePath(conf.getProfilePath()); + props.setProfileVerb(conf.getProfileVerb()); + props.setProfileUrl(conf.getProfileUrl()); + props.setTokenUrl(conf.getTokenUrl()); + props.setResponseType(conf.getResponseType()); + props.setScope(conf.getScope()); + props.setPrincipalAttributeId(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())); @@ -164,6 +197,13 @@ public Map map(final AuthModuleTO authModuleTO, final OIDCAuthMo props.setPrincipalAttributeId(conf.getUserIdAttribute()); props.setExpireSessionWithToken(conf.isExpireSessionWithToken()); props.setTokenExpirationAdvance(conf.getTokenExpirationAdvance()); + } + + @Override + public Map map(final AuthModuleTO authModuleTO, final OIDCAuthModuleConf conf) { + Pac4jGenericOidcClientProperties props = new Pac4jGenericOidcClientProperties(); + map(authModuleTO, props, conf); + Pac4jOidcClientProperties client = new Pac4jOidcClientProperties(); client.setGeneric(props); @@ -171,26 +211,54 @@ public Map map(final AuthModuleTO authModuleTO, final OIDCAuthMo } @Override - public Map 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.setProfilePath(conf.getProfilePath()); - props.setProfileVerb(conf.getProfileVerb()); - props.setProfileUrl(conf.getProfileUrl()); - props.setTokenUrl(conf.getTokenUrl()); - props.setResponseType(conf.getResponseType()); - props.setScope(conf.getScope()); - props.setPrincipalAttributeId(conf.getUserIdAttribute()); - props.setWithState(conf.isWithState()); - props.setProfileAttrs(authModuleTO.getItems().stream(). - collect(Collectors.toMap(Item::getIntAttrName, Item::getExtAttrName))); + public Map 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 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 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 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 @@ -316,28 +384,4 @@ public Map map(final AuthModuleTO authModuleTO, final SimpleMfaA return prefix("cas.authn.mfa.simple.", CasCoreConfigurationUtils.asMap(props)); } - - @Override - public Map 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.setPrincipalAttributeId(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)); - } }