You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2018/05/03 14:58:12 UTC
[5/8] syncope git commit: [SYNCOPE-1270] implementation for OpenID
Connect for Admin Console and Enduser - This closes #74
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java
new file mode 100644
index 0000000..69268cb
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java
@@ -0,0 +1,79 @@
+/*
+ * 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.core.persistence.jpa.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+import org.apache.syncope.core.persistence.api.entity.OIDCProviderItem;
+import org.apache.syncope.core.persistence.jpa.entity.resource.AbstractItem;
+
+@Entity
+@Table(name = JPAOIDCProviderItem.TABLE)
+@Cacheable
+public class JPAOIDCProviderItem extends AbstractItem implements OIDCProviderItem {
+
+ public static final String TABLE = "OIDCProviderItem";
+
+ private static final long serialVersionUID = -6903418265811089724L;
+
+ @ManyToOne
+ private JPAOIDCProvider op;
+
+ @Override
+ public OIDCProvider getOP() {
+ return op;
+ }
+
+ @Override
+ public void setOP(final OIDCProvider op) {
+ checkType(op, JPAOIDCProvider.class);
+ this.op = (JPAOIDCProvider) op;
+ }
+
+ @ManyToMany(fetch = FetchType.EAGER)
+ @JoinTable(name = TABLE + "Transformer",
+ joinColumns =
+ @JoinColumn(name = "item_id"),
+ inverseJoinColumns =
+ @JoinColumn(name = "implementation_id"))
+ private List<JPAImplementation> transformers = new ArrayList<>();
+
+ @Override
+ public boolean add(final Implementation transformer) {
+ checkType(transformer, JPAImplementation.class);
+ checkImplementationType(transformer, ImplementationType.ITEM_TRANSFORMER);
+ return this.transformers.add((JPAImplementation) transformer);
+ }
+
+ @Override
+ public List<? extends Implementation> getTransformers() {
+ return transformers;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCUserTemplate.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCUserTemplate.java b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCUserTemplate.java
new file mode 100644
index 0000000..54eea72
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCUserTemplate.java
@@ -0,0 +1,52 @@
+/*
+ * 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.core.persistence.jpa.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+import org.apache.syncope.core.persistence.api.entity.OIDCUserTemplate;
+import org.apache.syncope.core.persistence.jpa.entity.resource.AbstractAnyTemplate;
+
+@Entity
+@Table(name = JPAOIDCUserTemplate.TABLE, uniqueConstraints =
+ @UniqueConstraint(columnNames = { "op_id" }))
+public class JPAOIDCUserTemplate extends AbstractAnyTemplate implements OIDCUserTemplate {
+
+ public static final String TABLE = "OIDCUserTemplate";
+
+ private static final long serialVersionUID = 3964321047520954968L;
+
+ @ManyToOne
+ private JPAOIDCProvider op;
+
+ @Override
+ public OIDCProvider getOP() {
+ return op;
+ }
+
+ @Override
+ public void setOP(final OIDCProvider op) {
+ checkType(op, JPAOIDCProvider.class);
+ this.op = (JPAOIDCProvider) op;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/pom.xml b/ext/oidcclient/pom.xml
new file mode 100644
index 0000000..6bdb336
--- /dev/null
+++ b/ext/oidcclient/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope</groupId>
+ <artifactId>syncope-ext</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client</name>
+ <description>Apache Syncope Ext: OIDC Client</description>
+ <groupId>org.apache.syncope.ext</groupId>
+ <artifactId>syncope-ext-oidcclient</artifactId>
+ <packaging>pom</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../..</rootpom.basedir>
+ </properties>
+
+
+ <modules>
+ <module>common-lib</module>
+ <module>rest-api</module>
+ <module>logic</module>
+ <module>rest-cxf</module>
+ <module>persistence-api</module>
+ <module>persistence-jpa</module>
+ <module>agent</module>
+ <module>client-console</module>
+ <module>client-enduser</module>
+ <module>provisioning-api</module>
+ <module>provisioning-java</module>
+ </modules>
+
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/provisioning-api/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/provisioning-api/pom.xml b/ext/oidcclient/provisioning-api/pom.xml
new file mode 100644
index 0000000..3d58721
--- /dev/null
+++ b/ext/oidcclient/provisioning-api/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope.ext</groupId>
+ <artifactId>syncope-ext-oidcclient</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client Provisioning API</name>
+ <description>Apache Syncope Ext: OIDC Client Provisioning API</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-provisioning-api</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-provisioning-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-persistence-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-common-lib</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/OIDCProviderActions.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/OIDCProviderActions.java b/ext/oidcclient/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/OIDCProviderActions.java
new file mode 100644
index 0000000..40ea6a8
--- /dev/null
+++ b/ext/oidcclient/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/OIDCProviderActions.java
@@ -0,0 +1,35 @@
+/*
+ * 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.core.provisioning.api;
+
+import org.apache.syncope.common.lib.patch.UserPatch;
+import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
+import org.apache.syncope.common.lib.to.UserTO;
+
+public interface OIDCProviderActions {
+
+ UserTO beforeCreate(UserTO input, OIDCLoginResponseTO loginResponse);
+
+ UserTO afterCreate(UserTO input, OIDCLoginResponseTO loginResponse);
+
+ UserPatch beforeUpdate(UserPatch input, OIDCLoginResponseTO loginResponse);
+
+ UserTO afterUpdate(UserTO input, OIDCLoginResponseTO loginResponse);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/OIDCProviderDataBinder.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/OIDCProviderDataBinder.java b/ext/oidcclient/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/OIDCProviderDataBinder.java
new file mode 100644
index 0000000..acea05d
--- /dev/null
+++ b/ext/oidcclient/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/OIDCProviderDataBinder.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.core.provisioning.api.data;
+
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+
+public interface OIDCProviderDataBinder {
+
+ OIDCProvider create(OIDCProviderTO op);
+
+ OIDCProvider update(OIDCProvider op, OIDCProviderTO opTO);
+
+ OIDCProviderTO getOIDCProviderTO(OIDCProvider op);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/provisioning-java/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/provisioning-java/pom.xml b/ext/oidcclient/provisioning-java/pom.xml
new file mode 100644
index 0000000..962c2b7
--- /dev/null
+++ b/ext/oidcclient/provisioning-java/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope.ext</groupId>
+ <artifactId>syncope-ext-oidcclient</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client Provisioning Java</name>
+ <description>Apache Syncope Ext: OIDC Client Provisioning Java</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-provisioning-java</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-provisioning-java</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-provisioning-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultOIDCProviderActions.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultOIDCProviderActions.java b/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultOIDCProviderActions.java
new file mode 100644
index 0000000..e6b060c
--- /dev/null
+++ b/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultOIDCProviderActions.java
@@ -0,0 +1,48 @@
+/*
+ * 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.core.provisioning.java;
+
+import org.apache.syncope.common.lib.patch.UserPatch;
+import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.core.provisioning.api.OIDCProviderActions;
+
+public class DefaultOIDCProviderActions implements OIDCProviderActions {
+
+ @Override
+ public UserTO beforeCreate(final UserTO input, final OIDCLoginResponseTO loginResponse) {
+ return input;
+ }
+
+ @Override
+ public UserTO afterCreate(final UserTO input, final OIDCLoginResponseTO loginResponse) {
+ return input;
+ }
+
+ @Override
+ public UserPatch beforeUpdate(final UserPatch input, final OIDCLoginResponseTO loginResponse) {
+ return input;
+ }
+
+ @Override
+ public UserTO afterUpdate(final UserTO input, final OIDCLoginResponseTO loginResponse) {
+ return input;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCProviderDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCProviderDataBinderImpl.java b/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCProviderDataBinderImpl.java
new file mode 100644
index 0000000..75ead03
--- /dev/null
+++ b/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCProviderDataBinderImpl.java
@@ -0,0 +1,258 @@
+/*
+ * 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.core.provisioning.java.data;
+
+import java.text.ParseException;
+import java.util.stream.Collectors;
+import org.apache.syncope.common.lib.SyncopeClientCompositeException;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.common.lib.to.ItemTO;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.OIDCProviderDAO;
+import org.apache.syncope.core.persistence.api.entity.Entity;
+import org.apache.syncope.core.persistence.api.entity.OIDCEntityFactory;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+import org.apache.syncope.core.persistence.api.entity.OIDCProviderItem;
+import org.apache.syncope.core.persistence.api.entity.OIDCUserTemplate;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
+import org.apache.syncope.core.provisioning.api.data.OIDCProviderDataBinder;
+import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
+import org.apache.syncope.core.spring.BeanUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class OIDCProviderDataBinderImpl implements OIDCProviderDataBinder {
+
+ private static final Logger LOG = LoggerFactory.getLogger(OIDCProviderDataBinder.class);
+
+ private static final String[] ITEM_IGNORE_PROPERTIES = { "key", "purpose" };
+
+ @Autowired
+ private AnyTypeDAO anyTypeDAO;
+
+ @Autowired
+ private OIDCProviderDAO oidcOPDAO;
+
+ @Autowired
+ private OIDCEntityFactory entityFactory;
+
+ @Autowired
+ private IntAttrNameParser intAttrNameParser;
+
+ @Override
+ public OIDCProvider create(final OIDCProviderTO opTO) {
+ return update(entityFactory.newEntity(OIDCProvider.class), opTO);
+
+ }
+
+ private void populateItems(
+ final OIDCProviderTO opTO,
+ final OIDCProvider op,
+ final AnyTypeClassTO allowedSchemas) {
+
+ SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+ SyncopeClientException invalidMapping =
+ SyncopeClientException.build(ClientExceptionType.InvalidMapping);
+ SyncopeClientException requiredValuesMissing =
+ SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
+
+ for (ItemTO itemTO : opTO.getItems()) {
+ if (itemTO == null) {
+ LOG.error("Null {}", ItemTO.class.getSimpleName());
+ invalidMapping.getElements().add("Null " + ItemTO.class.getSimpleName());
+ } else if (itemTO.getIntAttrName() == null) {
+ requiredValuesMissing.getElements().add("intAttrName");
+ scce.addException(requiredValuesMissing);
+ } else {
+ IntAttrName intAttrName = null;
+ try {
+ intAttrName = intAttrNameParser.parse(itemTO.getIntAttrName(), AnyTypeKind.USER);
+ } catch (ParseException e) {
+ LOG.error("Invalid intAttrName '{}' specified, ignoring", itemTO.getIntAttrName(), e);
+ }
+
+ if (intAttrName == null || intAttrName.getSchemaType() == null && intAttrName.getField() == null) {
+ LOG.error("'{}' not existing", itemTO.getIntAttrName());
+ invalidMapping.getElements().add("'" + itemTO.getIntAttrName() + "' not existing");
+ } else {
+ boolean allowed = true;
+ if (intAttrName.getSchemaType() != null
+ && intAttrName.getEnclosingGroup() == null
+ && intAttrName.getRelatedAnyObject() == null) {
+ switch (intAttrName.getSchemaType()) {
+ case PLAIN:
+ allowed = allowedSchemas.getPlainSchemas().contains(intAttrName.getSchemaName());
+ break;
+
+ case DERIVED:
+ allowed = allowedSchemas.getDerSchemas().contains(intAttrName.getSchemaName());
+ break;
+
+ case VIRTUAL:
+ allowed = allowedSchemas.getVirSchemas().contains(intAttrName.getSchemaName());
+ break;
+
+ default:
+ }
+ }
+
+ if (allowed) {
+ // no mandatory condition implies mandatory condition false
+ if (!JexlUtils.isExpressionValid(itemTO.getMandatoryCondition() == null
+ ? "false" : itemTO.getMandatoryCondition())) {
+
+ SyncopeClientException invalidMandatoryCondition = SyncopeClientException.build(
+ ClientExceptionType.InvalidValues);
+ invalidMandatoryCondition.getElements().add(itemTO.getMandatoryCondition());
+ scce.addException(invalidMandatoryCondition);
+ }
+
+ OIDCProviderItem item = entityFactory.newEntity(OIDCProviderItem.class);
+ BeanUtils.copyProperties(itemTO, item, ITEM_IGNORE_PROPERTIES);
+ item.setOP(op);
+ item.setPurpose(MappingPurpose.NONE);
+ if (item.isConnObjectKey()) {
+ if (intAttrName.getSchemaType() == SchemaType.VIRTUAL) {
+ invalidMapping.getElements().
+ add("Virtual attributes cannot be set as ConnObjectKey");
+ }
+ if ("password".equals(intAttrName.getField())) {
+ invalidMapping.getElements().add(
+ "Password attributes cannot be set as ConnObjectKey");
+ }
+
+ op.setConnObjectKeyItem(item);
+ } else {
+ op.add(item);
+ }
+ } else {
+ LOG.error("'{}' not allowed", itemTO.getIntAttrName());
+ invalidMapping.getElements().add("'" + itemTO.getIntAttrName() + "' not allowed");
+ }
+ }
+ }
+ }
+
+ if (!invalidMapping.getElements().isEmpty()) {
+ scce.addException(invalidMapping);
+ }
+ if (scce.hasExceptions()) {
+ throw scce;
+ }
+ }
+
+ @Override
+ public OIDCProvider update(final OIDCProvider op, final OIDCProviderTO opTO) {
+ op.setAuthorizationEndpoint(opTO.getAuthorizationEndpoint());
+ op.setClientID(opTO.getClientID());
+ op.setClientSecret(opTO.getClientSecret());
+ op.setName(opTO.getName());
+ op.setIssuer(opTO.getIssuer());
+ op.setJwksUri(opTO.getJwksUri());
+ op.setTokenEndpoint(opTO.getTokenEndpoint());
+ op.setUserinfoEndpoint(opTO.getUserinfoEndpoint());
+ op.setHasDiscovery(opTO.getHasDiscovery());
+ op.setCreateUnmatching(opTO.isCreateUnmatching());
+ op.setUpdateMatching(opTO.isUpdateMatching());
+
+ if (opTO.getUserTemplate() == null) {
+ op.setUserTemplate(null);
+ } else {
+ OIDCUserTemplate userTemplate = op.getUserTemplate();
+ if (userTemplate == null) {
+ userTemplate = entityFactory.newEntity(OIDCUserTemplate.class);
+ userTemplate.setAnyType(anyTypeDAO.findUser());
+ userTemplate.setOP(op);
+ op.setUserTemplate(userTemplate);
+ }
+ userTemplate.set(opTO.getUserTemplate());
+ }
+
+ op.getItems().clear();
+ AnyTypeClassTO allowedSchemas = new AnyTypeClassTO();
+ anyTypeDAO.findUser().getClasses().forEach(anyTypeClass -> {
+ allowedSchemas.getPlainSchemas().addAll(anyTypeClass.getPlainSchemas().stream().
+ map(Entity::getKey).collect(Collectors.toList()));
+ allowedSchemas.getDerSchemas().addAll(anyTypeClass.getDerSchemas().stream().
+ map(Entity::getKey).collect(Collectors.toList()));
+ allowedSchemas.getVirSchemas().addAll(anyTypeClass.getVirSchemas().stream().
+ map(Entity::getKey).collect(Collectors.toList()));
+ });
+ populateItems(opTO, op, allowedSchemas);
+
+ op.getActionsClassNames().clear();
+ op.getActionsClassNames().addAll(opTO.getActionsClassNames());
+
+ return oidcOPDAO.save(op);
+ }
+
+ private void populateItems(final OIDCProvider op, final OIDCProviderTO opTO) {
+ op.getItems().forEach(item -> {
+ ItemTO itemTO = new ItemTO();
+ itemTO.setKey(item.getKey());
+ BeanUtils.copyProperties(item, itemTO, ITEM_IGNORE_PROPERTIES);
+ itemTO.setPurpose(MappingPurpose.NONE);
+
+ if (itemTO.isConnObjectKey()) {
+ opTO.setConnObjectKeyItem(itemTO);
+ } else {
+ opTO.add(itemTO);
+ }
+ });
+ }
+
+ @Override
+ public OIDCProviderTO getOIDCProviderTO(final OIDCProvider op) {
+ OIDCProviderTO opTO = new OIDCProviderTO();
+
+ opTO.setKey(op.getKey());
+ opTO.setAuthorizationEndpoint(op.getAuthorizationEndpoint());
+ opTO.setClientID(op.getClientID());
+ opTO.setClientSecret(op.getClientSecret());
+ opTO.setName(op.getName());
+ opTO.setIssuer(op.getIssuer());
+ opTO.setJwksUri(op.getJwksUri());
+ opTO.setTokenEndpoint(op.getTokenEndpoint());
+ opTO.setUserinfoEndpoint(op.getUserinfoEndpoint());
+ opTO.setHasDiscovery(op.getHasDiscovery());
+ opTO.setCreateUnmatching(op.isCreateUnmatching());
+ opTO.setUpdateMatching(op.isUpdateMatching());
+
+ if (op.getUserTemplate() != null) {
+ opTO.setUserTemplate((UserTO) op.getUserTemplate().get());
+ }
+
+ populateItems(op, opTO);
+
+ opTO.getActionsClassNames().addAll(op.getActionsClassNames());
+
+ return opTO;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/rest-api/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/rest-api/pom.xml b/ext/oidcclient/rest-api/pom.xml
new file mode 100644
index 0000000..60c469f
--- /dev/null
+++ b/ext/oidcclient/rest-api/pom.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope.ext</groupId>
+ <artifactId>syncope-ext-oidcclient</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client REST API</name>
+ <description>Apache Syncope Ext: OIDC Client REST API</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-rest-api</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.common</groupId>
+ <artifactId>syncope-common-rest-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-common-lib</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- Generating javadoc JAR artifact for usage with CXF's WADL generator (for core) -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <inherited>true</inherited>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCClientService.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCClientService.java b/ext/oidcclient/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCClientService.java
new file mode 100644
index 0000000..d599e75
--- /dev/null
+++ b/ext/oidcclient/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCClientService.java
@@ -0,0 +1,75 @@
+/*
+ * 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.rest.api.service;
+
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.security.SecurityRequirements;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import org.apache.syncope.common.lib.OIDCConstants;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.OIDCLoginRequestTO;
+import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
+
+/**
+ * REST operations for OpenID Connect Clients.
+ */
+@Tag(name = "OIDCClients")
+@SecurityRequirements({
+ @SecurityRequirement(name = "BasicAuthentication"),
+ @SecurityRequirement(name = "Bearer") })
+@Path("oidcclient/clients")
+public interface OIDCClientService extends JAXRSService {
+
+ /**
+ * Generates OpenID Connect authentication request for the Provider matching the provided op.
+ *
+ * @param redirectURI redirect URI
+ * @param op OpenID Connect Provider
+ * @return OpenID Connect authentication request
+ */
+ @POST
+ @Path("loginRequest")
+ @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ OIDCLoginRequestTO createLoginRequest(
+ @QueryParam(OIDCConstants.REDIRECT_URI) String redirectURI,
+ @QueryParam(OIDCConstants.OP) String op);
+
+ /**
+ * Uses the provided authorization code to go through the OpenID Connect tokens process and finally creates JWT for
+ * the matching user, if found.
+ *
+ * @param redirectURI redirect URI
+ * @param authorizationCode authorization code generated by the remote OpenID Connect Provider
+ * @param op OpenID Connect Provider
+ * @return JWT for the matching user plus attributes returned in the response
+ */
+ @POST
+ @Path("login")
+ @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ OIDCLoginResponseTO login(
+ @QueryParam(OIDCConstants.REDIRECT_URI) String redirectURI,
+ @QueryParam("authorizationCode") String authorizationCode,
+ @QueryParam(OIDCConstants.OP) String op);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCProviderService.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCProviderService.java b/ext/oidcclient/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCProviderService.java
new file mode 100644
index 0000000..9705b31
--- /dev/null
+++ b/ext/oidcclient/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCProviderService.java
@@ -0,0 +1,156 @@
+/*
+ * 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.rest.api.service;
+
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.headers.Header;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.security.SecurityRequirements;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.PUT;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.HttpHeaders;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+
+/**
+ * REST operations for OpenID Connect Providers.
+ */
+@Tag(name = "OIDCProviders")
+@SecurityRequirements({
+ @SecurityRequirement(name = "BasicAuthentication"),
+ @SecurityRequirement(name = "Bearer") })
+@Path("oidcclient/providers")
+public interface OIDCProviderService extends JAXRSService {
+
+ /**
+ * Returns the list of available OIDCProviderActions implementations.
+ *
+ * @return the list of available OIDCProviderActions implementations
+ */
+ @GET
+ @Path("actionsClasses")
+ @Produces({ MediaType.APPLICATION_JSON })
+ Set<String> getActionsClasses();
+
+ /**
+ * Returns a list of all defined OIDC Providers.
+ *
+ * @return list of all defined OIDC Providers
+ */
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ List<OIDCProviderTO> list();
+
+ /**
+ * Returns the OIDC Provider with matching key, if available.
+ *
+ * @param key OIDC Provider's key
+ * @return OIDC Providers with matching key, if available
+ */
+ @GET
+ @Path("{key}")
+ @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ OIDCProviderTO read(@PathParam("key") String key);
+
+ /**
+ * Creates a new OIDC Provider.
+ *
+ * @param oidcProviderTO OpenID Connect Provider configuration to be stored
+ * @return Response object featuring Location header of created OIDC Provider
+ */
+ @ApiResponses(
+ @ApiResponse(responseCode = "201",
+ description = "OIDC Provider successfully created", headers = {
+ @Header(name = RESTHeaders.RESOURCE_KEY, schema =
+ @Schema(type = "string"),
+ description = "Key value for the entity created"),
+ @Header(name = HttpHeaders.LOCATION, schema =
+ @Schema(type = "string"),
+ description = "URL of the entity created") }))
+ @POST
+ @Consumes({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ Response create(OIDCProviderTO oidcProviderTO);
+
+ /**
+ * Creates a new OIDC Provider by using its Discovery Document.
+ *
+ * @param oidcProviderTO OpenID Connect Provider configuration to be stored
+ * @return Response object featuring Location header of created OIDC Provider
+ */
+ @ApiResponses(
+ @ApiResponse(responseCode = "201",
+ description = "OIDC Provider successfully created", headers = {
+ @Header(name = RESTHeaders.RESOURCE_KEY, schema =
+ @Schema(type = "string"),
+ description = "Key value for the entity created"),
+ @Header(name = HttpHeaders.LOCATION, schema =
+ @Schema(type = "string"),
+ description = "URL of the entity created") }))
+ @POST
+ @Path("fromDiscovery")
+ @Consumes({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ Response createFromDiscovery(OIDCProviderTO oidcProviderTO);
+
+ /**
+ * Updates the OIDC Provider with matching key.
+ *
+ * @param oidcProviderTO OpenID Connect Provider configuration to be stored
+ */
+ @Parameter(name = "key", description = "OIDC Provider's key", in = ParameterIn.PATH, schema =
+ @Schema(type = "string"))
+ @ApiResponses(
+ @ApiResponse(responseCode = "204", description = "Operation was successful"))
+ @PUT
+ @Path("{key}")
+ @Consumes({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ void update(@NotNull OIDCProviderTO oidcProviderTO);
+
+ /**
+ * Deletes the OIDC Provider with matching key.
+ *
+ * @param key OIDC Provider key
+ */
+ @ApiResponses(
+ @ApiResponse(responseCode = "204", description = "Operation was successful"))
+ @DELETE
+ @Path("{key}")
+ @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, MediaType.APPLICATION_XML })
+ void delete(@PathParam("key") String key);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/rest-cxf/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/rest-cxf/pom.xml b/ext/oidcclient/rest-cxf/pom.xml
new file mode 100644
index 0000000..38798be
--- /dev/null
+++ b/ext/oidcclient/rest-cxf/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.syncope.ext</groupId>
+ <artifactId>syncope-ext-oidcclient</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client REST CXF</name>
+ <description>Apache Syncope Ext: OIDC Client REST CXF</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-rest-cxf</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-rest-cxf</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-rest-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-rest-api</artifactId>
+ <version>${project.version}</version>
+ <classifier>javadoc</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-logic</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCClientServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCClientServiceImpl.java b/ext/oidcclient/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCClientServiceImpl.java
new file mode 100644
index 0000000..74c14b9
--- /dev/null
+++ b/ext/oidcclient/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCClientServiceImpl.java
@@ -0,0 +1,44 @@
+/*
+ * 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.core.rest.cxf.service;
+
+import org.apache.syncope.common.lib.to.OIDCLoginRequestTO;
+import org.apache.syncope.common.rest.api.service.OIDCClientService;
+import org.apache.syncope.core.logic.OIDCClientLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
+
+@Service
+public class OIDCClientServiceImpl extends AbstractServiceImpl implements OIDCClientService {
+
+ @Autowired
+ private OIDCClientLogic logic;
+
+ @Override
+ public OIDCLoginRequestTO createLoginRequest(final String redirectURI, final String op) {
+ return logic.createLoginRequest(redirectURI, op);
+ }
+
+ @Override
+ public OIDCLoginResponseTO login(final String redirectURI, final String authorizationCode, final String op) {
+ return logic.login(redirectURI, authorizationCode, op);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCProviderServiceImpl.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCProviderServiceImpl.java b/ext/oidcclient/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCProviderServiceImpl.java
new file mode 100644
index 0000000..7af4366
--- /dev/null
+++ b/ext/oidcclient/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/OIDCProviderServiceImpl.java
@@ -0,0 +1,83 @@
+/*
+ * 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.core.rest.cxf.service;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
+import org.apache.syncope.core.logic.OIDCProviderLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class OIDCProviderServiceImpl extends AbstractServiceImpl implements OIDCProviderService {
+
+ @Autowired
+ private OIDCProviderLogic logic;
+
+ @Override
+ public Set<String> getActionsClasses() {
+ return logic.getActionsClasses();
+ }
+
+ @Override
+ public Response create(final OIDCProviderTO oidcProviderTO) {
+ String created = logic.create(oidcProviderTO);
+
+ URI location = uriInfo.getAbsolutePathBuilder().path(created).build();
+ return Response.created(location).
+ header(RESTHeaders.RESOURCE_KEY, created).
+ build();
+ }
+
+ @Override
+ public Response createFromDiscovery(final OIDCProviderTO oidcProviderTO) {
+ String created = logic.createFromDiscovery(oidcProviderTO);
+
+ URI location = uriInfo.getAbsolutePathBuilder().path(created).build();
+ return Response.created(location).
+ header(RESTHeaders.RESOURCE_KEY, created).
+ build();
+ }
+
+ @Override
+ public List<OIDCProviderTO> list() {
+ return logic.list();
+
+ }
+
+ @Override
+ public OIDCProviderTO read(final String key) {
+ return logic.read(key);
+ }
+
+ @Override
+ public void update(final OIDCProviderTO oidcProviderTO) {
+ logic.update(oidcProviderTO);
+ }
+
+ @Override
+ public void delete(final String key) {
+ logic.delete(key);
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/pom.xml
----------------------------------------------------------------------
diff --git a/ext/pom.xml b/ext/pom.xml
index a2aa130..d1e5b1b 100644
--- a/ext/pom.xml
+++ b/ext/pom.xml
@@ -82,6 +82,7 @@ under the License.
<module>saml2sp</module>
<module>elasticsearch</module>
<module>scimv2</module>
+ <module>oidcclient</module>
</modules>
</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/Login.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/Login.java b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/Login.java
index e206ff7..98d4504 100644
--- a/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/Login.java
+++ b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/Login.java
@@ -30,7 +30,7 @@ import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.common.lib.to.SAML2RequestTO;
import org.apache.syncope.common.rest.api.service.SAML2SPService;
-@WebServlet(name = "login", urlPatterns = { "/saml2sp/login" })
+@WebServlet(name = "saml2spLogin", urlPatterns = { "/saml2sp/login" })
public class Login extends AbstractSAML2SPServlet {
private static final long serialVersionUID = 968480296813639041L;
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/console-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/pom.xml b/fit/console-reference/pom.xml
index c13b264..698bc94 100644
--- a/fit/console-reference/pom.xml
+++ b/fit/console-reference/pom.xml
@@ -75,6 +75,12 @@ under the License.
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-console</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/console-reference/src/main/resources/oidcclient-agent.properties
----------------------------------------------------------------------
diff --git a/fit/console-reference/src/main/resources/oidcclient-agent.properties b/fit/console-reference/src/main/resources/oidcclient-agent.properties
new file mode 100644
index 0000000..1d53d49
--- /dev/null
+++ b/fit/console-reference/src/main/resources/oidcclient-agent.properties
@@ -0,0 +1,26 @@
+# 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.
+conf.directory=${conf.directory}
+
+anonymousUser=${anonymousUser}
+anonymousKey=${anonymousKey}
+
+scheme=http
+host=localhost
+port=9080
+rootPath=/syncope/rest/
+useGZIPCompression=true
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/console-reference/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/src/main/webapp/WEB-INF/web.xml b/fit/console-reference/src/main/webapp/WEB-INF/web.xml
index 890e5b0..1dc41d1 100644
--- a/fit/console-reference/src/main/webapp/WEB-INF/web.xml
+++ b/fit/console-reference/src/main/webapp/WEB-INF/web.xml
@@ -53,6 +53,16 @@ under the License.
<param-value>../wicket/bookmarkable/org.apache.syncope.client.console.pages.SAML2SPSelfReg</param-value>
</context-param>
+ <!-- OIDC Client Parameters -->
+ <context-param>
+ <param-name>oidcclient.login.success.url</param-name>
+ <param-value>../wicket/bookmarkable/org.apache.syncope.client.console.pages.OIDCClientLogin</param-value>
+ </context-param>
+ <context-param>
+ <param-name>oidcclient.login.error.url</param-name>
+ <param-value>../wicket/bookmarkable/org.apache.syncope.client.console.pages.Login</param-value>
+ </context-param>
+
<!-- SESSION TIMEOUT (MINUTES)-->
<session-config>
<session-timeout>30</session-timeout>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/console-reference/src/test/resources/rebel.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/src/test/resources/rebel.xml b/fit/console-reference/src/test/resources/rebel.xml
index cfd69c9..876c58f 100644
--- a/fit/console-reference/src/test/resources/rebel.xml
+++ b/fit/console-reference/src/test/resources/rebel.xml
@@ -34,6 +34,10 @@ under the License.
</dir>
<dir name="${basedir}/../../ext/scimv2/client-console/target/classes">
</dir>
+ <dir name="${basedir}/../../ext/oidcclient/agent/target/classes">
+ </dir>
+ <dir name="${basedir}/../../ext/oidcclient/client-console/target/classes">
+ </dir>
</classpath>
<web>
@@ -57,6 +61,10 @@ under the License.
<dir name="${basedir}/../../ext/scimv2/client-console/target/classes">
</dir>
</link>
+ <link target="/">
+ <dir name="${basedir}/../../ext/oidcclient/client-console/target/classes">
+ </dir>
+ </link>
</web>
</application>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/core-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml
index 4e5e4a1..9b5d717 100644
--- a/fit/core-reference/pom.xml
+++ b/fit/core-reference/pom.xml
@@ -185,6 +185,18 @@ under the License.
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-rest-cxf</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-console</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
@@ -1099,6 +1111,17 @@ under the License.
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-rest-cxf</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-persistence-jpa</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.syncope.ext.scimv2</groupId>
<artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
<version>${project.version}</version>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
index 759f5e4..9e7d541 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -84,6 +84,8 @@ import org.apache.syncope.common.rest.api.service.ResourceService;
import org.apache.syncope.common.rest.api.service.GroupService;
import org.apache.syncope.common.rest.api.service.ImplementationService;
import org.apache.syncope.common.rest.api.service.MailTemplateService;
+import org.apache.syncope.common.rest.api.service.OIDCClientService;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
import org.apache.syncope.common.rest.api.service.RealmService;
import org.apache.syncope.common.rest.api.service.ReconciliationService;
import org.apache.syncope.common.rest.api.service.RelationshipTypeService;
@@ -252,6 +254,10 @@ public abstract class AbstractITCase {
protected static SAML2SPService saml2SpService;
protected static SAML2IdPService saml2IdPService;
+
+ protected static OIDCClientService oidcClientService;
+
+ protected static OIDCProviderService oidcProviderService;
protected static SCIMConfService scimConfService;
@@ -322,6 +328,8 @@ public abstract class AbstractITCase {
camelRouteService = adminClient.getService(CamelRouteService.class);
saml2SpService = adminClient.getService(SAML2SPService.class);
saml2IdPService = adminClient.getService(SAML2IdPService.class);
+ oidcClientService = adminClient.getService(OIDCClientService.class);
+ oidcProviderService = adminClient.getService(OIDCProviderService.class);
scimConfService = adminClient.getService(SCIMConfService.class);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/core-reference/src/test/java/org/apache/syncope/fit/OIDCClientDetector.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/OIDCClientDetector.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/OIDCClientDetector.java
new file mode 100644
index 0000000..b08342e
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/OIDCClientDetector.java
@@ -0,0 +1,52 @@
+/*
+ * 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.fit;
+
+import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OIDCClientDetector {
+
+ private static final Logger LOG = LoggerFactory.getLogger(OIDCClientDetector.class);
+
+ private static Boolean ENABLED;
+
+ public static boolean isOIDCClientAvailable() {
+ synchronized (LOG) {
+ if (ENABLED == null) {
+ try {
+ new SyncopeClientFactoryBean().
+ setAddress(AbstractITCase.ADDRESS).
+ setContentType(SyncopeClientFactoryBean.ContentType.XML).
+ create(new AnonymousAuthenticationHandler(
+ AbstractITCase.ANONYMOUS_UNAME, AbstractITCase.ANONYMOUS_KEY)).
+ getService(OIDCProviderService.class).list();
+ ENABLED = true;
+ } catch (Exception e) {
+ // ignore
+ ENABLED = false;
+ }
+ }
+ }
+ return ENABLED;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/core-reference/src/test/java/org/apache/syncope/fit/core/OIDCClientITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/OIDCClientITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/OIDCClientITCase.java
new file mode 100644
index 0000000..33a9d44
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/OIDCClientITCase.java
@@ -0,0 +1,152 @@
+/*
+ * 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.fit.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
+import org.apache.syncope.client.lib.BasicAuthenticationHandler;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.to.ItemTO;
+import org.apache.syncope.common.lib.to.OIDCLoginRequestTO;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.service.OIDCClientService;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
+import org.apache.syncope.fit.AbstractITCase;
+import org.apache.syncope.fit.OIDCClientDetector;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class OIDCClientITCase extends AbstractITCase {
+
+ private static SyncopeClient anonymous;
+
+ private static SyncopeClient admin;
+
+ @BeforeClass
+ public static void setup() {
+ anonymous = new SyncopeClientFactoryBean().
+ setAddress(ADDRESS).
+ create(new AnonymousAuthenticationHandler(ANONYMOUS_UNAME, ANONYMOUS_KEY));
+
+ admin = new SyncopeClientFactoryBean().
+ setAddress(ADDRESS).
+ create(new BasicAuthenticationHandler(ADMIN_UNAME, ADMIN_PWD));
+ }
+
+ @BeforeClass
+ public static void createOIDCProviderWithoutDiscovery() throws Exception {
+ if (!OIDCClientDetector.isOIDCClientAvailable()) {
+ return;
+ }
+
+ assertTrue(oidcProviderService.list().isEmpty());
+
+ OIDCProviderTO oidcProviderTO = new OIDCProviderTO();
+ oidcProviderTO.setAuthorizationEndpoint("AuthorizationEndpoint");
+ oidcProviderTO.setClientID("ClientID");
+ oidcProviderTO.setClientSecret("ClientSecret");
+ oidcProviderTO.setIssuer("https://accounts.google.com");
+ oidcProviderTO.setJwksUri("JwksUri");
+ oidcProviderTO.setName("Google");
+ oidcProviderTO.setTokenEndpoint("TokenEndpoint");
+ oidcProviderTO.setUserinfoEndpoint("UserinfoEndpoint");
+
+ admin.getService(OIDCProviderService.class).create(oidcProviderTO);
+ }
+
+ @AfterClass
+ public static void clearProviders() throws Exception {
+ if (!OIDCClientDetector.isOIDCClientAvailable()) {
+ return;
+ }
+
+ for (OIDCProviderTO op : oidcProviderService.list()) {
+ oidcProviderService.delete(op.getKey());
+ }
+ }
+
+ @Test
+ public void createLoginRequest() {
+ Assume.assumeTrue(OIDCClientDetector.isOIDCClientAvailable());
+
+ OIDCLoginRequestTO loginRequest = anonymous.getService(OIDCClientService.class).
+ createLoginRequest("http://localhost:9080/syncope-console/oidcclient/code-consumer", "Google");
+
+ assertNotNull(loginRequest);
+ assertEquals("http://localhost:9080/syncope-console/oidcclient/code-consumer", loginRequest.getRedirectURI());
+ assertNotNull(loginRequest.getProviderAddress());
+ assertNotNull(loginRequest.getClientId());
+ assertNotNull(loginRequest.getResponseType());
+ assertNotNull(loginRequest.getScope());
+ assertNotNull(loginRequest.getState());
+ }
+
+ @Test
+ public void setProviderMapping() {
+ Assume.assumeTrue(OIDCClientDetector.isOIDCClientAvailable());
+
+ OIDCProviderTO ssoCircle = IterableUtils.find(oidcProviderService.list(), new Predicate<OIDCProviderTO>() {
+
+ @Override
+ public boolean evaluate(final OIDCProviderTO object) {
+ return "Google".equals(object.getName());
+ }
+ });
+ assertNotNull(ssoCircle);
+ assertFalse(ssoCircle.isCreateUnmatching());
+ assertNull(ssoCircle.getUserTemplate());
+ assertFalse(ssoCircle.getItems().isEmpty());
+ assertNotNull(ssoCircle.getConnObjectKeyItem());
+ assertNotEquals("fullname", ssoCircle.getConnObjectKeyItem().getIntAttrName());
+ assertNotEquals("given_name", ssoCircle.getConnObjectKeyItem().getExtAttrName());
+
+ ssoCircle.setCreateUnmatching(true);
+
+ UserTO userTemplate = new UserTO();
+ userTemplate.setRealm("'/'");
+ ssoCircle.setUserTemplate(userTemplate);
+
+ ssoCircle.getItems().clear();
+ ItemTO keyMapping = new ItemTO();
+ keyMapping.setIntAttrName("fullname");
+ keyMapping.setExtAttrName("given_name");
+ ssoCircle.setConnObjectKeyItem(keyMapping);
+
+ oidcProviderService.update(ssoCircle);
+
+ ssoCircle = oidcProviderService.read(ssoCircle.getKey());
+ assertTrue(ssoCircle.isCreateUnmatching());
+ assertEquals(userTemplate, ssoCircle.getUserTemplate());
+ assertEquals("fullname", ssoCircle.getConnObjectKeyItem().getIntAttrName());
+ assertEquals("given_name", ssoCircle.getConnObjectKeyItem().getExtAttrName());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/core-reference/src/test/resources/rebel.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/rebel.xml b/fit/core-reference/src/test/resources/rebel.xml
index da4b4b1..0a3965b 100644
--- a/fit/core-reference/src/test/resources/rebel.xml
+++ b/fit/core-reference/src/test/resources/rebel.xml
@@ -103,6 +103,23 @@ under the License.
</dir>
<dir name="${basedir}/../../ext/scimv2/logic/target/classes">
</dir>
+ <dir name="${basedir}/../../ext/oidcclient/common-lib/target/classes">
+ </dir>
+ <dir name="${basedir}/../../ext/oidcclient/logic/target/classes">
+ </dir>
+ <dir name="${basedir}/../../ext/oidcclient/persistence-api/target/classes">
+ </dir>
+ <dir name="${basedir}/../../ext/oidcclient/persistence-jpa/target/classes">
+ <exclude name="org/apache/syncope/core/persistence/jpa/entity/**"/>
+ </dir>
+ <dir name="${basedir}/../../ext/oidcclient/provisioning-api/target/classes">
+ </dir>
+ <dir name="${basedir}/../../ext/oidcclient/provisioning-java/target/classes">
+ </dir>
+ <dir name="${basedir}/../../ext/oidcclient/rest-api/target/classes">
+ </dir>
+ <dir name="${basedir}/../../ext/oidcclient/rest-cxf/target/classes">
+ </dir>
</classpath>
<web>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/enduser-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/enduser-reference/pom.xml b/fit/enduser-reference/pom.xml
index c2fe31a..127d62d 100644
--- a/fit/enduser-reference/pom.xml
+++ b/fit/enduser-reference/pom.xml
@@ -68,6 +68,12 @@ under the License.
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-enduser</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/enduser-reference/src/main/resources/oidcclient-agent.properties
----------------------------------------------------------------------
diff --git a/fit/enduser-reference/src/main/resources/oidcclient-agent.properties b/fit/enduser-reference/src/main/resources/oidcclient-agent.properties
new file mode 100644
index 0000000..1d53d49
--- /dev/null
+++ b/fit/enduser-reference/src/main/resources/oidcclient-agent.properties
@@ -0,0 +1,26 @@
+# 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.
+conf.directory=${conf.directory}
+
+anonymousUser=${anonymousUser}
+anonymousKey=${anonymousKey}
+
+scheme=http
+host=localhost
+port=9080
+rootPath=/syncope/rest/
+useGZIPCompression=true
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/enduser-reference/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/fit/enduser-reference/src/main/webapp/WEB-INF/web.xml b/fit/enduser-reference/src/main/webapp/WEB-INF/web.xml
index 7f61a36..81a7651 100644
--- a/fit/enduser-reference/src/main/webapp/WEB-INF/web.xml
+++ b/fit/enduser-reference/src/main/webapp/WEB-INF/web.xml
@@ -53,6 +53,16 @@ under the License.
<param-value>../wicket/bookmarkable/org.apache.syncope.client.enduser.pages.SAML2SPSelfReg</param-value>
</context-param>
+ <context-param>
+ <param-name>oidcclient.login.success.url</param-name>
+ <param-value>../wicket/bookmarkable/org.apache.syncope.client.enduser.pages.OIDCClientLogin</param-value>
+ </context-param>
+ <context-param>
+ <param-name>oidcclient.login.error.url</param-name>
+ <param-value>../wicket/bookmarkable/org.apache.syncope.client.enduser.pages.HomePage</param-value>
+ </context-param>
+
+
<!-- SESSION TIMEOUT (MINUTES)-->
<session-config>
<session-timeout>30</session-timeout>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/fit/enduser-reference/src/test/resources/rebel.xml
----------------------------------------------------------------------
diff --git a/fit/enduser-reference/src/test/resources/rebel.xml b/fit/enduser-reference/src/test/resources/rebel.xml
index da15397..d544b8d 100644
--- a/fit/enduser-reference/src/test/resources/rebel.xml
+++ b/fit/enduser-reference/src/test/resources/rebel.xml
@@ -30,6 +30,10 @@ under the License.
</dir>
<dir name="${basedir}/../../ext/saml2sp/client-enduser/target/classes">
</dir>
+ <dir name="${basedir}/../../ext/oidcclient/agent/target/classes">
+ </dir>
+ <dir name="${basedir}/../../ext/oidcclient/client-enduser/target/classes">
+ </dir>
</classpath>
<web>
@@ -45,6 +49,10 @@ under the License.
<dir name="${basedir}/../../ext/saml2sp/client-enduser/target/classes">
</dir>
</link>
+ <link target="/">
+ <dir name="${basedir}/../../ext/oidcclient/client-enduser/target/classes">
+ </dir>
+ </link>
</web>
</application>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 49ef0d7..e20e477 100644
--- a/pom.xml
+++ b/pom.xml
@@ -604,6 +604,16 @@ under the License.
</exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-rs-security-sso-oidc</artifactId>
+ <version>${cxf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-rs-extension-providers</artifactId>
+ <version>${cxf.version}</version>
+ </dependency>
<!-- /CXF -->
<!-- Swagger -->
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/src/main/asciidoc/reference-guide/concepts/extensions.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/reference-guide/concepts/extensions.adoc b/src/main/asciidoc/reference-guide/concepts/extensions.adoc
index d6493b6..52d245e 100644
--- a/src/main/asciidoc/reference-guide/concepts/extensions.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/extensions.adoc
@@ -116,6 +116,39 @@ This extension adds features to all components and layers that are available, an
<<customization-extensions,new extensions>>.
====
+==== OpenID Connect Client
+
+This extension can be leveraged to provide http://openid.net/connect/[OpenID Connect^]-based
+https://en.wikipedia.org/wiki/Single_sign-on[Single Sign-On^] access to the <<admin-console-component>>,
+the <<enduser-component>> or any other Java EE application dealing with the <<core>>.
+
+Once installed, one or more OpenID Providers can be created either from
+the http://openid.net/specs/openid-connect-discovery-1_0.html[discovery document^] if it is supported or from inserting
+manually the required attributes, in any case the client_id and the secret_id from the OAuth 2.0 credential and the issuer
+are required.
+After configuration the OpenID provider, the http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[Authorization Code Flow^]
+is going to be implemented in order to reach the user information to be used by Syncope to match the internal users.
+
+
+[NOTE]
+.Extension Sources
+====
+The source code of this extension is available from the Apache Syncope
+ifeval::["{snapshotOrRelease}" == "release"]
+https://github.com/apache/syncope/tree/syncope-{docVersion}/ext/oidcclient[source tree^]
+endif::[]
+ifeval::["{snapshotOrRelease}" == "snapshot"]
+https://github.com/apache/syncope/tree/2_0_X/ext/oidcclient[source tree^]
+endif::[]
+.
+====
+
+[TIP]
+====
+This extension adds features to all components and layers that are available, and can be taken as reference when creating
+<<customization-extensions,new extensions>>.
+====
+
==== Elasticsearch
This extension provides an alternate internal search engine for <<users-groups-and-any-objects>>, requiring an external
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc b/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc
index 80a3870..622f51f 100644
--- a/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc
+++ b/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc
@@ -350,6 +350,25 @@ Setup a <<keystore,keystore>> and place it under the <<properties-files-location
the content of `core/src/main/resources/saml2sp-logic.properties` accordingly.
[discrete]
+===== Enable the <<openid-connect-client>> extension
+
+Add the following dependencies to `core/pom.xml`:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-rest-cxf</artifactId>
+ <version>${syncope.version}</version>
+</dependency>
+<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-persistence-jpa</artifactId>
+ <version>${syncope.version}</version>
+</dependency>
+----
+
+[discrete]
===== Enable the <<elasticsearch>> extension
Add the following dependencies to `core/pom.xml`:
@@ -474,6 +493,23 @@ Add the following dependencies to `console/pom.xml`:
Copy `console/src/main/resources/all/saml2sp-agent.properties` to `console/src/main/resources/saml2sp-agent.properties`.
[discrete]
+===== Enable the <<openid-connect-client>> extension
+
+Add the following dependencies to `console/pom.xml`:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-console</artifactId>
+ <version>${syncope.version}</version>
+</dependency>
+----
+
+Copy `console/src/main/resources/all/oidcclient-agent.properties` to `console/src/main/resources/oidcclient-agent.properties`.
+
+
+[discrete]
===== Enable the <<SCIM>> extension
Add the following dependencies to `console/pom.xml`:
@@ -512,6 +548,22 @@ Add the following dependencies to `enduser/pom.xml`:
Copy `enduser/src/main/resources/all/saml2sp-agent.properties` to `enduser/src/main/resources/saml2sp-agent.properties`.
+[discrete]
+===== Enable the <<openid-connect-client>> extension
+
+Add the following dependencies to `enduser/pom.xml`:
+
+[source,xml,subs="verbatim,attributes"]
+----
+<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-enduser</artifactId>
+ <version>${syncope.version}</version>
+</dependency>
+----
+
+Copy `enduser/src/main/resources/all/oidcclient-agent.properties` to `enduser/src/main/resources/oidcclient-agent.properties`.
+
[[customization-enduser-i18n]]
===== i18n