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:08 UTC
[1/8] syncope git commit: [SYNCOPE-1270] implementation for OpenID
Connect for Admin Console and Enduser
Repository: syncope
Updated Branches:
refs/heads/2_0_X 13f442a92 -> f29e60f62
refs/heads/master 064b7efac -> 797fd1cbd
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/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..65fb816
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java
@@ -0,0 +1,74 @@
+/*
+ * 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.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+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;
+
+ /**
+ * (Optional) classes for Item transformation.
+ */
+ @ElementCollection(fetch = FetchType.EAGER)
+ @Column(name = "transformerClassName")
+ @CollectionTable(name = TABLE + "_Transformer",
+ joinColumns =
+ @JoinColumn(name = "oidcProviderItemItem_id", referencedColumnName = "id"))
+ private List<String> transformerClassNames = new ArrayList<>();
+
+ @Override
+ public List<String> getTransformerClassNames() {
+ return transformerClassNames;
+ }
+
+ @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/f29e60f6/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/f29e60f6/ext/oidcclient/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/pom.xml b/ext/oidcclient/pom.xml
new file mode 100644
index 0000000..ff10b6d
--- /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.0.9-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/f29e60f6/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..99b7a9c
--- /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.0.9-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/f29e60f6/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/f29e60f6/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/f29e60f6/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..8738e5a
--- /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.0.9-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/f29e60f6/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/f29e60f6/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..6cfa235
--- /dev/null
+++ b/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCProviderDataBinderImpl.java
@@ -0,0 +1,266 @@
+/*
+ * 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 org.apache.commons.collections4.CollectionUtils;
+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.AnyTypeClass;
+import org.apache.syncope.core.persistence.api.entity.DerSchema;
+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.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
+import org.apache.syncope.core.provisioning.api.data.OIDCProviderDataBinder;
+import org.apache.syncope.core.provisioning.api.utils.EntityUtils;
+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();
+ for (AnyTypeClass anyTypeClass : anyTypeDAO.findUser().getClasses()) {
+ allowedSchemas.getPlainSchemas().addAll(
+ CollectionUtils.collect(anyTypeClass.getPlainSchemas(),
+ EntityUtils.<PlainSchema>keyTransformer()));
+ allowedSchemas.getDerSchemas().addAll(
+ CollectionUtils.collect(anyTypeClass.getDerSchemas(),
+ EntityUtils.<DerSchema>keyTransformer()));
+ allowedSchemas.getVirSchemas().addAll(
+ CollectionUtils.collect(anyTypeClass.getVirSchemas(),
+ EntityUtils.<VirSchema>keyTransformer()));
+ }
+ 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) {
+ for (OIDCProviderItem item : op.getItems()) {
+ 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/f29e60f6/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..7f71fb0
--- /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.0.9-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/f29e60f6/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..5585502
--- /dev/null
+++ b/ext/oidcclient/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCClientService.java
@@ -0,0 +1,74 @@
+/*
+ * 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.annotations.Api;
+import io.swagger.annotations.Authorization;
+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.
+ */
+@Api(tags = "OIDCClients", authorizations = {
+ @Authorization(value = "BasicAuthentication")
+ ,
+ @Authorization(value = "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/f29e60f6/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..b8ee7c7
--- /dev/null
+++ b/ext/oidcclient/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/OIDCProviderService.java
@@ -0,0 +1,151 @@
+/*
+ * 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.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import io.swagger.annotations.Authorization;
+import io.swagger.annotations.ResponseHeader;
+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.
+ */
+@Api(tags = "OIDCProviders", authorizations = {
+ @Authorization(value = "BasicAuthentication"),
+ @Authorization(value = "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(code = 201,
+ message = "SecurityQuestion successfully created", responseHeaders = {
+ @ResponseHeader(name = RESTHeaders.RESOURCE_KEY, response = String.class,
+ description = "UUID generated for the entity created")
+ ,
+ @ResponseHeader(name = HttpHeaders.LOCATION, response = String.class,
+ 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(code = 201,
+ message = "SecurityQuestion successfully created", responseHeaders = {
+ @ResponseHeader(name = RESTHeaders.RESOURCE_KEY, response = String.class,
+ description = "UUID generated for the entity created")
+ ,
+ @ResponseHeader(name = HttpHeaders.LOCATION, response = String.class,
+ 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
+ */
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "key", paramType = "path", dataType = "string", value = "OIDC Provider's key") })
+ @ApiResponses(
+ @ApiResponse(code = 204, message = "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(code = 204, message = "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/f29e60f6/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..701093b
--- /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.0.9-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/f29e60f6/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/f29e60f6/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/f29e60f6/ext/pom.xml
----------------------------------------------------------------------
diff --git a/ext/pom.xml b/ext/pom.xml
index 73a5585..fb86dfd 100644
--- a/ext/pom.xml
+++ b/ext/pom.xml
@@ -93,6 +93,7 @@ under the License.
<module>swagger-ui</module>
<module>saml2sp</module>
<module>scimv2</module>
+ <module>oidcclient</module>
</modules>
</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/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/f29e60f6/fit/console-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/pom.xml b/fit/console-reference/pom.xml
index e4f2405..4fff371 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/f29e60f6/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/f29e60f6/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/f29e60f6/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/f29e60f6/fit/core-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml
index 798a6e9..0b719e8 100644
--- a/fit/core-reference/pom.xml
+++ b/fit/core-reference/pom.xml
@@ -191,6 +191,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>
@@ -1075,6 +1087,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/f29e60f6/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 3595886..5d24bd8 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
@@ -83,6 +83,8 @@ import org.apache.syncope.common.rest.api.service.ReportService;
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.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;
@@ -247,6 +249,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;
@@ -318,6 +324,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/f29e60f6/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/f29e60f6/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/f29e60f6/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 e740552..975ded0 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/f29e60f6/fit/enduser-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/enduser-reference/pom.xml b/fit/enduser-reference/pom.xml
index 61ddfd9..2cb3b8e 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/f29e60f6/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/f29e60f6/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/f29e60f6/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/f29e60f6/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 302cbb9..8a11868 100644
--- a/pom.xml
+++ b/pom.xml
@@ -636,6 +636,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/f29e60f6/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 ae749ce..4b709b9 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
[WARNING]
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/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 4c46ef1..2e2541b 100644
--- a/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc
+++ b/src/main/asciidoc/reference-guide/workingwithapachesyncope/customization.adoc
@@ -351,6 +351,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
[WARNING]
@@ -478,6 +497,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`:
@@ -516,6 +552,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
[4/8] syncope git commit: [SYNCOPE-1270] implementation for OpenID
Connect for Admin Console and Enduser
Posted by il...@apache.org.
[SYNCOPE-1270] implementation for OpenID Connect for Admin Console and Enduser
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/f29e60f6
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/f29e60f6
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/f29e60f6
Branch: refs/heads/2_0_X
Commit: f29e60f62f12bc7ec77ce6de4d2674db466a8f4f
Parents: 13f442a
Author: dayash <di...@tirasa.net>
Authored: Wed May 2 09:50:13 2018 +0200
Committer: dayash <di...@tirasa.net>
Committed: Thu May 3 16:16:14 2018 +0200
----------------------------------------------------------------------
archetype/pom.xml | 31 ++
.../archetype-resources/console/pom.xml | 6 +
.../resources/archetype-resources/core/pom.xml | 11 +
.../archetype-resources/enduser/pom.xml | 6 +
.../resources/META-INF/resources/app/index.html | 1 +
.../resources/META-INF/resources/app/js/app.js | 27 +-
.../app/js/controllers/LoginController.js | 2 +
.../app/js/services/oidcProviderService.js | 42 ++
.../META-INF/resources/app/views/self.html | 8 +
deb/console/pom.xml | 13 +
deb/console/src/deb/control/conffiles | 2 +
deb/enduser/pom.xml | 13 +
deb/enduser/src/deb/control/conffiles | 2 +
deb/enduser/src/deb/control/preinst | 1 +
ext/oidcclient/agent/pom.xml | 126 ++++++
.../ext/oidcclient/agent/CodeConsumer.java | 92 ++++
.../syncope/ext/oidcclient/agent/Constants.java | 40 ++
.../syncope/ext/oidcclient/agent/Login.java | 89 ++++
.../oidcclient/agent/OIDCClientAgentSetup.java | 77 ++++
.../resources/oidcclient/loginError.jsp | 35 ++
.../resources/oidcclient/loginSuccess.jsp | 33 ++
.../main/resources/META-INF/web-fragment.xml | 26 ++
.../main/resources/oidcclient-agent.properties | 26 ++
ext/oidcclient/client-console/pom.xml | 83 ++++
.../client/console/pages/OIDCClient.java | 68 +++
.../client/console/pages/OIDCClientLogin.java | 68 +++
.../panels/OIDCProvidersDirectoryPanel.java | 291 +++++++++++++
.../console/panels/OIDCSSOLoginFormPanel.java | 109 +++++
.../console/rest/OIDCProviderRestClient.java | 59 +++
.../wizards/OIDCProviderMappingPanel.java | 104 +++++
.../wizards/OIDCProviderWizardBuilder.java | 290 +++++++++++++
.../client/console/pages/OIDCClient.html | 37 ++
.../client/console/pages/OIDCClient.properties | 17 +
.../console/pages/OIDCClient_it.properties | 17 +
.../console/pages/OIDCClient_pt_BR.properties | 17 +
.../console/pages/OIDCClient_ru.properties | 17 +
.../panels/OIDCProvidersDirectoryPanel.html | 23 +
.../OIDCProvidersDirectoryPanel.properties | 30 ++
.../OIDCProvidersDirectoryPanel_it.properties | 30 ++
...OIDCProvidersDirectoryPanel_pt_BR.properties | 30 ++
.../OIDCProvidersDirectoryPanel_ru.properties | 30 ++
.../console/panels/OIDCSSOLoginFormPanel.html | 25 ++
.../OIDCProviderWizardBuilder$Mapping.html | 23 +
.../wizards/OIDCProviderWizardBuilder$OP.html | 28 ++
.../OIDCProviderWizardBuilder$OP.properties | 24 ++
.../OIDCProviderWizardBuilder$OPContinue.html | 33 ++
...CProviderWizardBuilder$OPContinue.properties | 27 ++
...oviderWizardBuilder$OPContinue_it.properties | 27 ++
...derWizardBuilder$OPContinue_pt_BR.properties | 27 ++
...oviderWizardBuilder$OPContinue_ru.properties | 27 ++
.../OIDCProviderWizardBuilder$OP_it.properties | 24 ++
...IDCProviderWizardBuilder$OP_pt_BR.properties | 24 ++
.../OIDCProviderWizardBuilder$OP_ru.properties | 24 ++
ext/oidcclient/client-enduser/pom.xml | 83 ++++
.../client/enduser/pages/OIDCClientLogin.java | 63 +++
.../resources/OIDCProvidersResource.java | 72 ++++
ext/oidcclient/common-lib/pom.xml | 56 +++
.../syncope/common/lib/OIDCConstants.java | 45 ++
.../common/lib/to/OIDCLoginRequestTO.java | 91 ++++
.../common/lib/to/OIDCLoginResponseTO.java | 140 +++++++
.../syncope/common/lib/to/OIDCProviderTO.java | 229 ++++++++++
.../common/lib/types/OIDCClientEntitlement.java | 57 +++
ext/oidcclient/logic/pom.xml | 76 ++++
.../syncope/core/logic/OIDCClientLogic.java | 418 +++++++++++++++++++
.../syncope/core/logic/OIDCProviderLogic.java | 177 ++++++++
...ClientClassPathScanImplementationLookup.java | 78 ++++
.../core/logic/init/OIDCClientLoader.java | 55 +++
.../model/OIDCProviderDiscoveryDocument.java | 128 ++++++
.../core/logic/model/TokenEndpointResponse.java | 86 ++++
.../core/logic/oidc/OIDCUserManager.java | 306 ++++++++++++++
ext/oidcclient/persistence-api/pom.xml | 61 +++
.../persistence/api/dao/OIDCProviderDAO.java | 35 ++
.../api/entity/OIDCEntityFactory.java | 25 ++
.../persistence/api/entity/OIDCProvider.java | 84 ++++
.../api/entity/OIDCProviderItem.java | 29 ++
.../api/entity/OIDCUserTemplate.java | 27 ++
ext/oidcclient/persistence-jpa/pom.xml | 134 ++++++
.../persistence/jpa/dao/JPAOIDCProviderDAO.java | 78 ++++
.../jpa/entity/JPAOIDCEntityFactory.java | 49 +++
.../persistence/jpa/entity/JPAOIDCProvider.java | 257 ++++++++++++
.../jpa/entity/JPAOIDCProviderItem.java | 74 ++++
.../jpa/entity/JPAOIDCUserTemplate.java | 52 +++
ext/oidcclient/pom.xml | 55 +++
ext/oidcclient/provisioning-api/pom.xml | 67 +++
.../provisioning/api/OIDCProviderActions.java | 35 ++
.../api/data/OIDCProviderDataBinder.java | 32 ++
ext/oidcclient/provisioning-java/pom.xml | 61 +++
.../java/DefaultOIDCProviderActions.java | 48 +++
.../java/data/OIDCProviderDataBinderImpl.java | 266 ++++++++++++
ext/oidcclient/rest-api/pom.xml | 77 ++++
.../rest/api/service/OIDCClientService.java | 74 ++++
.../rest/api/service/OIDCProviderService.java | 151 +++++++
ext/oidcclient/rest-cxf/pom.xml | 72 ++++
.../rest/cxf/service/OIDCClientServiceImpl.java | 44 ++
.../cxf/service/OIDCProviderServiceImpl.java | 83 ++++
ext/pom.xml | 1 +
.../syncope/ext/saml2lsp/agent/Login.java | 2 +-
fit/console-reference/pom.xml | 6 +
.../main/resources/oidcclient-agent.properties | 26 ++
.../src/main/webapp/WEB-INF/web.xml | 10 +
.../src/test/resources/rebel.xml | 8 +
fit/core-reference/pom.xml | 23 +
.../org/apache/syncope/fit/AbstractITCase.java | 8 +
.../apache/syncope/fit/OIDCClientDetector.java | 52 +++
.../syncope/fit/core/OIDCClientITCase.java | 152 +++++++
fit/core-reference/src/test/resources/rebel.xml | 17 +
fit/enduser-reference/pom.xml | 6 +
.../main/resources/oidcclient-agent.properties | 26 ++
.../src/main/webapp/WEB-INF/web.xml | 10 +
.../src/test/resources/rebel.xml | 8 +
pom.xml | 10 +
.../reference-guide/concepts/extensions.adoc | 33 ++
.../workingwithapachesyncope/customization.adoc | 52 +++
113 files changed, 6920 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/archetype/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/pom.xml b/archetype/pom.xml
index baf1272..ee4d3fa 100644
--- a/archetype/pom.xml
+++ b/archetype/pom.xml
@@ -233,6 +233,13 @@ under the License.
</includes>
</resource>
<resource>
+ <directory>../ext/oidcclient/agent/src/main/resources</directory>
+ <targetPath>${project.build.outputDirectory}/archetype-resources/console/src/main/resources/all</targetPath>
+ <includes>
+ <include>oidcclient-agent.properties</include>
+ </includes>
+ </resource>
+ <resource>
<directory>../fit/console-reference/src/main/resources</directory>
<targetPath>${project.build.outputDirectory}/archetype-resources/console/src/main/resources</targetPath>
<includes>
@@ -250,6 +257,14 @@ under the License.
</includes>
</resource>
<resource>
+ <directory>../fit/console-reference/src/main/resources</directory>
+ <targetPath>${project.build.outputDirectory}/archetype-resources/console/src/test/resources</targetPath>
+ <includes>
+ <include>console.properties</include>
+ <include>oidcclient-agent.properties</include>
+ </includes>
+ </resource>
+ <resource>
<directory>../fit/console-reference/src/main/webapp/WEB-INF</directory>
<targetPath>${project.build.outputDirectory}/archetype-resources/console/src/main/webapp/WEB-INF</targetPath>
</resource>
@@ -270,6 +285,13 @@ under the License.
</includes>
</resource>
<resource>
+ <directory>../ext/oidcclient/agent/src/main/resources</directory>
+ <targetPath>${project.build.outputDirectory}/archetype-resources/enduser/src/main/resources/all</targetPath>
+ <includes>
+ <include>oidcclient-agent.properties</include>
+ </includes>
+ </resource>
+ <resource>
<directory>../client/enduser/src/main/resources/META-INF/resources/app</directory>
<targetPath>${project.build.outputDirectory}/archetype-resources/enduser/src/main/webapp/app</targetPath>
</resource>
@@ -290,6 +312,15 @@ under the License.
</includes>
</resource>
<resource>
+ <directory>../fit/enduser-reference/src/main/resources</directory>
+ <targetPath>${project.build.outputDirectory}/archetype-resources/enduser/src/test/resources</targetPath>
+ <includes>
+ <include>enduser.properties</include>
+ <include>oidcclient-agent.properties</include>
+ <include>customForm.json</include>
+ </includes>
+ </resource>
+ <resource>
<directory>../fit/enduser-reference/src/main/webapp/WEB-INF</directory>
<targetPath>${project.build.outputDirectory}/archetype-resources/enduser/src/main/webapp/WEB-INF</targetPath>
</resource>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/archetype/src/main/resources/archetype-resources/console/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/src/main/resources/archetype-resources/console/pom.xml b/archetype/src/main/resources/archetype-resources/console/pom.xml
index 8506fa9..287562a 100644
--- a/archetype/src/main/resources/archetype-resources/console/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/console/pom.xml
@@ -141,6 +141,12 @@ under the License.
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-console</artifactId>
+ <version>${syncope.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.syncope.ext.scimv2</groupId>
<artifactId>syncope-ext-scimv2-client-console</artifactId>
<version>${syncope.version}</version>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/archetype/src/main/resources/archetype-resources/core/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/src/main/resources/archetype-resources/core/pom.xml b/archetype/src/main/resources/archetype-resources/core/pom.xml
index 3f3ef73..a24b17d 100644
--- a/archetype/src/main/resources/archetype-resources/core/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/core/pom.xml
@@ -193,6 +193,17 @@ under the License.
</dependency>
<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>
+
+ <dependency>
<groupId>org.apache.syncope.ext.scimv2</groupId>
<artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
<version>${syncope.version}</version>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/archetype/src/main/resources/archetype-resources/enduser/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/src/main/resources/archetype-resources/enduser/pom.xml b/archetype/src/main/resources/archetype-resources/enduser/pom.xml
index 2f9943c..4e8826c 100644
--- a/archetype/src/main/resources/archetype-resources/enduser/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/enduser/pom.xml
@@ -332,6 +332,12 @@ under the License.
<artifactId>syncope-ext-saml2sp-client-enduser</artifactId>
<version>${syncope.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-enduser</artifactId>
+ <version>${syncope.version}</version>
+ </dependency>
</dependencies>
<build>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/client/enduser/src/main/resources/META-INF/resources/app/index.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/index.html b/client/enduser/src/main/resources/META-INF/resources/app/index.html
index cd4542a..2613a6e 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/index.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/index.html
@@ -100,6 +100,7 @@ under the License.
<script src="js/services/groupService.js"></script>
<script src="js/services/anyService.js"></script>
<script src="js/services/saml2IdPService.js"></script>
+ <script src="js/services/oidcProviderService.js"></script>
<script src="js/services/saml2SPService.js"></script>
<!--controllers-->
<script src="js/controllers/HomeController.js"></script>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
index 3ae4f9d..1019cad 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
@@ -341,7 +341,8 @@ app.run(['$rootScope', '$location', '$state', 'AuthService',
};
}]);
app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'InfoService', 'SAML2IdPService',
- function ($scope, $rootScope, $location, InfoService, SAML2IdPService) {
+ 'OIDCProviderService',
+ function ($scope, $rootScope, $location, InfoService, SAML2IdPService, OIDCProviderService) {
$scope.initApplication = function () {
/*
* disable by default wizard buttons in self-registration
@@ -377,6 +378,10 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I
available: [],
selected: {}
};
+ $rootScope.oidcops = {
+ available: [],
+ selected: {}
+ };
InfoService.getInfo().then(
function (response) {
@@ -406,6 +411,19 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I
/*
* configuration getters
*/
+
+ /* <Extensions> */
+ OIDCProviderService.getAvailableOIDCProviders().then(
+ function (response) {
+ $rootScope.oidcops.available = response;
+ },
+ function (response) {
+ console.debug("No OIDC Client extension available", response);
+ });
+ /* </Extensions> */
+ /*
+ * configuration getters
+ */
$rootScope.isSelfRegAllowed = function () {
return $rootScope.selfRegAllowed === true;
};
@@ -418,6 +436,13 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I
$rootScope.saml2login = function () {
window.location.href = '../saml2sp/login?idp=' + $rootScope.saml2idps.selected.entityID;
};
+
+ $rootScope.oidcclientExtAvailable = function () {
+ return $rootScope.oidcops.available.length > 0;
+ };
+ $rootScope.oidclogin = function () {
+ window.location.href = '../oidcclient/login?op=' + $rootScope.oidcops.selected.name;
+ };
$rootScope.getVersion = function () {
return $rootScope.version;
};
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
index b58aced..d2b755c 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
@@ -34,6 +34,8 @@ angular.module("login").controller("LoginController", ['$scope', '$rootScope', '
$scope.credentials.errorMessage = '';
// reset SAML 2.0 entityID
$rootScope.saml2idps.selected.entityID = null;
+ // reset OIDC name
+ $rootScope.oidcops.selected.name = null;
// got to update page
$location.path("/self/update");
}, function (response) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/client/enduser/src/main/resources/META-INF/resources/app/js/services/oidcProviderService.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/oidcProviderService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/oidcProviderService.js
new file mode 100644
index 0000000..d2ce926
--- /dev/null
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/oidcProviderService.js
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+angular.module('self')
+ .factory('OIDCProviderService', ['$resource', '$q', '$http',
+ function ($resource, $q, $http) {
+
+ var oidcProviderService = {};
+
+ oidcProviderService.getAvailableOIDCProviders = function () {
+ return $http.get("../api/oidcProviders")
+ .then(function (response) {
+ return response.data;
+ }, function (response) {
+ console.error("Something went wrong during oidcProviders extension retrieval, exit with status: ",
+ response);
+ return $q.reject(response.data || response.statusText);
+ });
+ };
+
+ return oidcProviderService;
+ }]);
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/self.html b/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
index 1cc279e..cedb21c 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
@@ -62,6 +62,14 @@ under the License.
ng-model="saml2idps.selected" ng-change="saml2login()">
</select>
</div>
+ <div class="form-group">
+ <span ng-if="$root.oidcclientExtAvailable()">OpenID Connect</span>
+ <select id="oiscclient" style="width: 100%; text-align: left;" class="btn dropdown-toggle btn-default"
+ ng-if="$root.oidcclientExtAvailable()"
+ ng-options="op.name for op in oidcops.available track by op.name"
+ ng-model="oidcops.selected" ng-change="oidclogin()">
+ </select>
+ </div>
</fieldset>
</form>
</div>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/deb/console/pom.xml
----------------------------------------------------------------------
diff --git a/deb/console/pom.xml b/deb/console/pom.xml
index 9688af6..8898ce3 100644
--- a/deb/console/pom.xml
+++ b/deb/console/pom.xml
@@ -55,6 +55,11 @@ under the License.
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-console</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.syncope.ext.scimv2</groupId>
<artifactId>syncope-ext-scimv2-client-console</artifactId>
<version>${project.version}</version>
@@ -116,6 +121,14 @@ under the License.
<filtering>true</filtering>
</resource>
<resource>
+ <directory>${project.basedir}/../../ext/oidcclient/agent/src/main/resources</directory>
+ <includes>
+ <include>oidcclient-agent.properties</include>
+ </includes>
+ <targetPath>${project.build.directory}/etc</targetPath>
+ <filtering>true</filtering>
+ </resource>
+ <resource>
<directory>${basedir}/../../fit/console-reference/src/main/resources</directory>
<includes>
<include>log4j2.xml</include>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/deb/console/src/deb/control/conffiles
----------------------------------------------------------------------
diff --git a/deb/console/src/deb/control/conffiles b/deb/console/src/deb/control/conffiles
index 47e5201..a9bfb08 100644
--- a/deb/console/src/deb/control/conffiles
+++ b/deb/console/src/deb/control/conffiles
@@ -1,3 +1,5 @@
/etc/tomcat8/Catalina/localhost/syncope-console.xml
/etc/apache-syncope/console.properties
/etc/apache-syncope/saml2sp-agent.properties
+/etc/apache-syncope/oidcclient-agent.properties
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/deb/enduser/pom.xml
----------------------------------------------------------------------
diff --git a/deb/enduser/pom.xml b/deb/enduser/pom.xml
index fc2ce00..64505df 100644
--- a/deb/enduser/pom.xml
+++ b/deb/enduser/pom.xml
@@ -44,6 +44,11 @@ under the License.
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-enduser</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.syncope.client</groupId>
<artifactId>syncope-client-enduser</artifactId>
<version>${project.version}</version>
@@ -106,6 +111,14 @@ under the License.
<filtering>true</filtering>
</resource>
<resource>
+ <directory>${project.basedir}/../../ext/oidcclient/agent/src/main/resources</directory>
+ <includes>
+ <include>oidcclient-agent.properties</include>
+ </includes>
+ <targetPath>${project.build.directory}/etc</targetPath>
+ <filtering>true</filtering>
+ </resource>
+ <resource>
<directory>${basedir}/../../fit/enduser-reference/src/main/resources</directory>
<includes>
<include>log4j2.xml</include>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/deb/enduser/src/deb/control/conffiles
----------------------------------------------------------------------
diff --git a/deb/enduser/src/deb/control/conffiles b/deb/enduser/src/deb/control/conffiles
index 934c7fb..8fb2453 100644
--- a/deb/enduser/src/deb/control/conffiles
+++ b/deb/enduser/src/deb/control/conffiles
@@ -2,3 +2,5 @@
/etc/apache-syncope/enduser.properties
/etc/apache-syncope/customForm.json
/etc/apache-syncope/saml2sp-agent.properties
+/etc/apache-syncope/oidcclient-agent.properties
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/deb/enduser/src/deb/control/preinst
----------------------------------------------------------------------
diff --git a/deb/enduser/src/deb/control/preinst b/deb/enduser/src/deb/control/preinst
index afdca38..0e88785 100644
--- a/deb/enduser/src/deb/control/preinst
+++ b/deb/enduser/src/deb/control/preinst
@@ -16,3 +16,4 @@
# specific language governing permissions and limitations
# under the License.
dpkg-divert --add --package apache-syncope-enduser --rename --divert /etc/apache-syncope/saml2sp-agent.properties.disabled /etc/apache-syncope/saml2sp-agent.properties
+dpkg-divert --add --package apache-syncope-enduser --rename --divert /etc/apache-syncope/oidcclient-agent.properties.disabled /etc/apache-syncope/oidcclient-agent.properties
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/agent/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/pom.xml b/ext/oidcclient/agent/pom.xml
new file mode 100644
index 0000000..adb83d1
--- /dev/null
+++ b/ext/oidcclient/agent/pom.xml
@@ -0,0 +1,126 @@
+<?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.0.9-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client Agent</name>
+ <description>Apache Syncope Ext: OIDC Client Agent</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-agent</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>javax.servlet.jsp-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.client</groupId>
+ <artifactId>syncope-client-lib</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>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+
+ <resource>
+ <directory>${basedir}</directory>
+ <targetPath>META-INF</targetPath>
+ <includes>
+ <include>LICENSE</include>
+ <include>NOTICE</include>
+ </includes>
+ </resource>
+ </resources>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>apache-release</id>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <inherited>false</inherited>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ <configuration>
+ <includes>
+ <include>${basedir}/LICENSE</include>
+ <include>${basedir}/NOTICE</include>
+ </includes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/CodeConsumer.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/CodeConsumer.java b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/CodeConsumer.java
new file mode 100644
index 0000000..08e9d23
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/CodeConsumer.java
@@ -0,0 +1,92 @@
+/*
+ * 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.ext.oidcclient.agent;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.OIDCConstants;
+import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
+import org.apache.syncope.common.rest.api.service.OIDCClientService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@WebServlet(name = "codeConsumer", urlPatterns = { "/oidcclient/code-consumer" })
+public class CodeConsumer extends HttpServlet {
+
+ private static final long serialVersionUID = 968480296813639041L;
+
+ protected static final Logger LOG = LoggerFactory.getLogger(CodeConsumer.class);
+
+ @Override
+ protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
+ throws ServletException, IOException {
+
+ try {
+ String authorizationCode = request.getParameter(OIDCConstants.CODE);
+ String state = request.getParameter(OIDCConstants.STATE);
+ if (StringUtils.isBlank(authorizationCode) || StringUtils.isBlank(state)) {
+ throw new IllegalArgumentException("Empty " + OIDCConstants.CODE + " or " + OIDCConstants.STATE);
+ }
+ if (state.equals(request.getSession().getAttribute(OIDCConstants.STATE).toString())) {
+ SyncopeClient anonymous = (SyncopeClient) request.getServletContext().
+ getAttribute(Constants.SYNCOPE_ANONYMOUS_CLIENT);
+
+ OIDCLoginResponseTO responseTO = anonymous.getService(OIDCClientService.class).login(
+ request.getRequestURL().toString(),
+ authorizationCode,
+ request.getSession().getAttribute(OIDCConstants.OP).toString());
+ request.getSession().setAttribute(
+ Constants.OIDCCLIENTJWT, responseTO.getAccessToken());
+ request.getSession().setAttribute(
+ Constants.OIDCCLIENTJWT_EXPIRE, responseTO.getAccessTokenExpiryTime());
+
+ String successURL = getServletContext().getInitParameter(Constants.CONTEXT_PARAM_LOGIN_SUCCESS_URL);
+ if (successURL == null) {
+ request.setAttribute("responseTO", responseTO);
+ request.getRequestDispatcher("loginSuccess.jsp").forward(request, response);
+ } else {
+ response.sendRedirect(successURL);
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid " + OIDCConstants.STATE + " provided");
+ }
+ } catch (Exception e) {
+ LOG.error("While processing authentication response from OP", e);
+ String errorURL = getServletContext().getInitParameter(Constants.CONTEXT_PARAM_LOGIN_ERROR_URL);
+
+ if (errorURL == null) {
+ request.setAttribute("exception", e);
+ request.getRequestDispatcher("loginError.jsp").forward(request, response);
+
+ e.printStackTrace(response.getWriter());
+ } else {
+ response.sendRedirect(errorURL + "?errorMessage="
+ + URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8.name()));
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Constants.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Constants.java b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Constants.java
new file mode 100644
index 0000000..1ff3327
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Constants.java
@@ -0,0 +1,40 @@
+/*
+ * 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.ext.oidcclient.agent;
+
+public final class Constants {
+
+ public static final String SYNCOPE_ANONYMOUS_CLIENT = "SyncopeAnonymousClient";
+
+ public static final String SYNCOPE_CLIENT_FACTORY = "SyncopeClientFactory";
+
+ public static final String PARAM_OP = "op";
+
+ public static final String CONTEXT_PARAM_LOGIN_SUCCESS_URL = "oidcclient.login.success.url";
+
+ public static final String CONTEXT_PARAM_LOGIN_ERROR_URL = "oidcclient.login.error.url";
+
+ public static final String OIDCCLIENTJWT = "oidcclient.jwt";
+
+ public static final String OIDCCLIENTJWT_EXPIRE = "oidcclient.jwt.expire";
+
+ private Constants() {
+ // private constructor for static utility class
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Login.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Login.java b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Login.java
new file mode 100644
index 0000000..36850e4
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Login.java
@@ -0,0 +1,89 @@
+/*
+ * 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.ext.oidcclient.agent;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriBuilder;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.OIDCConstants;
+import org.apache.syncope.common.lib.to.OIDCLoginRequestTO;
+import org.apache.syncope.common.rest.api.service.OIDCClientService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@WebServlet(name = "oidcclientLogin", urlPatterns = { "/oidcclient/login" })
+public class Login extends HttpServlet {
+
+ private static final long serialVersionUID = 968480296813639041L;
+
+ protected static final Logger LOG = LoggerFactory.getLogger(Login.class);
+
+ @Override
+ protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
+ throws ServletException, IOException {
+
+ String op = request.getParameter(Constants.PARAM_OP);
+
+ SyncopeClient anonymous = (SyncopeClient) request.getServletContext().
+ getAttribute(Constants.SYNCOPE_ANONYMOUS_CLIENT);
+ try {
+ String redirectURI = StringUtils.substringBefore(request.getRequestURL().toString(), "/login")
+ + "/code-consumer";
+ OIDCLoginRequestTO requestTO = anonymous.getService(OIDCClientService.class).
+ createLoginRequest(redirectURI, op);
+
+ request.getSession().setAttribute(OIDCConstants.STATE, requestTO.getState());
+ request.getSession().setAttribute(OIDCConstants.OP, op);
+
+ response.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache, no-store");
+ response.setHeader("Pragma", "no-cache");
+ response.setStatus(HttpServletResponse.SC_SEE_OTHER);
+
+ UriBuilder ub = UriBuilder.fromUri(requestTO.getProviderAddress());
+ ub.queryParam(OIDCConstants.CLIENT_ID, requestTO.getClientId());
+ ub.queryParam(OIDCConstants.REDIRECT_URI, requestTO.getRedirectURI());
+ ub.queryParam(OIDCConstants.RESPOSNSE_TYPE, requestTO.getResponseType());
+ ub.queryParam(OIDCConstants.SCOPE, requestTO.getScope());
+ ub.queryParam(OIDCConstants.STATE, requestTO.getState());
+ response.setHeader("Location", ub.build().toASCIIString());
+ } catch (Exception e) {
+ LOG.error("While preparing the Authentication Request", e);
+
+ String errorURL = getServletContext().getInitParameter(Constants.CONTEXT_PARAM_LOGIN_ERROR_URL);
+ if (errorURL == null) {
+ request.setAttribute("exception", e);
+ request.getRequestDispatcher("loginError.jsp").forward(request, response);
+
+ e.printStackTrace(response.getWriter());
+ } else {
+ response.sendRedirect(errorURL + "?errorMessage="
+ + URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8.name()));
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/OIDCClientAgentSetup.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/OIDCClientAgentSetup.java b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/OIDCClientAgentSetup.java
new file mode 100644
index 0000000..887d0d6
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/OIDCClientAgentSetup.java
@@ -0,0 +1,77 @@
+/*
+ * 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.ext.oidcclient.agent;
+
+import java.util.Properties;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.PropertyUtils;
+
+@WebListener
+public class OIDCClientAgentSetup implements ServletContextListener {
+
+ private static final String OIDCCLIENT_AGENT_PROPERTIES = "oidcclient-agent.properties";
+
+ private static <T> T assertNotNull(final T argument, final String name) {
+ if (argument == null) {
+ throw new IllegalArgumentException("Argument '" + name + "' may not be null.");
+ }
+ return argument;
+ }
+
+ @Override
+ public void contextInitialized(final ServletContextEvent sce) {
+ // read oidcclientagent.properties
+ Properties props = PropertyUtils.read(getClass(), OIDCCLIENT_AGENT_PROPERTIES, "conf.directory").getLeft();
+
+ String anonymousUser = props.getProperty("anonymousUser");
+ assertNotNull(anonymousUser, "<anonymousUser>");
+ String anonymousKey = props.getProperty("anonymousKey");
+ assertNotNull(anonymousKey, "<anonymousKey>");
+
+ String scheme = props.getProperty("scheme");
+ assertNotNull(scheme, "<scheme>");
+ String host = props.getProperty("host");
+ assertNotNull(host, "<host>");
+ String port = props.getProperty("port");
+ assertNotNull(port, "<port>");
+ String rootPath = props.getProperty("rootPath");
+ assertNotNull(rootPath, "<rootPath>");
+ String useGZIPCompression = props.getProperty("useGZIPCompression");
+ assertNotNull(useGZIPCompression, "<useGZIPCompression>");
+
+ SyncopeClientFactoryBean clientFactory = new SyncopeClientFactoryBean().
+ setAddress(scheme + "://" + host + ":" + port + "/" + rootPath).
+ setUseCompression(BooleanUtils.toBoolean(useGZIPCompression));
+
+ sce.getServletContext().setAttribute(Constants.SYNCOPE_CLIENT_FACTORY, clientFactory);
+ sce.getServletContext().setAttribute(
+ Constants.SYNCOPE_ANONYMOUS_CLIENT,
+ clientFactory.create(new AnonymousAuthenticationHandler(anonymousUser, anonymousKey)));
+ }
+
+ @Override
+ public void contextDestroyed(final ServletContextEvent sce) {
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginError.jsp
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginError.jsp b/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginError.jsp
new file mode 100644
index 0000000..b3c80d9
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginError.jsp
@@ -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.
+--%>
+<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
+<%
+ Exception exception = (Exception) request.getAttribute("exception");
+%>
+<html>
+ <head>
+ <title>Apache Syncope ${syncope.version} - OIDC CLIENT - Login Error</title>
+ </head>
+ <body>
+ <h1>An error was found</h1>
+
+ <h2><%=exception.getMessage()%></h2>
+ <pre>
+ <%exception.printStackTrace(new java.io.PrintWriter(out));%>
+ </pre>
+ </body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginSuccess.jsp
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginSuccess.jsp b/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginSuccess.jsp
new file mode 100644
index 0000000..7361842
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginSuccess.jsp
@@ -0,0 +1,33 @@
+<%--
+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.
+--%>
+<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
+<%@page import="org.apache.syncope.common.lib.to.OIDCLoginResponseTO"%>
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<c:set var="responseTO" value="${requestScope['responseTO']}"/>
+<html>
+ <head>
+ <title>Apache Syncope ${syncope.version} - OIDC CLIENT - Successful Login</title>
+ </head>
+ <body>
+ <h1>Welcome ${responseTO.userName}</h1>
+
+ <p>You have been successfully authenticated by the requested OIDC Provider</p>
+
+ </body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/agent/src/main/resources/META-INF/web-fragment.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/resources/META-INF/web-fragment.xml b/ext/oidcclient/agent/src/main/resources/META-INF/web-fragment.xml
new file mode 100644
index 0000000..fab858a
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/resources/META-INF/web-fragment.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<web-fragment xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+ http://xmlns.jcp.org/xml/ns/javaee/web-fragment_3_1.xsd"
+ id="${pom.artifactId}" version="3.1">
+
+</web-fragment>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/agent/src/main/resources/oidcclient-agent.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/resources/oidcclient-agent.properties b/ext/oidcclient/agent/src/main/resources/oidcclient-agent.properties
new file mode 100644
index 0000000..d3fee30
--- /dev/null
+++ b/ext/oidcclient/agent/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=8080
+rootPath=/syncope/rest/
+useGZIPCompression=true
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/pom.xml b/ext/oidcclient/client-console/pom.xml
new file mode 100644
index 0000000..51b190b
--- /dev/null
+++ b/ext/oidcclient/client-console/pom.xml
@@ -0,0 +1,83 @@
+<?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.0.9-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client Console</name>
+ <description>Apache Syncope Ext: OIDC Client Console</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-console</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-common-lib</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-agent</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.client</groupId>
+ <artifactId>syncope-client-console</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClient.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClient.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClient.java
new file mode 100644
index 0000000..f588733
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClient.java
@@ -0,0 +1,68 @@
+/*
+ * 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.client.console.pages;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.annotations.ExtPage;
+import org.apache.syncope.client.console.panels.OIDCProvidersDirectoryPanel;
+import org.apache.syncope.common.lib.types.OIDCClientEntitlement;
+import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+@ExtPage(label = "OIDC Client", icon = "fa-openid ", listEntitlement = OIDCClientEntitlement.OP_READ, priority = 100)
+public class OIDCClient extends BaseExtPage {
+
+ private static final long serialVersionUID = -599601954212606001L;
+
+ public OIDCClient(final PageParameters parameters) {
+ super(parameters);
+
+ body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class));
+
+ WebMarkupContainer content = new WebMarkupContainer("content");
+ content.setOutputMarkupId(true);
+ content.add(new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList()));
+ body.add(content);
+ }
+
+ private List<ITab> buildTabList() {
+
+ final List<ITab> tabs = new ArrayList<>(1);
+
+ tabs.add(new AbstractTab(new ResourceModel("op")) {
+ private static final long serialVersionUID = -6815067322125799251L;
+
+
+ @Override
+ public Panel getPanel(final String panelId) {
+ return new OIDCProvidersDirectoryPanel(panelId, getPageReference());
+ }
+ });
+
+ return tabs;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClientLogin.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClientLogin.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClientLogin.java
new file mode 100644
index 0000000..41b6cdc
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClientLogin.java
@@ -0,0 +1,68 @@
+/*
+ * 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.client.console.pages;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+
+import org.apache.wicket.authentication.IAuthenticationStrategy;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OIDCClientLogin extends WebPage {
+
+ private static final long serialVersionUID = 8581614051773949262L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(OIDCClientLogin.class);
+
+ private static final String OIDC_ACCESS_ERROR = "OIDC access error";
+
+ public OIDCClientLogin(final PageParameters parameters) {
+ super(parameters);
+
+ String token = (String) ((ServletWebRequest) getRequest()).getContainerRequest().
+ getSession().getAttribute(org.apache.syncope.ext.oidcclient.agent.Constants.OIDCCLIENTJWT);
+ if (StringUtils.isBlank(token)) {
+ LOG.error("No JWT found, redirecting to default greeter");
+
+ PageParameters params = new PageParameters();
+ params.add("errorMessage", OIDC_ACCESS_ERROR);
+ setResponsePage(Login.class, params);
+ }
+
+ IAuthenticationStrategy strategy = getApplication().getSecuritySettings().getAuthenticationStrategy();
+
+ if (SyncopeConsoleSession.get().authenticate(token)) {
+
+ // If login has been called because the user was not yet logged in, than continue to the
+ // original destination, otherwise to the Home page
+ continueToOriginalDestination();
+ setResponsePage(getApplication().getHomePage());
+ } else {
+ PageParameters params = new PageParameters();
+ params.add("errorMessage", OIDC_ACCESS_ERROR);
+ setResponsePage(Login.class, params);
+ }
+ strategy.remove();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java
new file mode 100644
index 0000000..dd66cc6
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java
@@ -0,0 +1,291 @@
+/*
+ * 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.client.console.panels;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.DirectoryDataProvider;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.console.pages.BasePage;
+import org.apache.syncope.client.console.panels.OIDCProvidersDirectoryPanel.OIDCProvidersProvider;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
+import org.apache.syncope.client.console.rest.OIDCProviderRestClient;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.KeyPropertyColumn;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksTogglePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
+import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.console.wizards.OIDCProviderWizardBuilder;
+import org.apache.syncope.client.console.wizards.WizardMgtPanel;
+import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.console.wizards.any.UserTemplateWizardBuilder;
+import org.apache.syncope.common.lib.SyncopeClientException;
+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.OIDCClientEntitlement;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.StringResourceModel;
+
+public class OIDCProvidersDirectoryPanel extends DirectoryPanel<
+ OIDCProviderTO, OIDCProviderTO, OIDCProvidersProvider, OIDCProviderRestClient> {
+
+ private static final long serialVersionUID = -1356497878858616714L;
+
+ private static final String PREF_OIDC_PROVIDERS_PAGINATOR_ROWS = "oidc.providers.paginator.rows";
+
+ private final BaseModal<Serializable> templateModal;
+
+ public OIDCProvidersDirectoryPanel(final String id, final PageReference pageRef) {
+ super(id, new Builder<OIDCProviderTO, OIDCProviderTO, OIDCProviderRestClient>(new OIDCProviderRestClient(),
+ pageRef) {
+
+ private static final long serialVersionUID = -5542535388772406165L;
+
+ @Override
+ protected WizardMgtPanel<OIDCProviderTO> newInstance(final String id, final boolean wizardInModal) {
+ throw new UnsupportedOperationException();
+ }
+ }.disableCheckBoxes());
+
+ this.addNewItemPanelBuilder(new OIDCProviderWizardBuilder(this, new OIDCProviderTO(), pageRef), true);
+ MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, OIDCClientEntitlement.OP_CREATE);
+
+ modal.size(Modal.Size.Large);
+
+ actionTogglePanel = new ActionLinksTogglePanel<OIDCProviderTO>("outer", pageRef) {
+
+ private static final long serialVersionUID = -7688359318035249200L;
+
+ @Override
+ public void toggleWithContent(
+ final AjaxRequestTarget target,
+ final ActionsPanel<OIDCProviderTO> actionsPanel,
+ final OIDCProviderTO modelObject) {
+
+ super.toggleWithContent(target, actionsPanel, modelObject);
+ setHeader(target, StringUtils.abbreviate(modelObject.getName(), 25));
+ this.toggle(target, true);
+ }
+
+ };
+ addOuterObject(actionTogglePanel);
+
+ templateModal = new BaseModal<Serializable>("outer") {
+
+ private static final long serialVersionUID = 5787433530654262016L;
+
+ @Override
+ protected void onConfigure() {
+ super.onConfigure();
+ setFooterVisible(false);
+ }
+ };
+ templateModal.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
+
+ private static final long serialVersionUID = 8804221891699487139L;
+
+ @Override
+ public void onClose(final AjaxRequestTarget target) {
+// target.add(content);
+ templateModal.show(false);
+ }
+ });
+ templateModal.size(Modal.Size.Large);
+ addOuterObject(templateModal);
+
+ initResultTable();
+
+ }
+
+ @Override
+ protected OIDCProvidersProvider dataProvider() {
+ return new OIDCProvidersProvider(rows);
+ }
+
+ @Override
+ protected String paginatorRowsKey() {
+ return PREF_OIDC_PROVIDERS_PAGINATOR_ROWS;
+
+ }
+
+ @Override
+ protected List<IColumn<OIDCProviderTO, String>> getColumns() {
+ List<IColumn<OIDCProviderTO, String>> columns = new ArrayList<>();
+ columns.add(new KeyPropertyColumn<OIDCProviderTO>(new ResourceModel("key"), "key", "key"));
+ columns.add(new PropertyColumn<OIDCProviderTO, String>(new ResourceModel("name"), "name", "name"));
+ columns.add(new PropertyColumn<OIDCProviderTO, String>(new ResourceModel("issuer"), "issuer", "issuer"));
+ columns.add(new PropertyColumn<OIDCProviderTO, String>(new ResourceModel("clientID"), "clientID", "clientID"));
+ return columns;
+
+ }
+
+ @Override
+ protected Collection<ActionLink.ActionType> getBulkActions() {
+ return Collections.<ActionLink.ActionType>emptyList();
+
+ }
+
+ @Override
+ public ActionsPanel<OIDCProviderTO> getActions(final IModel<OIDCProviderTO> model) {
+ final ActionsPanel<OIDCProviderTO> panel = super.getActions(model);
+
+ panel.add(new ActionLink<OIDCProviderTO>() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target, final OIDCProviderTO ignore) {
+ OIDCProviderTO object = restClient.read(model.getObject().getKey());
+ send(OIDCProvidersDirectoryPanel.this, Broadcast.EXACT,
+ new AjaxWizard.EditItemActionEvent<>(object, target));
+ modal.header(Model.of(StringUtils.capitalize(("Edit " + object.getName()))));
+ }
+ }, ActionLink.ActionType.EDIT, OIDCClientEntitlement.OP_UPDATE);
+
+ panel.add(new ActionLink<OIDCProviderTO>() {
+
+ private static final long serialVersionUID = 8557679125857348178L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target, final OIDCProviderTO ignore) {
+ final OIDCProviderTO object = restClient.read(model.getObject().getKey());
+
+ UserTemplateWizardBuilder builder = new UserTemplateWizardBuilder(
+ object.getUserTemplate(),
+ new AnyTypeRestClient().read(AnyTypeKind.USER.name()).getClasses(),
+ new UserFormLayoutInfo(),
+ pageRef) {
+
+ private static final long serialVersionUID = -7978723352517770634L;
+
+ @Override
+ protected Serializable onApplyInternal(final AnyWrapper<UserTO> modelObject) {
+ object.setUserTemplate(modelObject.getInnerObject());
+ restClient.update(object);
+
+ return modelObject;
+ }
+ };
+ templateModal.header(Model.of(StringUtils.capitalize(
+ new StringResourceModel("template.title", OIDCProvidersDirectoryPanel.this).getString())));
+ templateModal.setContent(builder.build(BaseModal.CONTENT_ID));
+ templateModal.show(true);
+ target.add(templateModal);
+
+ }
+ }, ActionLink.ActionType.TEMPLATE, OIDCClientEntitlement.OP_UPDATE);
+
+ panel.add(new ActionLink<OIDCProviderTO>() {
+
+ private static final long serialVersionUID = -5467832321897812767L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target, final OIDCProviderTO ignore) {
+ try {
+ restClient.delete(model.getObject().getKey());
+ SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+ target.add(container);
+ } catch (SyncopeClientException e) {
+ LOG.error("While deleting object {}", model.getObject().getKey(), e);
+ SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+ ? e.getClass().getName() : e.getMessage());
+ }
+ ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+ }
+ }, ActionLink.ActionType.DELETE, OIDCClientEntitlement.OP_DELETE, true);
+ return panel;
+ }
+
+ @Override
+ public void onEvent(final IEvent<?> event) {
+ super.onEvent(event);
+
+ if (event.getPayload() instanceof AjaxWizard.NewItemEvent) {
+ AjaxWizard.NewItemEvent<?> newItemEvent = AjaxWizard.NewItemEvent.class.cast(event.getPayload());
+ WizardModalPanel<?> modalPanel = newItemEvent.getModalPanel();
+
+ if (event.getPayload() instanceof AjaxWizard.NewItemActionEvent && modalPanel != null) {
+ final IModel<Serializable> model = new CompoundPropertyModel<>(modalPanel.getItem());
+ templateModal.setFormModel(model);
+ templateModal.header(newItemEvent.getResourceModel());
+ newItemEvent.getTarget().add(templateModal.setContent(modalPanel));
+ templateModal.show(true);
+ } else if (event.getPayload() instanceof AjaxWizard.NewItemCancelEvent) {
+ templateModal.close(newItemEvent.getTarget());
+ } else if (event.getPayload() instanceof AjaxWizard.NewItemFinishEvent) {
+ templateModal.close(newItemEvent.getTarget());
+ }
+ }
+ }
+
+ protected final class OIDCProvidersProvider extends DirectoryDataProvider<OIDCProviderTO> {
+
+ private static final long serialVersionUID = -2865055116864423761L;
+
+ private final SortableDataProviderComparator<OIDCProviderTO> comparator;
+
+ public OIDCProvidersProvider(final int paginatorRows) {
+ super(paginatorRows);
+
+ setSort("name", SortOrder.ASCENDING);
+ comparator = new SortableDataProviderComparator<>(this);
+ }
+
+ @Override
+ public Iterator<OIDCProviderTO> iterator(final long first, final long count) {
+ List<OIDCProviderTO> list = restClient.list();
+ Collections.sort(list, comparator);
+ return list.subList((int) first, (int) first + (int) count).iterator();
+ }
+
+ @Override
+ public long size() {
+ return restClient.list().size();
+ }
+
+ @Override
+ public IModel<OIDCProviderTO> model(final OIDCProviderTO object) {
+ return new CompoundPropertyModel<>(object);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.java
new file mode 100644
index 0000000..5b108e5
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.java
@@ -0,0 +1,109 @@
+/*
+ * 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.client.console.panels;
+
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.UrlUtils;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.http.handler.RedirectRequestHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OIDCSSOLoginFormPanel extends SSOLoginFormPanel {
+
+ private static final long serialVersionUID = 1154933731474854671L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(OIDCSSOLoginFormPanel.class);
+
+ public OIDCSSOLoginFormPanel(final String id) {
+ super(id);
+
+ List<OIDCProviderTO> available =
+ SyncopeConsoleSession.get().getAnonymousClient().getService(OIDCProviderService.class).list();
+
+ final Model<OIDCProviderTO> model = new Model<>();
+ AjaxDropDownChoicePanel<OIDCProviderTO> ops =
+ new AjaxDropDownChoicePanel<>("ops", "OpenID Connect", model, false);
+ ops.setChoices(available);
+ ops.setChoiceRenderer(new IChoiceRenderer<OIDCProviderTO>() {
+
+ private static final long serialVersionUID = 1814750973898916102L;
+
+ @Override
+ public Object getDisplayValue(final OIDCProviderTO object) {
+ return object.getName();
+ }
+
+ @Override
+ public String getIdValue(final OIDCProviderTO object, final int index) {
+ return object.getName();
+ }
+
+ @Override
+ public OIDCProviderTO getObject(final String id,
+ final IModel<? extends List<? extends OIDCProviderTO>> choices) {
+ return IterableUtils.find(choices.getObject(), new Predicate<OIDCProviderTO>() {
+
+ @Override
+ public boolean evaluate(final OIDCProviderTO object) {
+ return object.getName().equals(id);
+ }
+ });
+ }
+ });
+
+ ops.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+ private static final long serialVersionUID = -1107858522700306810L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ if (model.getObject() != null) {
+ try {
+ RequestCycle.get().scheduleRequestHandlerAfterCurrent(new RedirectRequestHandler(
+ UrlUtils.rewriteToContextRelative("oidcclient/login?op="
+ + URLEncoder.encode(
+ model.getObject().getName(), StandardCharsets.UTF_8.name()),
+ RequestCycle.get())));
+ } catch (Exception e) {
+ LOG.error("Could not redirect to the selected OP {}", model.getObject().getName(), e);
+ }
+ }
+ }
+ });
+ ops.setOutputMarkupPlaceholderTag(true);
+ ops.setVisible(!available.isEmpty());
+ add(ops);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/rest/OIDCProviderRestClient.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/rest/OIDCProviderRestClient.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/rest/OIDCProviderRestClient.java
new file mode 100644
index 0000000..a666d74
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/rest/OIDCProviderRestClient.java
@@ -0,0 +1,59 @@
+/*
+ * 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.client.console.rest;
+
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
+
+public class OIDCProviderRestClient extends BaseRestClient {
+
+ private static final long serialVersionUID = -4006712447589576324L;
+
+ public List<OIDCProviderTO> list() {
+ return getService(OIDCProviderService.class).list();
+ }
+
+ public Set<String> getActionsClasses() {
+ return getService(OIDCProviderService.class).getActionsClasses();
+ }
+
+ public void create(final OIDCProviderTO op) {
+ SyncopeConsoleSession.get().getService(OIDCProviderService.class).create(op);
+ }
+
+ public void createFromDiscovery(final OIDCProviderTO op) {
+ SyncopeConsoleSession.get().getService(OIDCProviderService.class).createFromDiscovery(op);
+ }
+
+ public OIDCProviderTO read(final String key) {
+ return getService(OIDCProviderService.class).read(key);
+ }
+
+ public void update(final OIDCProviderTO op) {
+ getService(OIDCProviderService.class).update(op);
+ }
+
+ public void delete(final String key) {
+ getService(OIDCProviderService.class).delete(key);
+ }
+
+}
[3/8] syncope git commit: [SYNCOPE-1270] implementation for OpenID
Connect for Admin Console and Enduser
Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderMappingPanel.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderMappingPanel.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderMappingPanel.java
new file mode 100644
index 0000000..d12965e
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderMappingPanel.java
@@ -0,0 +1,104 @@
+/*
+ * 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.client.console.wizards;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.console.wizards.resources.ItemTransformersTogglePanel;
+import org.apache.syncope.client.console.wizards.resources.JEXLTransformersTogglePanel;
+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.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.util.ListModel;
+
+public class OIDCProviderMappingPanel extends AbstractMappingPanel {
+
+ private static final long serialVersionUID = -4123879435574382968L;
+
+ public OIDCProviderMappingPanel(
+ final String id,
+ final OIDCProviderTO opTO,
+ final ItemTransformersTogglePanel mapItemTransformers,
+ final JEXLTransformersTogglePanel jexlTransformers) {
+
+ super(id,
+ mapItemTransformers,
+ jexlTransformers,
+ new ListModel<ItemTO>(opTO.getItems()),
+ true,
+ true,
+ MappingPurpose.NONE);
+
+ setOutputMarkupId(true);
+ }
+
+ @Override
+ protected void onBeforeRender() {
+ super.onBeforeRender();
+ purposeLabel.setVisible(false);
+ }
+
+ @Override
+ protected IModel<List<String>> getExtAttrNames() {
+ List<String> extAttrNames = new ArrayList<>();
+ extAttrNames.add("email");
+ extAttrNames.add("family_name");
+ extAttrNames.add("name");
+ extAttrNames.add("middle_name");
+ extAttrNames.add("given_name");
+ extAttrNames.add("preferred_username");
+ extAttrNames.add("nickname");
+ extAttrNames.add("profile");
+ extAttrNames.add("gender");
+ extAttrNames.add("locale");
+ extAttrNames.add("zoneinfo");
+ extAttrNames.add("birthdate");
+ extAttrNames.add("phone_number");
+ extAttrNames.add("address");
+ extAttrNames.add("updated_at");
+
+ return Model.ofList(extAttrNames);
+ }
+
+ @Override
+ protected void setAttrNames(final AjaxTextFieldPanel toBeUpdated) {
+ toBeUpdated.setRequired(true);
+ toBeUpdated.setEnabled(true);
+
+ List<String> choices = new ArrayList<>(USER_FIELD_NAMES);
+
+ for (AnyTypeClassTO anyTypeClassTO : anyTypeClassRestClient.list(
+ anyTypeRestClient.read(AnyTypeKind.USER.name()).getClasses())) {
+
+ choices.addAll(anyTypeClassTO.getPlainSchemas());
+ choices.addAll(anyTypeClassTO.getDerSchemas());
+ choices.addAll(anyTypeClassTO.getVirSchemas());
+ }
+
+ Collections.sort(choices);
+ toBeUpdated.setChoices(choices);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java
new file mode 100644
index 0000000..2fa465a
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java
@@ -0,0 +1,290 @@
+/*
+ * 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.client.console.wizards;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.panels.OIDCProvidersDirectoryPanel;
+import org.apache.syncope.client.console.rest.OIDCProviderRestClient;
+import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.console.wizards.resources.ItemTransformersTogglePanel;
+import org.apache.syncope.client.console.wizards.resources.JEXLTransformersTogglePanel;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.StringResourceModel;
+import org.apache.wicket.model.util.ListModel;
+import org.apache.wicket.validation.validator.UrlValidator;
+
+public class OIDCProviderWizardBuilder extends AjaxWizardBuilder<OIDCProviderTO> {
+
+ private static final long serialVersionUID = -3310772400714122768L;
+
+ private final OIDCProviderRestClient restClient = new OIDCProviderRestClient();
+
+ private final OIDCProvidersDirectoryPanel directoryPanel;
+
+ private final IModel<List<String>> actionsClasses = new LoadableDetachableModel<List<String>>() {
+
+ private static final long serialVersionUID = 5275935387613157437L;
+
+ @Override
+ protected List<String> load() {
+ return new ArrayList<>(restClient.getActionsClasses());
+ }
+ };
+
+ public OIDCProviderWizardBuilder(final OIDCProvidersDirectoryPanel directoryPanel, final OIDCProviderTO defaultItem,
+ final PageReference pageRef) {
+ super(defaultItem, pageRef);
+ this.directoryPanel = directoryPanel;
+ }
+
+ @Override
+ protected Serializable onApplyInternal(final OIDCProviderTO modelObject) {
+ if (modelObject.getKey() == null) {
+ if (modelObject.getHasDiscovery()) {
+ restClient.createFromDiscovery(modelObject);
+ } else {
+ restClient.create(modelObject);
+ }
+
+ } else {
+ restClient.update(modelObject);
+ }
+ return modelObject;
+ }
+
+ @Override
+ protected WizardModel buildModelSteps(final OIDCProviderTO modelObject, final WizardModel wizardModel) {
+ wizardModel.add(new OP(modelObject));
+ if (modelObject.getKey() == null) {
+ wizardModel.add(new OPContinue(modelObject));
+ } else {
+ wizardModel.add(new OPContinue(modelObject, true));
+ }
+
+ Mapping mapping = new Mapping(modelObject);
+ mapping.setOutputMarkupId(true);
+
+ ItemTransformersTogglePanel mapItemTransformers = new ItemTransformersTogglePanel(mapping, pageRef);
+ addOuterObject(mapItemTransformers);
+ JEXLTransformersTogglePanel jexlTransformers = new JEXLTransformersTogglePanel(mapping, pageRef);
+ addOuterObject(jexlTransformers);
+ mapping.add(new OIDCProviderMappingPanel("mapping", modelObject, mapItemTransformers, jexlTransformers));
+
+ wizardModel.add(mapping);
+
+ return wizardModel;
+ }
+
+ public class OP extends WizardStep {
+
+ private static final long serialVersionUID = 7127421283216134900L;
+
+ public OP(final OIDCProviderTO opTO) {
+ AjaxTextFieldPanel name = new AjaxTextFieldPanel(
+ "name", "name", new PropertyModel<String>(opTO, "name"), false);
+ name.addRequiredLabel();
+ name.setEnabled(true);
+ add(name);
+
+ AjaxTextFieldPanel clientID = new AjaxTextFieldPanel(
+ "clientID", "clientID", new PropertyModel<String>(opTO, "clientID"), false);
+ clientID.addRequiredLabel();
+ clientID.setEnabled(true);
+ add(clientID);
+
+ AjaxTextFieldPanel clientSecret = new AjaxTextFieldPanel(
+ "clientSecret", "clientSecret", new PropertyModel<String>(opTO, "clientSecret"), false);
+ clientSecret.addRequiredLabel();
+ clientSecret.setEnabled(true);
+ add(clientSecret);
+
+ AjaxCheckBoxPanel createUnmatching = new AjaxCheckBoxPanel(
+ "createUnmatching", "createUnmatching", new PropertyModel<Boolean>(opTO, "createUnmatching"),
+ false);
+ add(createUnmatching);
+
+ AjaxCheckBoxPanel updateMatching = new AjaxCheckBoxPanel(
+ "updateMatching", "updateMatching", new PropertyModel<Boolean>(opTO, "updateMatching"), false);
+ add(updateMatching);
+
+ AjaxPalettePanel<String> actionsClassNames = new AjaxPalettePanel.Builder<String>().
+ setAllowMoveAll(true).setAllowOrder(true).
+ setName(new StringResourceModel("actionsClassNames", directoryPanel).getString()).
+ build("actionsClassNames",
+ new PropertyModel<List<String>>(opTO, "actionsClassNames"),
+ new ListModel<>(actionsClasses.getObject()));
+ actionsClassNames.setOutputMarkupId(true);
+ add(actionsClassNames);
+ }
+ }
+
+ public class OPContinue extends WizardStep {
+
+ private static final long serialVersionUID = -7087008312629522790L;
+
+ public OPContinue(final OIDCProviderTO opTO) {
+
+ final WebMarkupContainer content = new WebMarkupContainer("content");
+ this.setOutputMarkupId(true);
+ content.setOutputMarkupId(true);
+ add(content);
+
+ UrlValidator urlValidator = new UrlValidator();
+ final AjaxTextFieldPanel issuer = new AjaxTextFieldPanel(
+ "issuer", "issuer", new PropertyModel<String>(opTO, "issuer"));
+ issuer.addValidator(urlValidator);
+ issuer.addRequiredLabel();
+ content.add(issuer);
+
+ final AjaxCheckBoxPanel hasDiscovery = new AjaxCheckBoxPanel(
+ "hasDiscovery", "hasDiscovery", new PropertyModel<Boolean>(opTO, "hasDiscovery"));
+ content.add(hasDiscovery);
+
+ final AjaxTextFieldPanel authorizationEndpoint = new AjaxTextFieldPanel("authorizationEndpoint",
+ "authorizationEndpoint", new PropertyModel<String>(opTO, "authorizationEndpoint"));
+ authorizationEndpoint.addRequiredLabel();
+ authorizationEndpoint.addValidator(urlValidator);
+ content.add(authorizationEndpoint);
+
+ final AjaxTextFieldPanel userinfoEndpoint = new AjaxTextFieldPanel("userinfoEndpoint",
+ "userinfoEndpoint", new PropertyModel<String>(opTO, "userinfoEndpoint"));
+ userinfoEndpoint.addRequiredLabel();
+ userinfoEndpoint.addValidator(urlValidator);
+ content.add(userinfoEndpoint);
+
+ final AjaxTextFieldPanel tokenEndpoint = new AjaxTextFieldPanel("tokenEndpoint",
+ "tokenEndpoint", new PropertyModel<String>(opTO, "tokenEndpoint"));
+ tokenEndpoint.addRequiredLabel();
+ tokenEndpoint.addValidator(urlValidator);
+ content.add(tokenEndpoint);
+
+ final AjaxTextFieldPanel jwksUri = new AjaxTextFieldPanel("jwksUri",
+ "jwksUri", new PropertyModel<String>(opTO, "jwksUri"));
+ jwksUri.addRequiredLabel();
+ jwksUri.addValidator(urlValidator);
+ content.add(jwksUri);
+
+ final WebMarkupContainer visibleParam = new WebMarkupContainer("visibleParams");
+ visibleParam.setOutputMarkupPlaceholderTag(true);
+ visibleParam.add(authorizationEndpoint);
+ visibleParam.add(userinfoEndpoint);
+ visibleParam.add(tokenEndpoint);
+ visibleParam.add(jwksUri);
+ content.add(visibleParam);
+
+ showHide(hasDiscovery, visibleParam);
+
+ hasDiscovery.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+ private static final long serialVersionUID = -1107858522700306810L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ showHide(hasDiscovery, visibleParam);
+ target.add(visibleParam);
+ }
+ });
+
+ }
+
+ public OPContinue(final OIDCProviderTO opTO, final boolean readOnly) {
+
+ final WebMarkupContainer content = new WebMarkupContainer("content");
+ this.setOutputMarkupId(true);
+ content.setOutputMarkupId(true);
+ add(content);
+
+ final AjaxTextFieldPanel issuer = new AjaxTextFieldPanel(
+ "issuer", "issuer", new PropertyModel<String>(opTO, "issuer"));
+ issuer.setReadOnly(readOnly);
+ content.add(issuer);
+
+ final AjaxCheckBoxPanel hasDiscovery = new AjaxCheckBoxPanel(
+ "hasDiscovery", "hasDiscovery", new PropertyModel<Boolean>(opTO, "hasDiscovery"));
+ hasDiscovery.setReadOnly(readOnly);
+ content.add(hasDiscovery);
+
+ final AjaxTextFieldPanel authorizationEndpoint = new AjaxTextFieldPanel("authorizationEndpoint",
+ "authorizationEndpoint", new PropertyModel<String>(opTO, "authorizationEndpoint"));
+ authorizationEndpoint.setReadOnly(readOnly);
+ content.add(authorizationEndpoint);
+
+ final AjaxTextFieldPanel userinfoEndpoint = new AjaxTextFieldPanel("userinfoEndpoint",
+ "userinfoEndpoint", new PropertyModel<String>(opTO, "userinfoEndpoint"));
+ userinfoEndpoint.setReadOnly(readOnly);
+ content.add(userinfoEndpoint);
+
+ final AjaxTextFieldPanel tokenEndpoint = new AjaxTextFieldPanel("tokenEndpoint",
+ "tokenEndpoint", new PropertyModel<String>(opTO, "tokenEndpoint"));
+ tokenEndpoint.setReadOnly(readOnly);
+ content.add(tokenEndpoint);
+
+ final AjaxTextFieldPanel jwksUri = new AjaxTextFieldPanel("jwksUri",
+ "jwksUri", new PropertyModel<String>(opTO, "jwksUri"));
+ jwksUri.setReadOnly(readOnly);
+ content.add(jwksUri);
+
+ final WebMarkupContainer visibleParam = new WebMarkupContainer("visibleParams");
+ visibleParam.setOutputMarkupPlaceholderTag(true);
+ visibleParam.add(authorizationEndpoint);
+ visibleParam.add(userinfoEndpoint);
+ visibleParam.add(tokenEndpoint);
+ visibleParam.add(jwksUri);
+ content.add(visibleParam);
+ }
+ }
+
+ private void showHide(final AjaxCheckBoxPanel hasDiscovery, final WebMarkupContainer visibleParams) {
+ if (hasDiscovery.getField().getValue().equals("false")) {
+ visibleParams.setVisible(true);
+ } else {
+ visibleParams.setVisible(false);
+ }
+ }
+
+ /**
+ * Mapping definition step.
+ */
+ private static final class Mapping extends WizardStep {
+
+ private static final long serialVersionUID = 3454904947720856253L;
+
+ Mapping(final OIDCProviderTO item) {
+ setTitleModel(Model.of("Mapping"));
+ setSummaryModel(Model.of(StringUtils.EMPTY));
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.html
new file mode 100644
index 0000000..a1a0aed
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:extend>
+ <section class="content-header">
+ <h1> </h1>
+ <ol class="breadcrumb">
+ <li><a wicket:id="dashboardBr"><i class="fa fa-dashboard"></i> <wicket:message key="dashboard"/></a></li>
+ <li class="active"><wicket:message key="extensions"/></li>
+ <li class="active">OIDC Client</li>
+ </ol>
+ </section>
+
+ <section class="content" wicket:id="content">
+ <div class="box">
+ <div class="box-body" wicket:id="tabbedPanel"/>
+ </div>
+ </section>
+ </wicket:extend>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.properties
new file mode 100644
index 0000000..b34f11c
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.properties
@@ -0,0 +1,17 @@
+# 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.
+op=OIDC Providers
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_it.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_it.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_it.properties
new file mode 100644
index 0000000..b34f11c
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_it.properties
@@ -0,0 +1,17 @@
+# 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.
+op=OIDC Providers
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_pt_BR.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_pt_BR.properties
new file mode 100644
index 0000000..b34f11c
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_pt_BR.properties
@@ -0,0 +1,17 @@
+# 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.
+op=OIDC Providers
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_ru.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_ru.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_ru.properties
new file mode 100644
index 0000000..b34f11c
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_ru.properties
@@ -0,0 +1,17 @@
+# 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.
+op=OIDC Providers
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.html
new file mode 100644
index 0000000..ce0dbe8
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.html
@@ -0,0 +1,23 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:extend>
+
+ </wicket:extend>
+</html>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.properties
new file mode 100644
index 0000000..569d0dc
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.properties
@@ -0,0 +1,30 @@
+# 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.
+clientID=Client ID
+clientSecret=Client Secret
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+any.new=New Provider
+template.title=user template
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_it.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_it.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_it.properties
new file mode 100644
index 0000000..569d0dc
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_it.properties
@@ -0,0 +1,30 @@
+# 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.
+clientID=Client ID
+clientSecret=Client Secret
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+any.new=New Provider
+template.title=user template
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_pt_BR.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_pt_BR.properties
new file mode 100644
index 0000000..569d0dc
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_pt_BR.properties
@@ -0,0 +1,30 @@
+# 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.
+clientID=Client ID
+clientSecret=Client Secret
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+any.new=New Provider
+template.title=user template
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_ru.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_ru.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_ru.properties
new file mode 100644
index 0000000..569d0dc
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_ru.properties
@@ -0,0 +1,30 @@
+# 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.
+clientID=Client ID
+clientSecret=Client Secret
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+any.new=New Provider
+template.title=user template
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.html
new file mode 100644
index 0000000..3b30b4c
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.html
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <div class="form-group">
+ <span wicket:id="ops"></span>
+ </div>
+ </wicket:panel>
+</html>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$Mapping.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$Mapping.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$Mapping.html
new file mode 100644
index 0000000..11b1a52
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$Mapping.html
@@ -0,0 +1,23 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <span wicket:id="mapping" />
+ </wicket:panel>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.html
new file mode 100644
index 0000000..4ad49d8
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.html
@@ -0,0 +1,28 @@
+<!--
+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. actionsClassNames
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <div class="form-group"><span wicket:id="name">[name]</span></div>
+ <div class="form-group"><span wicket:id="clientID">[clientID]</span></div>
+ <div class="form-group"><span wicket:id="clientSecret">[clientSecret]</span></div>
+ <div class="form-group"><span wicket:id="createUnmatching">[createUnmatching]</span></div>
+ <div class="form-group"><span wicket:id="updateMatching">[updateMatching]</span></div>
+ <div class="form-group"><span wicket:id="actionsClassNames">[actionsClassNames]</span></div>
+ </wicket:panel>
+</html>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.properties
new file mode 100644
index 0000000..5ed531a
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.properties
@@ -0,0 +1,24 @@
+# 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.
+name=Name
+clientID=Client ID
+clientSecret=Client Secret
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html
new file mode 100644
index 0000000..01da6ec
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html
@@ -0,0 +1,33 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <div wicket:id="content">
+ <span wicket:id="issuer">[issuer]</span>
+ <span wicket:id="hasDiscovery">[hasDiscovery]</span>
+
+ <div wicket:id="visibleParams">
+ <span wicket:id="authorizationEndpoint">[authorizationEndpoint]</span>
+ <span wicket:id="tokenEndpoint">[tokenEndpoint]</span>
+ <span wicket:id="jwksUri">[jwksUri]</span>
+ <span wicket:id="userinfoEndpoint">[userinfoEndpoint]</span>
+ </div>
+ </div>
+ </wicket:panel>
+</html>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.properties
new file mode 100644
index 0000000..3f1d085
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.properties
@@ -0,0 +1,27 @@
+# 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.
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+tokenEndpoint= Token Endpoint
+jwksUri= JWKS URI
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_it.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_it.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_it.properties
new file mode 100644
index 0000000..3f1d085
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_it.properties
@@ -0,0 +1,27 @@
+# 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.
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+tokenEndpoint= Token Endpoint
+jwksUri= JWKS URI
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_pt_BR.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_pt_BR.properties
new file mode 100644
index 0000000..3f1d085
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_pt_BR.properties
@@ -0,0 +1,27 @@
+# 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.
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+tokenEndpoint= Token Endpoint
+jwksUri= JWKS URI
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_ru.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_ru.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_ru.properties
new file mode 100644
index 0000000..3f1d085
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_ru.properties
@@ -0,0 +1,27 @@
+# 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.
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+tokenEndpoint= Token Endpoint
+jwksUri= JWKS URI
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_it.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_it.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_it.properties
new file mode 100644
index 0000000..5ed531a
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_it.properties
@@ -0,0 +1,24 @@
+# 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.
+name=Name
+clientID=Client ID
+clientSecret=Client Secret
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_pt_BR.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_pt_BR.properties
new file mode 100644
index 0000000..5ed531a
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_pt_BR.properties
@@ -0,0 +1,24 @@
+# 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.
+name=Name
+clientID=Client ID
+clientSecret=Client Secret
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_ru.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_ru.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_ru.properties
new file mode 100644
index 0000000..5ed531a
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_ru.properties
@@ -0,0 +1,24 @@
+# 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.
+name=Name
+clientID=Client ID
+clientSecret=Client Secret
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-enduser/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-enduser/pom.xml b/ext/oidcclient/client-enduser/pom.xml
new file mode 100644
index 0000000..3a86a04
--- /dev/null
+++ b/ext/oidcclient/client-enduser/pom.xml
@@ -0,0 +1,83 @@
+<?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.0.9-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client Enduser</name>
+ <description>Apache Syncope Ext: OIDC Client Enduser</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-enduser</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-common-lib</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-agent</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.client</groupId>
+ <artifactId>syncope-client-enduser</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/OIDCClientLogin.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/OIDCClientLogin.java b/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/OIDCClientLogin.java
new file mode 100644
index 0000000..5aa8578
--- /dev/null
+++ b/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/OIDCClientLogin.java
@@ -0,0 +1,63 @@
+/*
+ * 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.client.enduser.pages;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.wicket.authentication.IAuthenticationStrategy;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OIDCClientLogin extends WebPage {
+
+ private static final long serialVersionUID = 8581614051773949262L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(OIDCClientLogin.class);
+
+ private static final String OIDC_ACCESS_ERROR = "OIDC access error";
+
+ public OIDCClientLogin(final PageParameters parameters) {
+ super(parameters);
+
+ String token = (String) ((ServletWebRequest) getRequest()).getContainerRequest().
+ getSession().getAttribute(org.apache.syncope.ext.oidcclient.agent.Constants.OIDCCLIENTJWT);
+ if (StringUtils.isBlank(token)) {
+ LOG.error("No JWT found, redirecting to default greeter");
+
+ PageParameters params = new PageParameters();
+ params.add("errorMessage", OIDC_ACCESS_ERROR);
+ setResponsePage(getApplication().getHomePage(), params);
+ }
+
+ IAuthenticationStrategy strategy = getApplication().getSecuritySettings().getAuthenticationStrategy();
+
+ if (SyncopeEnduserSession.get().authenticate(token)) {
+ setResponsePage(getApplication().getHomePage());
+ } else {
+ PageParameters params = new PageParameters();
+ params.add("errorMessage", OIDC_ACCESS_ERROR);
+ setResponsePage(getApplication().getHomePage(), params);
+ }
+ strategy.remove();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/OIDCProvidersResource.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/OIDCProvidersResource.java b/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/OIDCProvidersResource.java
new file mode 100644
index 0000000..3bb2d63
--- /dev/null
+++ b/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/OIDCProvidersResource.java
@@ -0,0 +1,72 @@
+/*
+ * 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.client.enduser.resources;
+
+import static org.apache.syncope.client.enduser.resources.BaseResource.MAPPER;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.annotations.Resource;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
+import org.apache.wicket.request.resource.AbstractResource;
+
+@Resource(key = "oidcProviders", path = "/api/oidcProviders")
+public class OIDCProvidersResource extends BaseResource {
+
+ private static final long serialVersionUID = -6595407257133697170L;
+
+ @Override
+ protected ResourceResponse newResourceResponse(final Attributes attributes) {
+ ResourceResponse response = new ResourceResponse();
+ response.setContentType(MediaType.APPLICATION_JSON);
+ response.setTextEncoding(StandardCharsets.UTF_8.name());
+ try {
+ final ArrayNode result = MAPPER.createArrayNode();
+
+ for (OIDCProviderTO op : SyncopeEnduserSession.get().getService(OIDCProviderService.class).list()) {
+ ObjectNode opNode = MAPPER.createObjectNode();
+ opNode.put("name", op.getName());
+ result.add(opNode);
+ }
+
+ response.setWriteCallback(new AbstractResource.WriteCallback() {
+
+ @Override
+ public void writeData(final Attributes attributes) throws IOException {
+ attributes.getResponse().write(MAPPER.writeValueAsString(result));
+ }
+ });
+ response.setStatusCode(Response.Status.OK.getStatusCode());
+ } catch (Exception e) {
+ LOG.error("Error retrieving available OIDC Providers", e);
+ response.setError(
+ Response.Status.BAD_REQUEST.getStatusCode(),
+ "ErrorMessage{{ " + e.getMessage() + "}}");
+ }
+
+ return response;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/common-lib/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/pom.xml b/ext/oidcclient/common-lib/pom.xml
new file mode 100644
index 0000000..f60b0f0
--- /dev/null
+++ b/ext/oidcclient/common-lib/pom.xml
@@ -0,0 +1,56 @@
+<?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.0.9-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client Common Lib</name>
+ <description>Apache Syncope Ext: OIDC Client Common Lib</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-common-lib</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.common</groupId>
+ <artifactId>syncope-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/f29e60f6/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/OIDCConstants.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/OIDCConstants.java b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/OIDCConstants.java
new file mode 100644
index 0000000..12daa0a
--- /dev/null
+++ b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/OIDCConstants.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+public final class OIDCConstants {
+
+ public static final String CLIENT_ID = "client_id";
+
+ public static final String CLIENT_SECRET = "client_secret";
+
+ public static final String SCOPE = "scope";
+
+ public static final String RESPOSNSE_TYPE = "response_type";
+
+ public static final String REDIRECT_URI = "redirect_uri";
+
+ public static final String STATE = "state";
+
+ public static final String CODE = "code";
+
+ public static final String GRANT_TYPE = "grant_type";
+
+ public static final String OP = "op";
+
+ private OIDCConstants() {
+ // private constructor for static utility class
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginRequestTO.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginRequestTO.java b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginRequestTO.java
new file mode 100644
index 0000000..5d4dc31
--- /dev/null
+++ b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginRequestTO.java
@@ -0,0 +1,91 @@
+/*
+ * 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.to;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlRootElement(name = "oidcLoginRequest")
+@XmlType
+public class OIDCLoginRequestTO extends AbstractBaseBean {
+
+ private static final long serialVersionUID = -3509031322459942441L;
+
+ private String providerAddress;
+
+ private String clientId;
+
+ private String scope;
+
+ private String responseType;
+
+ private String redirectURI;
+
+ private String state;
+
+ public String getProviderAddress() {
+ return providerAddress;
+ }
+
+ public void setProviderAddress(final String providerAddress) {
+ this.providerAddress = providerAddress;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(final String clientId) {
+ this.clientId = clientId;
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ public void setScope(final String scope) {
+ this.scope = scope;
+ }
+
+ public String getResponseType() {
+ return responseType;
+ }
+
+ public void setResponseType(final String responseType) {
+ this.responseType = responseType;
+ }
+
+ public String getRedirectURI() {
+ return redirectURI;
+ }
+
+ public void setRedirectURI(final String redirectURI) {
+ this.redirectURI = redirectURI;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(final String state) {
+ this.state = state;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginResponseTO.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginResponseTO.java b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginResponseTO.java
new file mode 100644
index 0000000..fd356a9
--- /dev/null
+++ b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginResponseTO.java
@@ -0,0 +1,140 @@
+/*
+ * 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.to;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlRootElement(name = "oidcLoginResponse")
+@XmlType
+public class OIDCLoginResponseTO extends AbstractBaseBean {
+
+ private static final long serialVersionUID = -5971442076182154492L;
+
+ private String username;
+
+ private String email;
+
+ private String name;
+
+ private String subject;
+
+ private String givenName;
+
+ private String familyName;
+
+ private String accessToken;
+
+ private Date accessTokenExpiryTime;
+
+ private final Set<AttrTO> attrs = new HashSet<>();
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(final String username) {
+ this.username = username;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(final String email) {
+ this.email = email;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ public void setSubject(final String subject) {
+ this.subject = subject;
+ }
+
+ public String getGivenName() {
+ return givenName;
+ }
+
+ public void setGivenName(final String givenName) {
+ this.givenName = givenName;
+ }
+
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ public void setFamilyName(final String familyName) {
+ this.familyName = familyName;
+ }
+
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ public void setAccessToken(final String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ public Date getAccessTokenExpiryTime() {
+ return accessTokenExpiryTime;
+ }
+
+ public void setAccessTokenExpiryTime(final Date accessTokenExpiryTime) {
+ this.accessTokenExpiryTime = accessTokenExpiryTime;
+ }
+
+ @JsonIgnore
+ public AttrTO getAttr(final String schema) {
+ return IterableUtils.find(attrs, new Predicate<AttrTO>() {
+
+ @Override
+ public boolean evaluate(final AttrTO object) {
+ return object.getSchema().equals(schema);
+ }
+ });
+ }
+
+ @XmlElementWrapper(name = "attrs")
+ @XmlElement(name = "attr")
+ @JsonProperty("attrs")
+ public Set<AttrTO> getAttrs() {
+ return attrs;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCProviderTO.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCProviderTO.java b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCProviderTO.java
new file mode 100644
index 0000000..2bb88aa
--- /dev/null
+++ b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCProviderTO.java
@@ -0,0 +1,229 @@
+/*
+ * 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.to;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.PathParam;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlRootElement(name = "oidcprovider")
+@XmlType
+public class OIDCProviderTO extends AbstractBaseBean implements EntityTO, ItemContainerTO {
+
+ private static final long serialVersionUID = -1229802774546135794L;
+
+ private String key;
+
+ private String name;
+
+ private String clientID;
+
+ private String clientSecret;
+
+ private String authorizationEndpoint;
+
+ private String tokenEndpoint;
+
+ private String jwksUri;
+
+ private String issuer;
+
+ private String userinfoEndpoint;
+
+ private boolean hasDiscovery;
+
+ private UserTO userTemplate;
+
+ private boolean createUnmatching;
+
+ private boolean updateMatching;
+
+ private final List<ItemTO> items = new ArrayList<>();
+
+ private final Set<String> actionsClassNames = new HashSet<>();
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @PathParam("key")
+ @Override
+ public void setKey(final String key) {
+ this.key = key;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getClientID() {
+ return clientID;
+ }
+
+ public void setClientID(final String clientID) {
+ this.clientID = clientID;
+ }
+
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ public void setClientSecret(final String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ public String getAuthorizationEndpoint() {
+ return authorizationEndpoint;
+ }
+
+ public void setAuthorizationEndpoint(final String authorizationEndpoint) {
+ this.authorizationEndpoint = authorizationEndpoint;
+ }
+
+ public String getTokenEndpoint() {
+ return tokenEndpoint;
+ }
+
+ public void setTokenEndpoint(final String tokenEndpoint) {
+ this.tokenEndpoint = tokenEndpoint;
+ }
+
+ public String getJwksUri() {
+ return jwksUri;
+ }
+
+ public void setJwksUri(final String jwksUri) {
+ this.jwksUri = jwksUri;
+ }
+
+ public String getIssuer() {
+ return issuer;
+ }
+
+ public void setIssuer(final String issuer) {
+ this.issuer = issuer;
+ }
+
+ public String getUserinfoEndpoint() {
+ return userinfoEndpoint;
+ }
+
+ public void setUserinfoEndpoint(final String userinfoEndpoint) {
+ this.userinfoEndpoint = userinfoEndpoint;
+ }
+
+ public UserTO getUserTemplate() {
+ return userTemplate;
+ }
+
+ public boolean getHasDiscovery() {
+ return hasDiscovery;
+ }
+
+ public void setHasDiscovery(final boolean hasDiscovery) {
+ this.hasDiscovery = hasDiscovery;
+ }
+
+ public void setUserTemplate(final UserTO userTemplate) {
+ this.userTemplate = userTemplate;
+ }
+
+ public boolean isCreateUnmatching() {
+ return createUnmatching;
+ }
+
+ public void setCreateUnmatching(final boolean createUnmatching) {
+ this.createUnmatching = createUnmatching;
+ }
+
+ public boolean isUpdateMatching() {
+ return updateMatching;
+ }
+
+ public void setUpdateMatching(final boolean updateMatching) {
+ this.updateMatching = updateMatching;
+ }
+
+
+
+ @Override
+ public ItemTO getConnObjectKeyItem() {
+ return IterableUtils.find(getItems(), new Predicate<ItemTO>() {
+
+ @Override
+ public boolean evaluate(final ItemTO item) {
+ return item.isConnObjectKey();
+ }
+ });
+ }
+
+ protected boolean addConnObjectKeyItem(final ItemTO connObjectItem) {
+ connObjectItem.setMandatoryCondition("true");
+ connObjectItem.setConnObjectKey(true);
+
+ return this.add(connObjectItem);
+ }
+
+ @Override
+ public boolean setConnObjectKeyItem(final ItemTO connObjectKeyItem) {
+ return connObjectKeyItem == null
+ ? remove(getConnObjectKeyItem())
+ : addConnObjectKeyItem(connObjectKeyItem);
+ }
+
+ @XmlElementWrapper(name = "items")
+ @XmlElement(name = "item")
+ @JsonProperty("items")
+ @Override
+ public List<ItemTO> getItems() {
+ return items;
+ }
+
+ @Override
+ public boolean add(final ItemTO item) {
+ return item == null ? false : this.items.contains(item) || this.items.add(item);
+ }
+
+ public boolean remove(final ItemTO item) {
+ return this.items.remove(item);
+ }
+
+ @XmlElementWrapper(name = "actionsClassNames")
+ @XmlElement(name = "actionsClassName")
+ @JsonProperty("actionsClassNames")
+ public Set<String> getActionsClassNames() {
+ return actionsClassNames;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCClientEntitlement.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCClientEntitlement.java b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCClientEntitlement.java
new file mode 100644
index 0000000..98cf4d6
--- /dev/null
+++ b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCClientEntitlement.java
@@ -0,0 +1,57 @@
+/*
+ * 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.types;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+public final class OIDCClientEntitlement {
+
+ public static final String OP_READ = "OP_READ";
+
+ public static final String OP_CREATE = "OP_CREATE";
+
+ public static final String OP_UPDATE = "OP_UPDATE";
+
+ public static final String OP_DELETE = "OP_DELETE";
+
+ private static final Set<String> VALUES;
+
+ static {
+ Set<String> values = new TreeSet<>();
+ for (Field field : OIDCClientEntitlement.class.getDeclaredFields()) {
+ if (Modifier.isStatic(field.getModifiers()) && String.class.equals(field.getType())) {
+ values.add(field.getName());
+ }
+ }
+ VALUES = Collections.unmodifiableSet(values);
+ }
+
+ public static Set<String> values() {
+ return VALUES;
+ }
+
+ private OIDCClientEntitlement() {
+ // private constructor for static utility class
+ }
+
+}
[8/8] syncope git commit: [SYNCOPE-1270] implementation for OpenID
Connect for Admin Console and Enduser - This closes #74
Posted by il...@apache.org.
[SYNCOPE-1270] implementation for OpenID Connect for Admin Console and Enduser - This closes #74
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/797fd1cb
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/797fd1cb
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/797fd1cb
Branch: refs/heads/master
Commit: 797fd1cbd801aedabb54b5d1dcb65d34636adec5
Parents: 064b7ef
Author: dayash <di...@tirasa.net>
Authored: Wed May 2 09:50:13 2018 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu May 3 16:57:56 2018 +0200
----------------------------------------------------------------------
archetype/pom.xml | 31 ++
.../archetype-resources/console/pom.xml | 6 +
.../resources/archetype-resources/core/pom.xml | 11 +
.../archetype-resources/enduser/pom.xml | 6 +
.../resources/META-INF/resources/app/index.html | 1 +
.../resources/META-INF/resources/app/js/app.js | 27 +-
.../app/js/controllers/LoginController.js | 2 +
.../app/js/services/oidcProviderService.js | 42 ++
.../META-INF/resources/app/views/self.html | 8 +
deb/console/pom.xml | 13 +
deb/console/src/deb/control/conffiles | 2 +
deb/enduser/pom.xml | 13 +
deb/enduser/src/deb/control/conffiles | 2 +
deb/enduser/src/deb/control/preinst | 1 +
ext/oidcclient/agent/pom.xml | 126 ++++++
.../ext/oidcclient/agent/CodeConsumer.java | 92 +++++
.../syncope/ext/oidcclient/agent/Constants.java | 40 ++
.../syncope/ext/oidcclient/agent/Login.java | 89 ++++
.../oidcclient/agent/OIDCClientAgentSetup.java | 77 ++++
.../resources/oidcclient/loginError.jsp | 35 ++
.../resources/oidcclient/loginSuccess.jsp | 33 ++
.../main/resources/META-INF/web-fragment.xml | 26 ++
.../main/resources/oidcclient-agent.properties | 26 ++
ext/oidcclient/client-console/pom.xml | 83 ++++
.../client/console/pages/OIDCClient.java | 68 ++++
.../client/console/pages/OIDCClientLogin.java | 68 ++++
.../panels/OIDCProvidersDirectoryPanel.java | 291 +++++++++++++
.../console/panels/OIDCSSOLoginFormPanel.java | 109 +++++
.../console/rest/OIDCProviderRestClient.java | 59 +++
.../wizards/OIDCProviderMappingPanel.java | 104 +++++
.../wizards/OIDCProviderWizardBuilder.java | 290 +++++++++++++
.../client/console/pages/OIDCClient.html | 37 ++
.../client/console/pages/OIDCClient.properties | 17 +
.../console/pages/OIDCClient_it.properties | 17 +
.../console/pages/OIDCClient_pt_BR.properties | 17 +
.../console/pages/OIDCClient_ru.properties | 17 +
.../panels/OIDCProvidersDirectoryPanel.html | 23 ++
.../OIDCProvidersDirectoryPanel.properties | 30 ++
.../OIDCProvidersDirectoryPanel_it.properties | 30 ++
...OIDCProvidersDirectoryPanel_pt_BR.properties | 30 ++
.../OIDCProvidersDirectoryPanel_ru.properties | 30 ++
.../console/panels/OIDCSSOLoginFormPanel.html | 25 ++
.../OIDCProviderWizardBuilder$Mapping.html | 23 ++
.../wizards/OIDCProviderWizardBuilder$OP.html | 28 ++
.../OIDCProviderWizardBuilder$OP.properties | 24 ++
.../OIDCProviderWizardBuilder$OPContinue.html | 33 ++
...CProviderWizardBuilder$OPContinue.properties | 27 ++
...oviderWizardBuilder$OPContinue_it.properties | 27 ++
...derWizardBuilder$OPContinue_pt_BR.properties | 27 ++
...oviderWizardBuilder$OPContinue_ru.properties | 27 ++
.../OIDCProviderWizardBuilder$OP_it.properties | 24 ++
...IDCProviderWizardBuilder$OP_pt_BR.properties | 24 ++
.../OIDCProviderWizardBuilder$OP_ru.properties | 24 ++
ext/oidcclient/client-enduser/pom.xml | 83 ++++
.../client/enduser/pages/OIDCClientLogin.java | 63 +++
.../resources/OIDCProvidersResource.java | 69 ++++
ext/oidcclient/common-lib/pom.xml | 56 +++
.../syncope/common/lib/OIDCConstants.java | 45 ++
.../common/lib/to/OIDCLoginRequestTO.java | 91 +++++
.../common/lib/to/OIDCLoginResponseTO.java | 133 ++++++
.../syncope/common/lib/to/OIDCProviderTO.java | 219 ++++++++++
.../common/lib/types/OIDCClientEntitlement.java | 57 +++
ext/oidcclient/logic/pom.xml | 76 ++++
.../syncope/core/logic/OIDCClientLogic.java | 406 +++++++++++++++++++
.../syncope/core/logic/OIDCProviderLogic.java | 167 ++++++++
...ClientClassPathScanImplementationLookup.java | 78 ++++
.../core/logic/init/OIDCClientLoader.java | 55 +++
.../model/OIDCProviderDiscoveryDocument.java | 128 ++++++
.../core/logic/model/TokenEndpointResponse.java | 86 ++++
.../core/logic/oidc/OIDCUserManager.java | 292 +++++++++++++
ext/oidcclient/persistence-api/pom.xml | 61 +++
.../persistence/api/dao/OIDCProviderDAO.java | 35 ++
.../api/entity/OIDCEntityFactory.java | 25 ++
.../persistence/api/entity/OIDCProvider.java | 85 ++++
.../api/entity/OIDCProviderItem.java | 29 ++
.../api/entity/OIDCUserTemplate.java | 27 ++
ext/oidcclient/persistence-jpa/pom.xml | 134 ++++++
.../persistence/jpa/dao/JPAOIDCProviderDAO.java | 78 ++++
.../jpa/entity/JPAOIDCEntityFactory.java | 49 +++
.../persistence/jpa/entity/JPAOIDCProvider.java | 250 ++++++++++++
.../jpa/entity/JPAOIDCProviderItem.java | 79 ++++
.../jpa/entity/JPAOIDCUserTemplate.java | 52 +++
ext/oidcclient/pom.xml | 55 +++
ext/oidcclient/provisioning-api/pom.xml | 67 +++
.../provisioning/api/OIDCProviderActions.java | 35 ++
.../api/data/OIDCProviderDataBinder.java | 32 ++
ext/oidcclient/provisioning-java/pom.xml | 61 +++
.../java/DefaultOIDCProviderActions.java | 48 +++
.../java/data/OIDCProviderDataBinderImpl.java | 258 ++++++++++++
ext/oidcclient/rest-api/pom.xml | 77 ++++
.../rest/api/service/OIDCClientService.java | 75 ++++
.../rest/api/service/OIDCProviderService.java | 156 +++++++
ext/oidcclient/rest-cxf/pom.xml | 72 ++++
.../rest/cxf/service/OIDCClientServiceImpl.java | 44 ++
.../cxf/service/OIDCProviderServiceImpl.java | 83 ++++
ext/pom.xml | 1 +
.../syncope/ext/saml2lsp/agent/Login.java | 2 +-
fit/console-reference/pom.xml | 6 +
.../main/resources/oidcclient-agent.properties | 26 ++
.../src/main/webapp/WEB-INF/web.xml | 10 +
.../src/test/resources/rebel.xml | 8 +
fit/core-reference/pom.xml | 23 ++
.../org/apache/syncope/fit/AbstractITCase.java | 8 +
.../apache/syncope/fit/OIDCClientDetector.java | 52 +++
.../syncope/fit/core/OIDCClientITCase.java | 152 +++++++
fit/core-reference/src/test/resources/rebel.xml | 17 +
fit/enduser-reference/pom.xml | 6 +
.../main/resources/oidcclient-agent.properties | 26 ++
.../src/main/webapp/WEB-INF/web.xml | 10 +
.../src/test/resources/rebel.xml | 8 +
pom.xml | 10 +
.../reference-guide/concepts/extensions.adoc | 33 ++
.../workingwithapachesyncope/customization.adoc | 52 +++
113 files changed, 6861 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/archetype/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/pom.xml b/archetype/pom.xml
index c4639be..27eccc4 100644
--- a/archetype/pom.xml
+++ b/archetype/pom.xml
@@ -233,6 +233,13 @@ under the License.
</includes>
</resource>
<resource>
+ <directory>../ext/oidcclient/agent/src/main/resources</directory>
+ <targetPath>${project.build.outputDirectory}/archetype-resources/console/src/main/resources/all</targetPath>
+ <includes>
+ <include>oidcclient-agent.properties</include>
+ </includes>
+ </resource>
+ <resource>
<directory>../fit/console-reference/src/main/resources</directory>
<targetPath>${project.build.outputDirectory}/archetype-resources/console/src/main/resources</targetPath>
<includes>
@@ -252,6 +259,14 @@ under the License.
</includes>
</resource>
<resource>
+ <directory>../fit/console-reference/src/main/resources</directory>
+ <targetPath>${project.build.outputDirectory}/archetype-resources/console/src/test/resources</targetPath>
+ <includes>
+ <include>console.properties</include>
+ <include>oidcclient-agent.properties</include>
+ </includes>
+ </resource>
+ <resource>
<directory>../fit/console-reference/src/main/webapp/WEB-INF</directory>
<targetPath>${project.build.outputDirectory}/archetype-resources/console/src/main/webapp/WEB-INF</targetPath>
</resource>
@@ -272,6 +287,13 @@ under the License.
</includes>
</resource>
<resource>
+ <directory>../ext/oidcclient/agent/src/main/resources</directory>
+ <targetPath>${project.build.outputDirectory}/archetype-resources/enduser/src/main/resources/all</targetPath>
+ <includes>
+ <include>oidcclient-agent.properties</include>
+ </includes>
+ </resource>
+ <resource>
<directory>../client/enduser/src/main/resources/META-INF/resources/app</directory>
<targetPath>${project.build.outputDirectory}/archetype-resources/enduser/src/main/webapp/app</targetPath>
</resource>
@@ -292,6 +314,15 @@ under the License.
</includes>
</resource>
<resource>
+ <directory>../fit/enduser-reference/src/main/resources</directory>
+ <targetPath>${project.build.outputDirectory}/archetype-resources/enduser/src/test/resources</targetPath>
+ <includes>
+ <include>enduser.properties</include>
+ <include>oidcclient-agent.properties</include>
+ <include>customForm.json</include>
+ </includes>
+ </resource>
+ <resource>
<directory>../fit/enduser-reference/src/main/webapp/WEB-INF</directory>
<targetPath>${project.build.outputDirectory}/archetype-resources/enduser/src/main/webapp/WEB-INF</targetPath>
</resource>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/archetype/src/main/resources/archetype-resources/console/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/src/main/resources/archetype-resources/console/pom.xml b/archetype/src/main/resources/archetype-resources/console/pom.xml
index 401387e..479126c 100644
--- a/archetype/src/main/resources/archetype-resources/console/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/console/pom.xml
@@ -141,6 +141,12 @@ under the License.
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-console</artifactId>
+ <version>${syncope.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.syncope.ext.scimv2</groupId>
<artifactId>syncope-ext-scimv2-client-console</artifactId>
<version>${syncope.version}</version>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/archetype/src/main/resources/archetype-resources/core/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/src/main/resources/archetype-resources/core/pom.xml b/archetype/src/main/resources/archetype-resources/core/pom.xml
index 68d62b3..f248d9a 100644
--- a/archetype/src/main/resources/archetype-resources/core/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/core/pom.xml
@@ -193,6 +193,17 @@ under the License.
</dependency>
<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>
+
+ <dependency>
<groupId>org.apache.syncope.ext.scimv2</groupId>
<artifactId>syncope-ext-scimv2-rest-cxf</artifactId>
<version>${syncope.version}</version>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/archetype/src/main/resources/archetype-resources/enduser/pom.xml
----------------------------------------------------------------------
diff --git a/archetype/src/main/resources/archetype-resources/enduser/pom.xml b/archetype/src/main/resources/archetype-resources/enduser/pom.xml
index 0b097f3..5f98d31 100644
--- a/archetype/src/main/resources/archetype-resources/enduser/pom.xml
+++ b/archetype/src/main/resources/archetype-resources/enduser/pom.xml
@@ -332,6 +332,12 @@ under the License.
<artifactId>syncope-ext-saml2sp-client-enduser</artifactId>
<version>${syncope.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-enduser</artifactId>
+ <version>${syncope.version}</version>
+ </dependency>
</dependencies>
<build>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/client/enduser/src/main/resources/META-INF/resources/app/index.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/index.html b/client/enduser/src/main/resources/META-INF/resources/app/index.html
index cd4542a..2613a6e 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/index.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/index.html
@@ -100,6 +100,7 @@ under the License.
<script src="js/services/groupService.js"></script>
<script src="js/services/anyService.js"></script>
<script src="js/services/saml2IdPService.js"></script>
+ <script src="js/services/oidcProviderService.js"></script>
<script src="js/services/saml2SPService.js"></script>
<!--controllers-->
<script src="js/controllers/HomeController.js"></script>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
index 3ae4f9d..1019cad 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
@@ -341,7 +341,8 @@ app.run(['$rootScope', '$location', '$state', 'AuthService',
};
}]);
app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'InfoService', 'SAML2IdPService',
- function ($scope, $rootScope, $location, InfoService, SAML2IdPService) {
+ 'OIDCProviderService',
+ function ($scope, $rootScope, $location, InfoService, SAML2IdPService, OIDCProviderService) {
$scope.initApplication = function () {
/*
* disable by default wizard buttons in self-registration
@@ -377,6 +378,10 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I
available: [],
selected: {}
};
+ $rootScope.oidcops = {
+ available: [],
+ selected: {}
+ };
InfoService.getInfo().then(
function (response) {
@@ -406,6 +411,19 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I
/*
* configuration getters
*/
+
+ /* <Extensions> */
+ OIDCProviderService.getAvailableOIDCProviders().then(
+ function (response) {
+ $rootScope.oidcops.available = response;
+ },
+ function (response) {
+ console.debug("No OIDC Client extension available", response);
+ });
+ /* </Extensions> */
+ /*
+ * configuration getters
+ */
$rootScope.isSelfRegAllowed = function () {
return $rootScope.selfRegAllowed === true;
};
@@ -418,6 +436,13 @@ app.controller('ApplicationController', ['$scope', '$rootScope', '$location', 'I
$rootScope.saml2login = function () {
window.location.href = '../saml2sp/login?idp=' + $rootScope.saml2idps.selected.entityID;
};
+
+ $rootScope.oidcclientExtAvailable = function () {
+ return $rootScope.oidcops.available.length > 0;
+ };
+ $rootScope.oidclogin = function () {
+ window.location.href = '../oidcclient/login?op=' + $rootScope.oidcops.selected.name;
+ };
$rootScope.getVersion = function () {
return $rootScope.version;
};
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
index b58aced..d2b755c 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
@@ -34,6 +34,8 @@ angular.module("login").controller("LoginController", ['$scope', '$rootScope', '
$scope.credentials.errorMessage = '';
// reset SAML 2.0 entityID
$rootScope.saml2idps.selected.entityID = null;
+ // reset OIDC name
+ $rootScope.oidcops.selected.name = null;
// got to update page
$location.path("/self/update");
}, function (response) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/client/enduser/src/main/resources/META-INF/resources/app/js/services/oidcProviderService.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/oidcProviderService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/oidcProviderService.js
new file mode 100644
index 0000000..d2ce926
--- /dev/null
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/oidcProviderService.js
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+angular.module('self')
+ .factory('OIDCProviderService', ['$resource', '$q', '$http',
+ function ($resource, $q, $http) {
+
+ var oidcProviderService = {};
+
+ oidcProviderService.getAvailableOIDCProviders = function () {
+ return $http.get("../api/oidcProviders")
+ .then(function (response) {
+ return response.data;
+ }, function (response) {
+ console.error("Something went wrong during oidcProviders extension retrieval, exit with status: ",
+ response);
+ return $q.reject(response.data || response.statusText);
+ });
+ };
+
+ return oidcProviderService;
+ }]);
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/self.html b/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
index 1cc279e..cedb21c 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
@@ -62,6 +62,14 @@ under the License.
ng-model="saml2idps.selected" ng-change="saml2login()">
</select>
</div>
+ <div class="form-group">
+ <span ng-if="$root.oidcclientExtAvailable()">OpenID Connect</span>
+ <select id="oiscclient" style="width: 100%; text-align: left;" class="btn dropdown-toggle btn-default"
+ ng-if="$root.oidcclientExtAvailable()"
+ ng-options="op.name for op in oidcops.available track by op.name"
+ ng-model="oidcops.selected" ng-change="oidclogin()">
+ </select>
+ </div>
</fieldset>
</form>
</div>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/deb/console/pom.xml
----------------------------------------------------------------------
diff --git a/deb/console/pom.xml b/deb/console/pom.xml
index 3a4df52..85c6495 100644
--- a/deb/console/pom.xml
+++ b/deb/console/pom.xml
@@ -55,6 +55,11 @@ under the License.
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-console</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.syncope.ext.scimv2</groupId>
<artifactId>syncope-ext-scimv2-client-console</artifactId>
<version>${project.version}</version>
@@ -116,6 +121,14 @@ under the License.
<filtering>true</filtering>
</resource>
<resource>
+ <directory>${project.basedir}/../../ext/oidcclient/agent/src/main/resources</directory>
+ <includes>
+ <include>oidcclient-agent.properties</include>
+ </includes>
+ <targetPath>${project.build.directory}/etc</targetPath>
+ <filtering>true</filtering>
+ </resource>
+ <resource>
<directory>${basedir}/../../fit/console-reference/src/main/resources</directory>
<includes>
<include>log4j2.xml</include>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/deb/console/src/deb/control/conffiles
----------------------------------------------------------------------
diff --git a/deb/console/src/deb/control/conffiles b/deb/console/src/deb/control/conffiles
index 47e5201..a9bfb08 100644
--- a/deb/console/src/deb/control/conffiles
+++ b/deb/console/src/deb/control/conffiles
@@ -1,3 +1,5 @@
/etc/tomcat8/Catalina/localhost/syncope-console.xml
/etc/apache-syncope/console.properties
/etc/apache-syncope/saml2sp-agent.properties
+/etc/apache-syncope/oidcclient-agent.properties
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/deb/enduser/pom.xml
----------------------------------------------------------------------
diff --git a/deb/enduser/pom.xml b/deb/enduser/pom.xml
index 322b478..c27bf75 100644
--- a/deb/enduser/pom.xml
+++ b/deb/enduser/pom.xml
@@ -44,6 +44,11 @@ under the License.
<version>${project.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-enduser</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.syncope.client</groupId>
<artifactId>syncope-client-enduser</artifactId>
<version>${project.version}</version>
@@ -106,6 +111,14 @@ under the License.
<filtering>true</filtering>
</resource>
<resource>
+ <directory>${project.basedir}/../../ext/oidcclient/agent/src/main/resources</directory>
+ <includes>
+ <include>oidcclient-agent.properties</include>
+ </includes>
+ <targetPath>${project.build.directory}/etc</targetPath>
+ <filtering>true</filtering>
+ </resource>
+ <resource>
<directory>${basedir}/../../fit/enduser-reference/src/main/resources</directory>
<includes>
<include>log4j2.xml</include>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/deb/enduser/src/deb/control/conffiles
----------------------------------------------------------------------
diff --git a/deb/enduser/src/deb/control/conffiles b/deb/enduser/src/deb/control/conffiles
index 934c7fb..8fb2453 100644
--- a/deb/enduser/src/deb/control/conffiles
+++ b/deb/enduser/src/deb/control/conffiles
@@ -2,3 +2,5 @@
/etc/apache-syncope/enduser.properties
/etc/apache-syncope/customForm.json
/etc/apache-syncope/saml2sp-agent.properties
+/etc/apache-syncope/oidcclient-agent.properties
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/deb/enduser/src/deb/control/preinst
----------------------------------------------------------------------
diff --git a/deb/enduser/src/deb/control/preinst b/deb/enduser/src/deb/control/preinst
index afdca38..0e88785 100644
--- a/deb/enduser/src/deb/control/preinst
+++ b/deb/enduser/src/deb/control/preinst
@@ -16,3 +16,4 @@
# specific language governing permissions and limitations
# under the License.
dpkg-divert --add --package apache-syncope-enduser --rename --divert /etc/apache-syncope/saml2sp-agent.properties.disabled /etc/apache-syncope/saml2sp-agent.properties
+dpkg-divert --add --package apache-syncope-enduser --rename --divert /etc/apache-syncope/oidcclient-agent.properties.disabled /etc/apache-syncope/oidcclient-agent.properties
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/agent/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/pom.xml b/ext/oidcclient/agent/pom.xml
new file mode 100644
index 0000000..b4c218e
--- /dev/null
+++ b/ext/oidcclient/agent/pom.xml
@@ -0,0 +1,126 @@
+<?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 Agent</name>
+ <description>Apache Syncope Ext: OIDC Client Agent</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-agent</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>javax.servlet.jsp-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.client</groupId>
+ <artifactId>syncope-client-lib</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>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+
+ <resource>
+ <directory>${basedir}</directory>
+ <targetPath>META-INF</targetPath>
+ <includes>
+ <include>LICENSE</include>
+ <include>NOTICE</include>
+ </includes>
+ </resource>
+ </resources>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>apache-release</id>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <inherited>false</inherited>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ <configuration>
+ <includes>
+ <include>${basedir}/LICENSE</include>
+ <include>${basedir}/NOTICE</include>
+ </includes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/CodeConsumer.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/CodeConsumer.java b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/CodeConsumer.java
new file mode 100644
index 0000000..08e9d23
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/CodeConsumer.java
@@ -0,0 +1,92 @@
+/*
+ * 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.ext.oidcclient.agent;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.OIDCConstants;
+import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
+import org.apache.syncope.common.rest.api.service.OIDCClientService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@WebServlet(name = "codeConsumer", urlPatterns = { "/oidcclient/code-consumer" })
+public class CodeConsumer extends HttpServlet {
+
+ private static final long serialVersionUID = 968480296813639041L;
+
+ protected static final Logger LOG = LoggerFactory.getLogger(CodeConsumer.class);
+
+ @Override
+ protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
+ throws ServletException, IOException {
+
+ try {
+ String authorizationCode = request.getParameter(OIDCConstants.CODE);
+ String state = request.getParameter(OIDCConstants.STATE);
+ if (StringUtils.isBlank(authorizationCode) || StringUtils.isBlank(state)) {
+ throw new IllegalArgumentException("Empty " + OIDCConstants.CODE + " or " + OIDCConstants.STATE);
+ }
+ if (state.equals(request.getSession().getAttribute(OIDCConstants.STATE).toString())) {
+ SyncopeClient anonymous = (SyncopeClient) request.getServletContext().
+ getAttribute(Constants.SYNCOPE_ANONYMOUS_CLIENT);
+
+ OIDCLoginResponseTO responseTO = anonymous.getService(OIDCClientService.class).login(
+ request.getRequestURL().toString(),
+ authorizationCode,
+ request.getSession().getAttribute(OIDCConstants.OP).toString());
+ request.getSession().setAttribute(
+ Constants.OIDCCLIENTJWT, responseTO.getAccessToken());
+ request.getSession().setAttribute(
+ Constants.OIDCCLIENTJWT_EXPIRE, responseTO.getAccessTokenExpiryTime());
+
+ String successURL = getServletContext().getInitParameter(Constants.CONTEXT_PARAM_LOGIN_SUCCESS_URL);
+ if (successURL == null) {
+ request.setAttribute("responseTO", responseTO);
+ request.getRequestDispatcher("loginSuccess.jsp").forward(request, response);
+ } else {
+ response.sendRedirect(successURL);
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid " + OIDCConstants.STATE + " provided");
+ }
+ } catch (Exception e) {
+ LOG.error("While processing authentication response from OP", e);
+ String errorURL = getServletContext().getInitParameter(Constants.CONTEXT_PARAM_LOGIN_ERROR_URL);
+
+ if (errorURL == null) {
+ request.setAttribute("exception", e);
+ request.getRequestDispatcher("loginError.jsp").forward(request, response);
+
+ e.printStackTrace(response.getWriter());
+ } else {
+ response.sendRedirect(errorURL + "?errorMessage="
+ + URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8.name()));
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Constants.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Constants.java b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Constants.java
new file mode 100644
index 0000000..1ff3327
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Constants.java
@@ -0,0 +1,40 @@
+/*
+ * 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.ext.oidcclient.agent;
+
+public final class Constants {
+
+ public static final String SYNCOPE_ANONYMOUS_CLIENT = "SyncopeAnonymousClient";
+
+ public static final String SYNCOPE_CLIENT_FACTORY = "SyncopeClientFactory";
+
+ public static final String PARAM_OP = "op";
+
+ public static final String CONTEXT_PARAM_LOGIN_SUCCESS_URL = "oidcclient.login.success.url";
+
+ public static final String CONTEXT_PARAM_LOGIN_ERROR_URL = "oidcclient.login.error.url";
+
+ public static final String OIDCCLIENTJWT = "oidcclient.jwt";
+
+ public static final String OIDCCLIENTJWT_EXPIRE = "oidcclient.jwt.expire";
+
+ private Constants() {
+ // private constructor for static utility class
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Login.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Login.java b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Login.java
new file mode 100644
index 0000000..36850e4
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/Login.java
@@ -0,0 +1,89 @@
+/*
+ * 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.ext.oidcclient.agent;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriBuilder;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.OIDCConstants;
+import org.apache.syncope.common.lib.to.OIDCLoginRequestTO;
+import org.apache.syncope.common.rest.api.service.OIDCClientService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@WebServlet(name = "oidcclientLogin", urlPatterns = { "/oidcclient/login" })
+public class Login extends HttpServlet {
+
+ private static final long serialVersionUID = 968480296813639041L;
+
+ protected static final Logger LOG = LoggerFactory.getLogger(Login.class);
+
+ @Override
+ protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
+ throws ServletException, IOException {
+
+ String op = request.getParameter(Constants.PARAM_OP);
+
+ SyncopeClient anonymous = (SyncopeClient) request.getServletContext().
+ getAttribute(Constants.SYNCOPE_ANONYMOUS_CLIENT);
+ try {
+ String redirectURI = StringUtils.substringBefore(request.getRequestURL().toString(), "/login")
+ + "/code-consumer";
+ OIDCLoginRequestTO requestTO = anonymous.getService(OIDCClientService.class).
+ createLoginRequest(redirectURI, op);
+
+ request.getSession().setAttribute(OIDCConstants.STATE, requestTO.getState());
+ request.getSession().setAttribute(OIDCConstants.OP, op);
+
+ response.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache, no-store");
+ response.setHeader("Pragma", "no-cache");
+ response.setStatus(HttpServletResponse.SC_SEE_OTHER);
+
+ UriBuilder ub = UriBuilder.fromUri(requestTO.getProviderAddress());
+ ub.queryParam(OIDCConstants.CLIENT_ID, requestTO.getClientId());
+ ub.queryParam(OIDCConstants.REDIRECT_URI, requestTO.getRedirectURI());
+ ub.queryParam(OIDCConstants.RESPOSNSE_TYPE, requestTO.getResponseType());
+ ub.queryParam(OIDCConstants.SCOPE, requestTO.getScope());
+ ub.queryParam(OIDCConstants.STATE, requestTO.getState());
+ response.setHeader("Location", ub.build().toASCIIString());
+ } catch (Exception e) {
+ LOG.error("While preparing the Authentication Request", e);
+
+ String errorURL = getServletContext().getInitParameter(Constants.CONTEXT_PARAM_LOGIN_ERROR_URL);
+ if (errorURL == null) {
+ request.setAttribute("exception", e);
+ request.getRequestDispatcher("loginError.jsp").forward(request, response);
+
+ e.printStackTrace(response.getWriter());
+ } else {
+ response.sendRedirect(errorURL + "?errorMessage="
+ + URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8.name()));
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/OIDCClientAgentSetup.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/OIDCClientAgentSetup.java b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/OIDCClientAgentSetup.java
new file mode 100644
index 0000000..887d0d6
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/java/org/apache/syncope/ext/oidcclient/agent/OIDCClientAgentSetup.java
@@ -0,0 +1,77 @@
+/*
+ * 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.ext.oidcclient.agent;
+
+import java.util.Properties;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.PropertyUtils;
+
+@WebListener
+public class OIDCClientAgentSetup implements ServletContextListener {
+
+ private static final String OIDCCLIENT_AGENT_PROPERTIES = "oidcclient-agent.properties";
+
+ private static <T> T assertNotNull(final T argument, final String name) {
+ if (argument == null) {
+ throw new IllegalArgumentException("Argument '" + name + "' may not be null.");
+ }
+ return argument;
+ }
+
+ @Override
+ public void contextInitialized(final ServletContextEvent sce) {
+ // read oidcclientagent.properties
+ Properties props = PropertyUtils.read(getClass(), OIDCCLIENT_AGENT_PROPERTIES, "conf.directory").getLeft();
+
+ String anonymousUser = props.getProperty("anonymousUser");
+ assertNotNull(anonymousUser, "<anonymousUser>");
+ String anonymousKey = props.getProperty("anonymousKey");
+ assertNotNull(anonymousKey, "<anonymousKey>");
+
+ String scheme = props.getProperty("scheme");
+ assertNotNull(scheme, "<scheme>");
+ String host = props.getProperty("host");
+ assertNotNull(host, "<host>");
+ String port = props.getProperty("port");
+ assertNotNull(port, "<port>");
+ String rootPath = props.getProperty("rootPath");
+ assertNotNull(rootPath, "<rootPath>");
+ String useGZIPCompression = props.getProperty("useGZIPCompression");
+ assertNotNull(useGZIPCompression, "<useGZIPCompression>");
+
+ SyncopeClientFactoryBean clientFactory = new SyncopeClientFactoryBean().
+ setAddress(scheme + "://" + host + ":" + port + "/" + rootPath).
+ setUseCompression(BooleanUtils.toBoolean(useGZIPCompression));
+
+ sce.getServletContext().setAttribute(Constants.SYNCOPE_CLIENT_FACTORY, clientFactory);
+ sce.getServletContext().setAttribute(
+ Constants.SYNCOPE_ANONYMOUS_CLIENT,
+ clientFactory.create(new AnonymousAuthenticationHandler(anonymousUser, anonymousKey)));
+ }
+
+ @Override
+ public void contextDestroyed(final ServletContextEvent sce) {
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginError.jsp
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginError.jsp b/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginError.jsp
new file mode 100644
index 0000000..b3c80d9
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginError.jsp
@@ -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.
+--%>
+<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
+<%
+ Exception exception = (Exception) request.getAttribute("exception");
+%>
+<html>
+ <head>
+ <title>Apache Syncope ${syncope.version} - OIDC CLIENT - Login Error</title>
+ </head>
+ <body>
+ <h1>An error was found</h1>
+
+ <h2><%=exception.getMessage()%></h2>
+ <pre>
+ <%exception.printStackTrace(new java.io.PrintWriter(out));%>
+ </pre>
+ </body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginSuccess.jsp
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginSuccess.jsp b/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginSuccess.jsp
new file mode 100644
index 0000000..7361842
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/resources/META-INF/resources/oidcclient/loginSuccess.jsp
@@ -0,0 +1,33 @@
+<%--
+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.
+--%>
+<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
+<%@page import="org.apache.syncope.common.lib.to.OIDCLoginResponseTO"%>
+<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<c:set var="responseTO" value="${requestScope['responseTO']}"/>
+<html>
+ <head>
+ <title>Apache Syncope ${syncope.version} - OIDC CLIENT - Successful Login</title>
+ </head>
+ <body>
+ <h1>Welcome ${responseTO.userName}</h1>
+
+ <p>You have been successfully authenticated by the requested OIDC Provider</p>
+
+ </body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/agent/src/main/resources/META-INF/web-fragment.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/resources/META-INF/web-fragment.xml b/ext/oidcclient/agent/src/main/resources/META-INF/web-fragment.xml
new file mode 100644
index 0000000..fab858a
--- /dev/null
+++ b/ext/oidcclient/agent/src/main/resources/META-INF/web-fragment.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<web-fragment xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+ http://xmlns.jcp.org/xml/ns/javaee/web-fragment_3_1.xsd"
+ id="${pom.artifactId}" version="3.1">
+
+</web-fragment>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/agent/src/main/resources/oidcclient-agent.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/agent/src/main/resources/oidcclient-agent.properties b/ext/oidcclient/agent/src/main/resources/oidcclient-agent.properties
new file mode 100644
index 0000000..d3fee30
--- /dev/null
+++ b/ext/oidcclient/agent/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=8080
+rootPath=/syncope/rest/
+useGZIPCompression=true
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/pom.xml b/ext/oidcclient/client-console/pom.xml
new file mode 100644
index 0000000..59ba01a
--- /dev/null
+++ b/ext/oidcclient/client-console/pom.xml
@@ -0,0 +1,83 @@
+<?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 Console</name>
+ <description>Apache Syncope Ext: OIDC Client Console</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-console</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-common-lib</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-agent</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.client</groupId>
+ <artifactId>syncope-client-console</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClient.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClient.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClient.java
new file mode 100644
index 0000000..f588733
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClient.java
@@ -0,0 +1,68 @@
+/*
+ * 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.client.console.pages;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.annotations.ExtPage;
+import org.apache.syncope.client.console.panels.OIDCProvidersDirectoryPanel;
+import org.apache.syncope.common.lib.types.OIDCClientEntitlement;
+import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+@ExtPage(label = "OIDC Client", icon = "fa-openid ", listEntitlement = OIDCClientEntitlement.OP_READ, priority = 100)
+public class OIDCClient extends BaseExtPage {
+
+ private static final long serialVersionUID = -599601954212606001L;
+
+ public OIDCClient(final PageParameters parameters) {
+ super(parameters);
+
+ body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class));
+
+ WebMarkupContainer content = new WebMarkupContainer("content");
+ content.setOutputMarkupId(true);
+ content.add(new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList()));
+ body.add(content);
+ }
+
+ private List<ITab> buildTabList() {
+
+ final List<ITab> tabs = new ArrayList<>(1);
+
+ tabs.add(new AbstractTab(new ResourceModel("op")) {
+ private static final long serialVersionUID = -6815067322125799251L;
+
+
+ @Override
+ public Panel getPanel(final String panelId) {
+ return new OIDCProvidersDirectoryPanel(panelId, getPageReference());
+ }
+ });
+
+ return tabs;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClientLogin.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClientLogin.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClientLogin.java
new file mode 100644
index 0000000..41b6cdc
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/pages/OIDCClientLogin.java
@@ -0,0 +1,68 @@
+/*
+ * 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.client.console.pages;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+
+import org.apache.wicket.authentication.IAuthenticationStrategy;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OIDCClientLogin extends WebPage {
+
+ private static final long serialVersionUID = 8581614051773949262L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(OIDCClientLogin.class);
+
+ private static final String OIDC_ACCESS_ERROR = "OIDC access error";
+
+ public OIDCClientLogin(final PageParameters parameters) {
+ super(parameters);
+
+ String token = (String) ((ServletWebRequest) getRequest()).getContainerRequest().
+ getSession().getAttribute(org.apache.syncope.ext.oidcclient.agent.Constants.OIDCCLIENTJWT);
+ if (StringUtils.isBlank(token)) {
+ LOG.error("No JWT found, redirecting to default greeter");
+
+ PageParameters params = new PageParameters();
+ params.add("errorMessage", OIDC_ACCESS_ERROR);
+ setResponsePage(Login.class, params);
+ }
+
+ IAuthenticationStrategy strategy = getApplication().getSecuritySettings().getAuthenticationStrategy();
+
+ if (SyncopeConsoleSession.get().authenticate(token)) {
+
+ // If login has been called because the user was not yet logged in, than continue to the
+ // original destination, otherwise to the Home page
+ continueToOriginalDestination();
+ setResponsePage(getApplication().getHomePage());
+ } else {
+ PageParameters params = new PageParameters();
+ params.add("errorMessage", OIDC_ACCESS_ERROR);
+ setResponsePage(Login.class, params);
+ }
+ strategy.remove();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java
new file mode 100644
index 0000000..dd66cc6
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.java
@@ -0,0 +1,291 @@
+/*
+ * 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.client.console.panels;
+
+import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.DirectoryDataProvider;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
+import org.apache.syncope.client.console.pages.BasePage;
+import org.apache.syncope.client.console.panels.OIDCProvidersDirectoryPanel.OIDCProvidersProvider;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
+import org.apache.syncope.client.console.rest.OIDCProviderRestClient;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.KeyPropertyColumn;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksTogglePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
+import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.client.console.wizards.OIDCProviderWizardBuilder;
+import org.apache.syncope.client.console.wizards.WizardMgtPanel;
+import org.apache.syncope.client.console.wizards.any.AnyWrapper;
+import org.apache.syncope.client.console.wizards.any.UserTemplateWizardBuilder;
+import org.apache.syncope.common.lib.SyncopeClientException;
+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.OIDCClientEntitlement;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.StringResourceModel;
+
+public class OIDCProvidersDirectoryPanel extends DirectoryPanel<
+ OIDCProviderTO, OIDCProviderTO, OIDCProvidersProvider, OIDCProviderRestClient> {
+
+ private static final long serialVersionUID = -1356497878858616714L;
+
+ private static final String PREF_OIDC_PROVIDERS_PAGINATOR_ROWS = "oidc.providers.paginator.rows";
+
+ private final BaseModal<Serializable> templateModal;
+
+ public OIDCProvidersDirectoryPanel(final String id, final PageReference pageRef) {
+ super(id, new Builder<OIDCProviderTO, OIDCProviderTO, OIDCProviderRestClient>(new OIDCProviderRestClient(),
+ pageRef) {
+
+ private static final long serialVersionUID = -5542535388772406165L;
+
+ @Override
+ protected WizardMgtPanel<OIDCProviderTO> newInstance(final String id, final boolean wizardInModal) {
+ throw new UnsupportedOperationException();
+ }
+ }.disableCheckBoxes());
+
+ this.addNewItemPanelBuilder(new OIDCProviderWizardBuilder(this, new OIDCProviderTO(), pageRef), true);
+ MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, OIDCClientEntitlement.OP_CREATE);
+
+ modal.size(Modal.Size.Large);
+
+ actionTogglePanel = new ActionLinksTogglePanel<OIDCProviderTO>("outer", pageRef) {
+
+ private static final long serialVersionUID = -7688359318035249200L;
+
+ @Override
+ public void toggleWithContent(
+ final AjaxRequestTarget target,
+ final ActionsPanel<OIDCProviderTO> actionsPanel,
+ final OIDCProviderTO modelObject) {
+
+ super.toggleWithContent(target, actionsPanel, modelObject);
+ setHeader(target, StringUtils.abbreviate(modelObject.getName(), 25));
+ this.toggle(target, true);
+ }
+
+ };
+ addOuterObject(actionTogglePanel);
+
+ templateModal = new BaseModal<Serializable>("outer") {
+
+ private static final long serialVersionUID = 5787433530654262016L;
+
+ @Override
+ protected void onConfigure() {
+ super.onConfigure();
+ setFooterVisible(false);
+ }
+ };
+ templateModal.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
+
+ private static final long serialVersionUID = 8804221891699487139L;
+
+ @Override
+ public void onClose(final AjaxRequestTarget target) {
+// target.add(content);
+ templateModal.show(false);
+ }
+ });
+ templateModal.size(Modal.Size.Large);
+ addOuterObject(templateModal);
+
+ initResultTable();
+
+ }
+
+ @Override
+ protected OIDCProvidersProvider dataProvider() {
+ return new OIDCProvidersProvider(rows);
+ }
+
+ @Override
+ protected String paginatorRowsKey() {
+ return PREF_OIDC_PROVIDERS_PAGINATOR_ROWS;
+
+ }
+
+ @Override
+ protected List<IColumn<OIDCProviderTO, String>> getColumns() {
+ List<IColumn<OIDCProviderTO, String>> columns = new ArrayList<>();
+ columns.add(new KeyPropertyColumn<OIDCProviderTO>(new ResourceModel("key"), "key", "key"));
+ columns.add(new PropertyColumn<OIDCProviderTO, String>(new ResourceModel("name"), "name", "name"));
+ columns.add(new PropertyColumn<OIDCProviderTO, String>(new ResourceModel("issuer"), "issuer", "issuer"));
+ columns.add(new PropertyColumn<OIDCProviderTO, String>(new ResourceModel("clientID"), "clientID", "clientID"));
+ return columns;
+
+ }
+
+ @Override
+ protected Collection<ActionLink.ActionType> getBulkActions() {
+ return Collections.<ActionLink.ActionType>emptyList();
+
+ }
+
+ @Override
+ public ActionsPanel<OIDCProviderTO> getActions(final IModel<OIDCProviderTO> model) {
+ final ActionsPanel<OIDCProviderTO> panel = super.getActions(model);
+
+ panel.add(new ActionLink<OIDCProviderTO>() {
+
+ private static final long serialVersionUID = -3722207913631435501L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target, final OIDCProviderTO ignore) {
+ OIDCProviderTO object = restClient.read(model.getObject().getKey());
+ send(OIDCProvidersDirectoryPanel.this, Broadcast.EXACT,
+ new AjaxWizard.EditItemActionEvent<>(object, target));
+ modal.header(Model.of(StringUtils.capitalize(("Edit " + object.getName()))));
+ }
+ }, ActionLink.ActionType.EDIT, OIDCClientEntitlement.OP_UPDATE);
+
+ panel.add(new ActionLink<OIDCProviderTO>() {
+
+ private static final long serialVersionUID = 8557679125857348178L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target, final OIDCProviderTO ignore) {
+ final OIDCProviderTO object = restClient.read(model.getObject().getKey());
+
+ UserTemplateWizardBuilder builder = new UserTemplateWizardBuilder(
+ object.getUserTemplate(),
+ new AnyTypeRestClient().read(AnyTypeKind.USER.name()).getClasses(),
+ new UserFormLayoutInfo(),
+ pageRef) {
+
+ private static final long serialVersionUID = -7978723352517770634L;
+
+ @Override
+ protected Serializable onApplyInternal(final AnyWrapper<UserTO> modelObject) {
+ object.setUserTemplate(modelObject.getInnerObject());
+ restClient.update(object);
+
+ return modelObject;
+ }
+ };
+ templateModal.header(Model.of(StringUtils.capitalize(
+ new StringResourceModel("template.title", OIDCProvidersDirectoryPanel.this).getString())));
+ templateModal.setContent(builder.build(BaseModal.CONTENT_ID));
+ templateModal.show(true);
+ target.add(templateModal);
+
+ }
+ }, ActionLink.ActionType.TEMPLATE, OIDCClientEntitlement.OP_UPDATE);
+
+ panel.add(new ActionLink<OIDCProviderTO>() {
+
+ private static final long serialVersionUID = -5467832321897812767L;
+
+ @Override
+ public void onClick(final AjaxRequestTarget target, final OIDCProviderTO ignore) {
+ try {
+ restClient.delete(model.getObject().getKey());
+ SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
+ target.add(container);
+ } catch (SyncopeClientException e) {
+ LOG.error("While deleting object {}", model.getObject().getKey(), e);
+ SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+ ? e.getClass().getName() : e.getMessage());
+ }
+ ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+ }
+ }, ActionLink.ActionType.DELETE, OIDCClientEntitlement.OP_DELETE, true);
+ return panel;
+ }
+
+ @Override
+ public void onEvent(final IEvent<?> event) {
+ super.onEvent(event);
+
+ if (event.getPayload() instanceof AjaxWizard.NewItemEvent) {
+ AjaxWizard.NewItemEvent<?> newItemEvent = AjaxWizard.NewItemEvent.class.cast(event.getPayload());
+ WizardModalPanel<?> modalPanel = newItemEvent.getModalPanel();
+
+ if (event.getPayload() instanceof AjaxWizard.NewItemActionEvent && modalPanel != null) {
+ final IModel<Serializable> model = new CompoundPropertyModel<>(modalPanel.getItem());
+ templateModal.setFormModel(model);
+ templateModal.header(newItemEvent.getResourceModel());
+ newItemEvent.getTarget().add(templateModal.setContent(modalPanel));
+ templateModal.show(true);
+ } else if (event.getPayload() instanceof AjaxWizard.NewItemCancelEvent) {
+ templateModal.close(newItemEvent.getTarget());
+ } else if (event.getPayload() instanceof AjaxWizard.NewItemFinishEvent) {
+ templateModal.close(newItemEvent.getTarget());
+ }
+ }
+ }
+
+ protected final class OIDCProvidersProvider extends DirectoryDataProvider<OIDCProviderTO> {
+
+ private static final long serialVersionUID = -2865055116864423761L;
+
+ private final SortableDataProviderComparator<OIDCProviderTO> comparator;
+
+ public OIDCProvidersProvider(final int paginatorRows) {
+ super(paginatorRows);
+
+ setSort("name", SortOrder.ASCENDING);
+ comparator = new SortableDataProviderComparator<>(this);
+ }
+
+ @Override
+ public Iterator<OIDCProviderTO> iterator(final long first, final long count) {
+ List<OIDCProviderTO> list = restClient.list();
+ Collections.sort(list, comparator);
+ return list.subList((int) first, (int) first + (int) count).iterator();
+ }
+
+ @Override
+ public long size() {
+ return restClient.list().size();
+ }
+
+ @Override
+ public IModel<OIDCProviderTO> model(final OIDCProviderTO object) {
+ return new CompoundPropertyModel<>(object);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.java
new file mode 100644
index 0000000..5b108e5
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.java
@@ -0,0 +1,109 @@
+/*
+ * 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.client.console.panels;
+
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.UrlUtils;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.http.handler.RedirectRequestHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OIDCSSOLoginFormPanel extends SSOLoginFormPanel {
+
+ private static final long serialVersionUID = 1154933731474854671L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(OIDCSSOLoginFormPanel.class);
+
+ public OIDCSSOLoginFormPanel(final String id) {
+ super(id);
+
+ List<OIDCProviderTO> available =
+ SyncopeConsoleSession.get().getAnonymousClient().getService(OIDCProviderService.class).list();
+
+ final Model<OIDCProviderTO> model = new Model<>();
+ AjaxDropDownChoicePanel<OIDCProviderTO> ops =
+ new AjaxDropDownChoicePanel<>("ops", "OpenID Connect", model, false);
+ ops.setChoices(available);
+ ops.setChoiceRenderer(new IChoiceRenderer<OIDCProviderTO>() {
+
+ private static final long serialVersionUID = 1814750973898916102L;
+
+ @Override
+ public Object getDisplayValue(final OIDCProviderTO object) {
+ return object.getName();
+ }
+
+ @Override
+ public String getIdValue(final OIDCProviderTO object, final int index) {
+ return object.getName();
+ }
+
+ @Override
+ public OIDCProviderTO getObject(final String id,
+ final IModel<? extends List<? extends OIDCProviderTO>> choices) {
+ return IterableUtils.find(choices.getObject(), new Predicate<OIDCProviderTO>() {
+
+ @Override
+ public boolean evaluate(final OIDCProviderTO object) {
+ return object.getName().equals(id);
+ }
+ });
+ }
+ });
+
+ ops.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+ private static final long serialVersionUID = -1107858522700306810L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ if (model.getObject() != null) {
+ try {
+ RequestCycle.get().scheduleRequestHandlerAfterCurrent(new RedirectRequestHandler(
+ UrlUtils.rewriteToContextRelative("oidcclient/login?op="
+ + URLEncoder.encode(
+ model.getObject().getName(), StandardCharsets.UTF_8.name()),
+ RequestCycle.get())));
+ } catch (Exception e) {
+ LOG.error("Could not redirect to the selected OP {}", model.getObject().getName(), e);
+ }
+ }
+ }
+ });
+ ops.setOutputMarkupPlaceholderTag(true);
+ ops.setVisible(!available.isEmpty());
+ add(ops);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/rest/OIDCProviderRestClient.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/rest/OIDCProviderRestClient.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/rest/OIDCProviderRestClient.java
new file mode 100644
index 0000000..a666d74
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/rest/OIDCProviderRestClient.java
@@ -0,0 +1,59 @@
+/*
+ * 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.client.console.rest;
+
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
+
+public class OIDCProviderRestClient extends BaseRestClient {
+
+ private static final long serialVersionUID = -4006712447589576324L;
+
+ public List<OIDCProviderTO> list() {
+ return getService(OIDCProviderService.class).list();
+ }
+
+ public Set<String> getActionsClasses() {
+ return getService(OIDCProviderService.class).getActionsClasses();
+ }
+
+ public void create(final OIDCProviderTO op) {
+ SyncopeConsoleSession.get().getService(OIDCProviderService.class).create(op);
+ }
+
+ public void createFromDiscovery(final OIDCProviderTO op) {
+ SyncopeConsoleSession.get().getService(OIDCProviderService.class).createFromDiscovery(op);
+ }
+
+ public OIDCProviderTO read(final String key) {
+ return getService(OIDCProviderService.class).read(key);
+ }
+
+ public void update(final OIDCProviderTO op) {
+ getService(OIDCProviderService.class).update(op);
+ }
+
+ public void delete(final String key) {
+ getService(OIDCProviderService.class).delete(key);
+ }
+
+}
[7/8] syncope git commit: [SYNCOPE-1270] implementation for OpenID
Connect for Admin Console and Enduser - This closes #74
Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderMappingPanel.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderMappingPanel.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderMappingPanel.java
new file mode 100644
index 0000000..d12965e
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderMappingPanel.java
@@ -0,0 +1,104 @@
+/*
+ * 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.client.console.wizards;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.console.wizards.resources.ItemTransformersTogglePanel;
+import org.apache.syncope.client.console.wizards.resources.JEXLTransformersTogglePanel;
+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.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.util.ListModel;
+
+public class OIDCProviderMappingPanel extends AbstractMappingPanel {
+
+ private static final long serialVersionUID = -4123879435574382968L;
+
+ public OIDCProviderMappingPanel(
+ final String id,
+ final OIDCProviderTO opTO,
+ final ItemTransformersTogglePanel mapItemTransformers,
+ final JEXLTransformersTogglePanel jexlTransformers) {
+
+ super(id,
+ mapItemTransformers,
+ jexlTransformers,
+ new ListModel<ItemTO>(opTO.getItems()),
+ true,
+ true,
+ MappingPurpose.NONE);
+
+ setOutputMarkupId(true);
+ }
+
+ @Override
+ protected void onBeforeRender() {
+ super.onBeforeRender();
+ purposeLabel.setVisible(false);
+ }
+
+ @Override
+ protected IModel<List<String>> getExtAttrNames() {
+ List<String> extAttrNames = new ArrayList<>();
+ extAttrNames.add("email");
+ extAttrNames.add("family_name");
+ extAttrNames.add("name");
+ extAttrNames.add("middle_name");
+ extAttrNames.add("given_name");
+ extAttrNames.add("preferred_username");
+ extAttrNames.add("nickname");
+ extAttrNames.add("profile");
+ extAttrNames.add("gender");
+ extAttrNames.add("locale");
+ extAttrNames.add("zoneinfo");
+ extAttrNames.add("birthdate");
+ extAttrNames.add("phone_number");
+ extAttrNames.add("address");
+ extAttrNames.add("updated_at");
+
+ return Model.ofList(extAttrNames);
+ }
+
+ @Override
+ protected void setAttrNames(final AjaxTextFieldPanel toBeUpdated) {
+ toBeUpdated.setRequired(true);
+ toBeUpdated.setEnabled(true);
+
+ List<String> choices = new ArrayList<>(USER_FIELD_NAMES);
+
+ for (AnyTypeClassTO anyTypeClassTO : anyTypeClassRestClient.list(
+ anyTypeRestClient.read(AnyTypeKind.USER.name()).getClasses())) {
+
+ choices.addAll(anyTypeClassTO.getPlainSchemas());
+ choices.addAll(anyTypeClassTO.getDerSchemas());
+ choices.addAll(anyTypeClassTO.getVirSchemas());
+ }
+
+ Collections.sort(choices);
+ toBeUpdated.setChoices(choices);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java
new file mode 100644
index 0000000..2fa465a
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/java/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder.java
@@ -0,0 +1,290 @@
+/*
+ * 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.client.console.wizards;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.panels.OIDCProvidersDirectoryPanel;
+import org.apache.syncope.client.console.rest.OIDCProviderRestClient;
+import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxPalettePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.client.console.wizards.resources.ItemTransformersTogglePanel;
+import org.apache.syncope.client.console.wizards.resources.JEXLTransformersTogglePanel;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.extensions.wizard.WizardStep;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.StringResourceModel;
+import org.apache.wicket.model.util.ListModel;
+import org.apache.wicket.validation.validator.UrlValidator;
+
+public class OIDCProviderWizardBuilder extends AjaxWizardBuilder<OIDCProviderTO> {
+
+ private static final long serialVersionUID = -3310772400714122768L;
+
+ private final OIDCProviderRestClient restClient = new OIDCProviderRestClient();
+
+ private final OIDCProvidersDirectoryPanel directoryPanel;
+
+ private final IModel<List<String>> actionsClasses = new LoadableDetachableModel<List<String>>() {
+
+ private static final long serialVersionUID = 5275935387613157437L;
+
+ @Override
+ protected List<String> load() {
+ return new ArrayList<>(restClient.getActionsClasses());
+ }
+ };
+
+ public OIDCProviderWizardBuilder(final OIDCProvidersDirectoryPanel directoryPanel, final OIDCProviderTO defaultItem,
+ final PageReference pageRef) {
+ super(defaultItem, pageRef);
+ this.directoryPanel = directoryPanel;
+ }
+
+ @Override
+ protected Serializable onApplyInternal(final OIDCProviderTO modelObject) {
+ if (modelObject.getKey() == null) {
+ if (modelObject.getHasDiscovery()) {
+ restClient.createFromDiscovery(modelObject);
+ } else {
+ restClient.create(modelObject);
+ }
+
+ } else {
+ restClient.update(modelObject);
+ }
+ return modelObject;
+ }
+
+ @Override
+ protected WizardModel buildModelSteps(final OIDCProviderTO modelObject, final WizardModel wizardModel) {
+ wizardModel.add(new OP(modelObject));
+ if (modelObject.getKey() == null) {
+ wizardModel.add(new OPContinue(modelObject));
+ } else {
+ wizardModel.add(new OPContinue(modelObject, true));
+ }
+
+ Mapping mapping = new Mapping(modelObject);
+ mapping.setOutputMarkupId(true);
+
+ ItemTransformersTogglePanel mapItemTransformers = new ItemTransformersTogglePanel(mapping, pageRef);
+ addOuterObject(mapItemTransformers);
+ JEXLTransformersTogglePanel jexlTransformers = new JEXLTransformersTogglePanel(mapping, pageRef);
+ addOuterObject(jexlTransformers);
+ mapping.add(new OIDCProviderMappingPanel("mapping", modelObject, mapItemTransformers, jexlTransformers));
+
+ wizardModel.add(mapping);
+
+ return wizardModel;
+ }
+
+ public class OP extends WizardStep {
+
+ private static final long serialVersionUID = 7127421283216134900L;
+
+ public OP(final OIDCProviderTO opTO) {
+ AjaxTextFieldPanel name = new AjaxTextFieldPanel(
+ "name", "name", new PropertyModel<String>(opTO, "name"), false);
+ name.addRequiredLabel();
+ name.setEnabled(true);
+ add(name);
+
+ AjaxTextFieldPanel clientID = new AjaxTextFieldPanel(
+ "clientID", "clientID", new PropertyModel<String>(opTO, "clientID"), false);
+ clientID.addRequiredLabel();
+ clientID.setEnabled(true);
+ add(clientID);
+
+ AjaxTextFieldPanel clientSecret = new AjaxTextFieldPanel(
+ "clientSecret", "clientSecret", new PropertyModel<String>(opTO, "clientSecret"), false);
+ clientSecret.addRequiredLabel();
+ clientSecret.setEnabled(true);
+ add(clientSecret);
+
+ AjaxCheckBoxPanel createUnmatching = new AjaxCheckBoxPanel(
+ "createUnmatching", "createUnmatching", new PropertyModel<Boolean>(opTO, "createUnmatching"),
+ false);
+ add(createUnmatching);
+
+ AjaxCheckBoxPanel updateMatching = new AjaxCheckBoxPanel(
+ "updateMatching", "updateMatching", new PropertyModel<Boolean>(opTO, "updateMatching"), false);
+ add(updateMatching);
+
+ AjaxPalettePanel<String> actionsClassNames = new AjaxPalettePanel.Builder<String>().
+ setAllowMoveAll(true).setAllowOrder(true).
+ setName(new StringResourceModel("actionsClassNames", directoryPanel).getString()).
+ build("actionsClassNames",
+ new PropertyModel<List<String>>(opTO, "actionsClassNames"),
+ new ListModel<>(actionsClasses.getObject()));
+ actionsClassNames.setOutputMarkupId(true);
+ add(actionsClassNames);
+ }
+ }
+
+ public class OPContinue extends WizardStep {
+
+ private static final long serialVersionUID = -7087008312629522790L;
+
+ public OPContinue(final OIDCProviderTO opTO) {
+
+ final WebMarkupContainer content = new WebMarkupContainer("content");
+ this.setOutputMarkupId(true);
+ content.setOutputMarkupId(true);
+ add(content);
+
+ UrlValidator urlValidator = new UrlValidator();
+ final AjaxTextFieldPanel issuer = new AjaxTextFieldPanel(
+ "issuer", "issuer", new PropertyModel<String>(opTO, "issuer"));
+ issuer.addValidator(urlValidator);
+ issuer.addRequiredLabel();
+ content.add(issuer);
+
+ final AjaxCheckBoxPanel hasDiscovery = new AjaxCheckBoxPanel(
+ "hasDiscovery", "hasDiscovery", new PropertyModel<Boolean>(opTO, "hasDiscovery"));
+ content.add(hasDiscovery);
+
+ final AjaxTextFieldPanel authorizationEndpoint = new AjaxTextFieldPanel("authorizationEndpoint",
+ "authorizationEndpoint", new PropertyModel<String>(opTO, "authorizationEndpoint"));
+ authorizationEndpoint.addRequiredLabel();
+ authorizationEndpoint.addValidator(urlValidator);
+ content.add(authorizationEndpoint);
+
+ final AjaxTextFieldPanel userinfoEndpoint = new AjaxTextFieldPanel("userinfoEndpoint",
+ "userinfoEndpoint", new PropertyModel<String>(opTO, "userinfoEndpoint"));
+ userinfoEndpoint.addRequiredLabel();
+ userinfoEndpoint.addValidator(urlValidator);
+ content.add(userinfoEndpoint);
+
+ final AjaxTextFieldPanel tokenEndpoint = new AjaxTextFieldPanel("tokenEndpoint",
+ "tokenEndpoint", new PropertyModel<String>(opTO, "tokenEndpoint"));
+ tokenEndpoint.addRequiredLabel();
+ tokenEndpoint.addValidator(urlValidator);
+ content.add(tokenEndpoint);
+
+ final AjaxTextFieldPanel jwksUri = new AjaxTextFieldPanel("jwksUri",
+ "jwksUri", new PropertyModel<String>(opTO, "jwksUri"));
+ jwksUri.addRequiredLabel();
+ jwksUri.addValidator(urlValidator);
+ content.add(jwksUri);
+
+ final WebMarkupContainer visibleParam = new WebMarkupContainer("visibleParams");
+ visibleParam.setOutputMarkupPlaceholderTag(true);
+ visibleParam.add(authorizationEndpoint);
+ visibleParam.add(userinfoEndpoint);
+ visibleParam.add(tokenEndpoint);
+ visibleParam.add(jwksUri);
+ content.add(visibleParam);
+
+ showHide(hasDiscovery, visibleParam);
+
+ hasDiscovery.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+ private static final long serialVersionUID = -1107858522700306810L;
+
+ @Override
+ protected void onUpdate(final AjaxRequestTarget target) {
+ showHide(hasDiscovery, visibleParam);
+ target.add(visibleParam);
+ }
+ });
+
+ }
+
+ public OPContinue(final OIDCProviderTO opTO, final boolean readOnly) {
+
+ final WebMarkupContainer content = new WebMarkupContainer("content");
+ this.setOutputMarkupId(true);
+ content.setOutputMarkupId(true);
+ add(content);
+
+ final AjaxTextFieldPanel issuer = new AjaxTextFieldPanel(
+ "issuer", "issuer", new PropertyModel<String>(opTO, "issuer"));
+ issuer.setReadOnly(readOnly);
+ content.add(issuer);
+
+ final AjaxCheckBoxPanel hasDiscovery = new AjaxCheckBoxPanel(
+ "hasDiscovery", "hasDiscovery", new PropertyModel<Boolean>(opTO, "hasDiscovery"));
+ hasDiscovery.setReadOnly(readOnly);
+ content.add(hasDiscovery);
+
+ final AjaxTextFieldPanel authorizationEndpoint = new AjaxTextFieldPanel("authorizationEndpoint",
+ "authorizationEndpoint", new PropertyModel<String>(opTO, "authorizationEndpoint"));
+ authorizationEndpoint.setReadOnly(readOnly);
+ content.add(authorizationEndpoint);
+
+ final AjaxTextFieldPanel userinfoEndpoint = new AjaxTextFieldPanel("userinfoEndpoint",
+ "userinfoEndpoint", new PropertyModel<String>(opTO, "userinfoEndpoint"));
+ userinfoEndpoint.setReadOnly(readOnly);
+ content.add(userinfoEndpoint);
+
+ final AjaxTextFieldPanel tokenEndpoint = new AjaxTextFieldPanel("tokenEndpoint",
+ "tokenEndpoint", new PropertyModel<String>(opTO, "tokenEndpoint"));
+ tokenEndpoint.setReadOnly(readOnly);
+ content.add(tokenEndpoint);
+
+ final AjaxTextFieldPanel jwksUri = new AjaxTextFieldPanel("jwksUri",
+ "jwksUri", new PropertyModel<String>(opTO, "jwksUri"));
+ jwksUri.setReadOnly(readOnly);
+ content.add(jwksUri);
+
+ final WebMarkupContainer visibleParam = new WebMarkupContainer("visibleParams");
+ visibleParam.setOutputMarkupPlaceholderTag(true);
+ visibleParam.add(authorizationEndpoint);
+ visibleParam.add(userinfoEndpoint);
+ visibleParam.add(tokenEndpoint);
+ visibleParam.add(jwksUri);
+ content.add(visibleParam);
+ }
+ }
+
+ private void showHide(final AjaxCheckBoxPanel hasDiscovery, final WebMarkupContainer visibleParams) {
+ if (hasDiscovery.getField().getValue().equals("false")) {
+ visibleParams.setVisible(true);
+ } else {
+ visibleParams.setVisible(false);
+ }
+ }
+
+ /**
+ * Mapping definition step.
+ */
+ private static final class Mapping extends WizardStep {
+
+ private static final long serialVersionUID = 3454904947720856253L;
+
+ Mapping(final OIDCProviderTO item) {
+ setTitleModel(Model.of("Mapping"));
+ setSummaryModel(Model.of(StringUtils.EMPTY));
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.html
new file mode 100644
index 0000000..a1a0aed
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:extend>
+ <section class="content-header">
+ <h1> </h1>
+ <ol class="breadcrumb">
+ <li><a wicket:id="dashboardBr"><i class="fa fa-dashboard"></i> <wicket:message key="dashboard"/></a></li>
+ <li class="active"><wicket:message key="extensions"/></li>
+ <li class="active">OIDC Client</li>
+ </ol>
+ </section>
+
+ <section class="content" wicket:id="content">
+ <div class="box">
+ <div class="box-body" wicket:id="tabbedPanel"/>
+ </div>
+ </section>
+ </wicket:extend>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.properties
new file mode 100644
index 0000000..b34f11c
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient.properties
@@ -0,0 +1,17 @@
+# 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.
+op=OIDC Providers
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_it.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_it.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_it.properties
new file mode 100644
index 0000000..b34f11c
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_it.properties
@@ -0,0 +1,17 @@
+# 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.
+op=OIDC Providers
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_pt_BR.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_pt_BR.properties
new file mode 100644
index 0000000..b34f11c
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_pt_BR.properties
@@ -0,0 +1,17 @@
+# 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.
+op=OIDC Providers
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_ru.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_ru.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_ru.properties
new file mode 100644
index 0000000..b34f11c
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/pages/OIDCClient_ru.properties
@@ -0,0 +1,17 @@
+# 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.
+op=OIDC Providers
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.html
new file mode 100644
index 0000000..ce0dbe8
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.html
@@ -0,0 +1,23 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:extend>
+
+ </wicket:extend>
+</html>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.properties
new file mode 100644
index 0000000..569d0dc
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel.properties
@@ -0,0 +1,30 @@
+# 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.
+clientID=Client ID
+clientSecret=Client Secret
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+any.new=New Provider
+template.title=user template
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_it.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_it.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_it.properties
new file mode 100644
index 0000000..569d0dc
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_it.properties
@@ -0,0 +1,30 @@
+# 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.
+clientID=Client ID
+clientSecret=Client Secret
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+any.new=New Provider
+template.title=user template
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_pt_BR.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_pt_BR.properties
new file mode 100644
index 0000000..569d0dc
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_pt_BR.properties
@@ -0,0 +1,30 @@
+# 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.
+clientID=Client ID
+clientSecret=Client Secret
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+any.new=New Provider
+template.title=user template
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_ru.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_ru.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_ru.properties
new file mode 100644
index 0000000..569d0dc
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCProvidersDirectoryPanel_ru.properties
@@ -0,0 +1,30 @@
+# 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.
+clientID=Client ID
+clientSecret=Client Secret
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+any.new=New Provider
+template.title=user template
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.html
new file mode 100644
index 0000000..3b30b4c
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/panels/OIDCSSOLoginFormPanel.html
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <div class="form-group">
+ <span wicket:id="ops"></span>
+ </div>
+ </wicket:panel>
+</html>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$Mapping.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$Mapping.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$Mapping.html
new file mode 100644
index 0000000..11b1a52
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$Mapping.html
@@ -0,0 +1,23 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <span wicket:id="mapping" />
+ </wicket:panel>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.html
new file mode 100644
index 0000000..4ad49d8
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.html
@@ -0,0 +1,28 @@
+<!--
+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. actionsClassNames
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <div class="form-group"><span wicket:id="name">[name]</span></div>
+ <div class="form-group"><span wicket:id="clientID">[clientID]</span></div>
+ <div class="form-group"><span wicket:id="clientSecret">[clientSecret]</span></div>
+ <div class="form-group"><span wicket:id="createUnmatching">[createUnmatching]</span></div>
+ <div class="form-group"><span wicket:id="updateMatching">[updateMatching]</span></div>
+ <div class="form-group"><span wicket:id="actionsClassNames">[actionsClassNames]</span></div>
+ </wicket:panel>
+</html>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.properties
new file mode 100644
index 0000000..5ed531a
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP.properties
@@ -0,0 +1,24 @@
+# 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.
+name=Name
+clientID=Client ID
+clientSecret=Client Secret
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html
new file mode 100644
index 0000000..01da6ec
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.html
@@ -0,0 +1,33 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+ <wicket:panel>
+ <div wicket:id="content">
+ <span wicket:id="issuer">[issuer]</span>
+ <span wicket:id="hasDiscovery">[hasDiscovery]</span>
+
+ <div wicket:id="visibleParams">
+ <span wicket:id="authorizationEndpoint">[authorizationEndpoint]</span>
+ <span wicket:id="tokenEndpoint">[tokenEndpoint]</span>
+ <span wicket:id="jwksUri">[jwksUri]</span>
+ <span wicket:id="userinfoEndpoint">[userinfoEndpoint]</span>
+ </div>
+ </div>
+ </wicket:panel>
+</html>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.properties
new file mode 100644
index 0000000..3f1d085
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue.properties
@@ -0,0 +1,27 @@
+# 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.
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+tokenEndpoint= Token Endpoint
+jwksUri= JWKS URI
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_it.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_it.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_it.properties
new file mode 100644
index 0000000..3f1d085
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_it.properties
@@ -0,0 +1,27 @@
+# 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.
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+tokenEndpoint= Token Endpoint
+jwksUri= JWKS URI
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_pt_BR.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_pt_BR.properties
new file mode 100644
index 0000000..3f1d085
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_pt_BR.properties
@@ -0,0 +1,27 @@
+# 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.
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+tokenEndpoint= Token Endpoint
+jwksUri= JWKS URI
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_ru.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_ru.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_ru.properties
new file mode 100644
index 0000000..3f1d085
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OPContinue_ru.properties
@@ -0,0 +1,27 @@
+# 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.
+issuer=Issuer
+hasDiscovery= Has Discovery Document
+authorizationEndpoint= Authorization Endpoint
+userinfoEndpoint= Userinfo Endpoint
+tokenEndpoint= Token Endpoint
+jwksUri= JWKS URI
+
+
+
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_it.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_it.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_it.properties
new file mode 100644
index 0000000..5ed531a
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_it.properties
@@ -0,0 +1,24 @@
+# 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.
+name=Name
+clientID=Client ID
+clientSecret=Client Secret
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_pt_BR.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_pt_BR.properties
new file mode 100644
index 0000000..5ed531a
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_pt_BR.properties
@@ -0,0 +1,24 @@
+# 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.
+name=Name
+clientID=Client ID
+clientSecret=Client Secret
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_ru.properties
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_ru.properties b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_ru.properties
new file mode 100644
index 0000000..5ed531a
--- /dev/null
+++ b/ext/oidcclient/client-console/src/main/resources/org/apache/syncope/client/console/wizards/OIDCProviderWizardBuilder$OP_ru.properties
@@ -0,0 +1,24 @@
+# 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.
+name=Name
+clientID=Client ID
+clientSecret=Client Secret
+createUnmatching=Create unmatching users
+updateMatching=Update matching users
+actionsClassNames=Actions
+
+
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-enduser/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-enduser/pom.xml b/ext/oidcclient/client-enduser/pom.xml
new file mode 100644
index 0000000..c7213c8
--- /dev/null
+++ b/ext/oidcclient/client-enduser/pom.xml
@@ -0,0 +1,83 @@
+<?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 Enduser</name>
+ <description>Apache Syncope Ext: OIDC Client Enduser</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-client-enduser</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-common-lib</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-agent</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.syncope.client</groupId>
+ <artifactId>syncope-client-enduser</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/OIDCClientLogin.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/OIDCClientLogin.java b/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/OIDCClientLogin.java
new file mode 100644
index 0000000..5aa8578
--- /dev/null
+++ b/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/OIDCClientLogin.java
@@ -0,0 +1,63 @@
+/*
+ * 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.client.enduser.pages;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.wicket.authentication.IAuthenticationStrategy;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OIDCClientLogin extends WebPage {
+
+ private static final long serialVersionUID = 8581614051773949262L;
+
+ private static final Logger LOG = LoggerFactory.getLogger(OIDCClientLogin.class);
+
+ private static final String OIDC_ACCESS_ERROR = "OIDC access error";
+
+ public OIDCClientLogin(final PageParameters parameters) {
+ super(parameters);
+
+ String token = (String) ((ServletWebRequest) getRequest()).getContainerRequest().
+ getSession().getAttribute(org.apache.syncope.ext.oidcclient.agent.Constants.OIDCCLIENTJWT);
+ if (StringUtils.isBlank(token)) {
+ LOG.error("No JWT found, redirecting to default greeter");
+
+ PageParameters params = new PageParameters();
+ params.add("errorMessage", OIDC_ACCESS_ERROR);
+ setResponsePage(getApplication().getHomePage(), params);
+ }
+
+ IAuthenticationStrategy strategy = getApplication().getSecuritySettings().getAuthenticationStrategy();
+
+ if (SyncopeEnduserSession.get().authenticate(token)) {
+ setResponsePage(getApplication().getHomePage());
+ } else {
+ PageParameters params = new PageParameters();
+ params.add("errorMessage", OIDC_ACCESS_ERROR);
+ setResponsePage(getApplication().getHomePage(), params);
+ }
+ strategy.remove();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/OIDCProvidersResource.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/OIDCProvidersResource.java b/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/OIDCProvidersResource.java
new file mode 100644
index 0000000..0faeba6
--- /dev/null
+++ b/ext/oidcclient/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/OIDCProvidersResource.java
@@ -0,0 +1,69 @@
+/*
+ * 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.client.enduser.resources;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.client.enduser.SyncopeEnduserSession;
+import org.apache.syncope.client.enduser.annotations.Resource;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
+import org.apache.wicket.request.resource.AbstractResource;
+
+@Resource(key = "oidcProviders", path = "/api/oidcProviders")
+public class OIDCProvidersResource extends BaseResource {
+
+ private static final long serialVersionUID = -6595407257133697170L;
+
+ @Override
+ protected ResourceResponse newResourceResponse(final Attributes attributes) {
+ ResourceResponse response = new ResourceResponse();
+ response.setContentType(MediaType.APPLICATION_JSON);
+ response.setTextEncoding(StandardCharsets.UTF_8.name());
+ try {
+ final ArrayNode result = MAPPER.createArrayNode();
+
+ SyncopeEnduserSession.get().getService(OIDCProviderService.class).list().forEach(op -> {
+ ObjectNode opNode = MAPPER.createObjectNode();
+ opNode.put("name", op.getName());
+ result.add(opNode);
+ });
+
+ response.setWriteCallback(new AbstractResource.WriteCallback() {
+
+ @Override
+ public void writeData(final Attributes attributes) throws IOException {
+ attributes.getResponse().write(MAPPER.writeValueAsString(result));
+ }
+ });
+ response.setStatusCode(Response.Status.OK.getStatusCode());
+ } catch (Exception e) {
+ LOG.error("Error retrieving available OIDC Providers", e);
+ response.setError(
+ Response.Status.BAD_REQUEST.getStatusCode(),
+ "ErrorMessage{{ " + e.getMessage() + "}}");
+ }
+
+ return response;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/common-lib/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/pom.xml b/ext/oidcclient/common-lib/pom.xml
new file mode 100644
index 0000000..a335452
--- /dev/null
+++ b/ext/oidcclient/common-lib/pom.xml
@@ -0,0 +1,56 @@
+<?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 Common Lib</name>
+ <description>Apache Syncope Ext: OIDC Client Common Lib</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-common-lib</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.common</groupId>
+ <artifactId>syncope-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/common-lib/src/main/java/org/apache/syncope/common/lib/OIDCConstants.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/OIDCConstants.java b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/OIDCConstants.java
new file mode 100644
index 0000000..12daa0a
--- /dev/null
+++ b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/OIDCConstants.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+public final class OIDCConstants {
+
+ public static final String CLIENT_ID = "client_id";
+
+ public static final String CLIENT_SECRET = "client_secret";
+
+ public static final String SCOPE = "scope";
+
+ public static final String RESPOSNSE_TYPE = "response_type";
+
+ public static final String REDIRECT_URI = "redirect_uri";
+
+ public static final String STATE = "state";
+
+ public static final String CODE = "code";
+
+ public static final String GRANT_TYPE = "grant_type";
+
+ public static final String OP = "op";
+
+ private OIDCConstants() {
+ // private constructor for static utility class
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginRequestTO.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginRequestTO.java b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginRequestTO.java
new file mode 100644
index 0000000..5d4dc31
--- /dev/null
+++ b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginRequestTO.java
@@ -0,0 +1,91 @@
+/*
+ * 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.to;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlRootElement(name = "oidcLoginRequest")
+@XmlType
+public class OIDCLoginRequestTO extends AbstractBaseBean {
+
+ private static final long serialVersionUID = -3509031322459942441L;
+
+ private String providerAddress;
+
+ private String clientId;
+
+ private String scope;
+
+ private String responseType;
+
+ private String redirectURI;
+
+ private String state;
+
+ public String getProviderAddress() {
+ return providerAddress;
+ }
+
+ public void setProviderAddress(final String providerAddress) {
+ this.providerAddress = providerAddress;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(final String clientId) {
+ this.clientId = clientId;
+ }
+
+ public String getScope() {
+ return scope;
+ }
+
+ public void setScope(final String scope) {
+ this.scope = scope;
+ }
+
+ public String getResponseType() {
+ return responseType;
+ }
+
+ public void setResponseType(final String responseType) {
+ this.responseType = responseType;
+ }
+
+ public String getRedirectURI() {
+ return redirectURI;
+ }
+
+ public void setRedirectURI(final String redirectURI) {
+ this.redirectURI = redirectURI;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(final String state) {
+ this.state = state;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginResponseTO.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginResponseTO.java b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginResponseTO.java
new file mode 100644
index 0000000..8e7798a
--- /dev/null
+++ b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCLoginResponseTO.java
@@ -0,0 +1,133 @@
+/*
+ * 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.to;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlRootElement(name = "oidcLoginResponse")
+@XmlType
+public class OIDCLoginResponseTO extends AbstractBaseBean {
+
+ private static final long serialVersionUID = -5971442076182154492L;
+
+ private String username;
+
+ private String email;
+
+ private String name;
+
+ private String subject;
+
+ private String givenName;
+
+ private String familyName;
+
+ private String accessToken;
+
+ private Date accessTokenExpiryTime;
+
+ private final Set<AttrTO> attrs = new HashSet<>();
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(final String username) {
+ this.username = username;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(final String email) {
+ this.email = email;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ public void setSubject(final String subject) {
+ this.subject = subject;
+ }
+
+ public String getGivenName() {
+ return givenName;
+ }
+
+ public void setGivenName(final String givenName) {
+ this.givenName = givenName;
+ }
+
+ public String getFamilyName() {
+ return familyName;
+ }
+
+ public void setFamilyName(final String familyName) {
+ this.familyName = familyName;
+ }
+
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ public void setAccessToken(final String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ public Date getAccessTokenExpiryTime() {
+ return accessTokenExpiryTime;
+ }
+
+ public void setAccessTokenExpiryTime(final Date accessTokenExpiryTime) {
+ this.accessTokenExpiryTime = accessTokenExpiryTime;
+ }
+
+ @JsonIgnore
+ public Optional<AttrTO> getAttr(final String schema) {
+ return attrs.stream().filter(attr -> attr.getSchema().equals(schema)).findFirst();
+ }
+
+ @XmlElementWrapper(name = "attrs")
+ @XmlElement(name = "attr")
+ @JsonProperty("attrs")
+ public Set<AttrTO> getAttrs() {
+ return attrs;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCProviderTO.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCProviderTO.java b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCProviderTO.java
new file mode 100644
index 0000000..eec4a83
--- /dev/null
+++ b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/to/OIDCProviderTO.java
@@ -0,0 +1,219 @@
+/*
+ * 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.to;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.PathParam;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+
+@XmlRootElement(name = "oidcprovider")
+@XmlType
+public class OIDCProviderTO extends AbstractBaseBean implements EntityTO, ItemContainerTO {
+
+ private static final long serialVersionUID = -1229802774546135794L;
+
+ private String key;
+
+ private String name;
+
+ private String clientID;
+
+ private String clientSecret;
+
+ private String authorizationEndpoint;
+
+ private String tokenEndpoint;
+
+ private String jwksUri;
+
+ private String issuer;
+
+ private String userinfoEndpoint;
+
+ private boolean hasDiscovery;
+
+ private UserTO userTemplate;
+
+ private boolean createUnmatching;
+
+ private boolean updateMatching;
+
+ private final List<ItemTO> items = new ArrayList<>();
+
+ private final Set<String> actionsClassNames = new HashSet<>();
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @PathParam("key")
+ @Override
+ public void setKey(final String key) {
+ this.key = key;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getClientID() {
+ return clientID;
+ }
+
+ public void setClientID(final String clientID) {
+ this.clientID = clientID;
+ }
+
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ public void setClientSecret(final String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ public String getAuthorizationEndpoint() {
+ return authorizationEndpoint;
+ }
+
+ public void setAuthorizationEndpoint(final String authorizationEndpoint) {
+ this.authorizationEndpoint = authorizationEndpoint;
+ }
+
+ public String getTokenEndpoint() {
+ return tokenEndpoint;
+ }
+
+ public void setTokenEndpoint(final String tokenEndpoint) {
+ this.tokenEndpoint = tokenEndpoint;
+ }
+
+ public String getJwksUri() {
+ return jwksUri;
+ }
+
+ public void setJwksUri(final String jwksUri) {
+ this.jwksUri = jwksUri;
+ }
+
+ public String getIssuer() {
+ return issuer;
+ }
+
+ public void setIssuer(final String issuer) {
+ this.issuer = issuer;
+ }
+
+ public String getUserinfoEndpoint() {
+ return userinfoEndpoint;
+ }
+
+ public void setUserinfoEndpoint(final String userinfoEndpoint) {
+ this.userinfoEndpoint = userinfoEndpoint;
+ }
+
+ public UserTO getUserTemplate() {
+ return userTemplate;
+ }
+
+ public boolean getHasDiscovery() {
+ return hasDiscovery;
+ }
+
+ public void setHasDiscovery(final boolean hasDiscovery) {
+ this.hasDiscovery = hasDiscovery;
+ }
+
+ public void setUserTemplate(final UserTO userTemplate) {
+ this.userTemplate = userTemplate;
+ }
+
+ public boolean isCreateUnmatching() {
+ return createUnmatching;
+ }
+
+ public void setCreateUnmatching(final boolean createUnmatching) {
+ this.createUnmatching = createUnmatching;
+ }
+
+ public boolean isUpdateMatching() {
+ return updateMatching;
+ }
+
+ public void setUpdateMatching(final boolean updateMatching) {
+ this.updateMatching = updateMatching;
+ }
+
+ @Override
+ public ItemTO getConnObjectKeyItem() {
+ return getItems().stream().filter(ItemTO::isConnObjectKey).findFirst().get();
+ }
+
+ protected boolean addConnObjectKeyItem(final ItemTO connObjectItem) {
+ connObjectItem.setMandatoryCondition("true");
+ connObjectItem.setConnObjectKey(true);
+
+ return this.add(connObjectItem);
+ }
+
+ @Override
+ public boolean setConnObjectKeyItem(final ItemTO connObjectKeyItem) {
+ return connObjectKeyItem == null
+ ? remove(getConnObjectKeyItem())
+ : addConnObjectKeyItem(connObjectKeyItem);
+ }
+
+ @XmlElementWrapper(name = "items")
+ @XmlElement(name = "item")
+ @JsonProperty("items")
+ @Override
+ public List<ItemTO> getItems() {
+ return items;
+ }
+
+ @Override
+ public boolean add(final ItemTO item) {
+ return item == null ? false : this.items.contains(item) || this.items.add(item);
+ }
+
+ public boolean remove(final ItemTO item) {
+ return this.items.remove(item);
+ }
+
+ @XmlElementWrapper(name = "actionsClassNames")
+ @XmlElement(name = "actionsClassName")
+ @JsonProperty("actionsClassNames")
+ public Set<String> getActionsClassNames() {
+ return actionsClassNames;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCClientEntitlement.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCClientEntitlement.java b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCClientEntitlement.java
new file mode 100644
index 0000000..98cf4d6
--- /dev/null
+++ b/ext/oidcclient/common-lib/src/main/java/org/apache/syncope/common/lib/types/OIDCClientEntitlement.java
@@ -0,0 +1,57 @@
+/*
+ * 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.types;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+public final class OIDCClientEntitlement {
+
+ public static final String OP_READ = "OP_READ";
+
+ public static final String OP_CREATE = "OP_CREATE";
+
+ public static final String OP_UPDATE = "OP_UPDATE";
+
+ public static final String OP_DELETE = "OP_DELETE";
+
+ private static final Set<String> VALUES;
+
+ static {
+ Set<String> values = new TreeSet<>();
+ for (Field field : OIDCClientEntitlement.class.getDeclaredFields()) {
+ if (Modifier.isStatic(field.getModifiers()) && String.class.equals(field.getType())) {
+ values.add(field.getName());
+ }
+ }
+ VALUES = Collections.unmodifiableSet(values);
+ }
+
+ public static Set<String> values() {
+ return VALUES;
+ }
+
+ private OIDCClientEntitlement() {
+ // private constructor for static utility class
+ }
+
+}
[5/8] syncope git commit: [SYNCOPE-1270] implementation for OpenID
Connect for Admin Console and Enduser - This closes #74
Posted by il...@apache.org.
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
[2/8] syncope git commit: [SYNCOPE-1270] implementation for OpenID
Connect for Admin Console and Enduser
Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/logic/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/pom.xml b/ext/oidcclient/logic/pom.xml
new file mode 100644
index 0000000..6daef24
--- /dev/null
+++ b/ext/oidcclient/logic/pom.xml
@@ -0,0 +1,76 @@
+<?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.0.9-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client Logic</name>
+ <description>Apache Syncope Ext: OIDC Client Logic</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-logic</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-logic</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-provisioning-java</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-rs-extension-providers</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-rs-security-sso-oidc</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ </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/f29e60f6/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCClientLogic.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCClientLogic.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCClientLogic.java
new file mode 100644
index 0000000..20decf9
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCClientLogic.java
@@ -0,0 +1,418 @@
+/*
+ * 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.logic;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.uuid.Generators;
+import com.fasterxml.uuid.impl.RandomBasedGenerator;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.provider.json.JsonMapObjectProvider;
+import org.apache.cxf.rs.security.jose.jaxrs.JsonWebKeysProvider;
+import org.apache.cxf.rs.security.oauth2.client.Consumer;
+import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
+import org.apache.cxf.rs.security.oidc.common.IdToken;
+import org.apache.cxf.rs.security.oidc.common.UserInfo;
+import org.apache.cxf.rs.security.oidc.rp.IdTokenReader;
+import org.apache.cxf.rs.security.oidc.rp.UserInfoClient;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.OIDCConstants;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.OIDCLoginRequestTO;
+import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.core.logic.model.TokenEndpointResponse;
+import org.apache.syncope.core.logic.oidc.OIDCUserManager;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.OIDCProviderDAO;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+import org.apache.syncope.core.persistence.api.entity.OIDCProviderItem;
+import org.apache.syncope.core.provisioning.api.data.AccessTokenDataBinder;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import org.apache.syncope.core.spring.security.AuthContextUtils;
+import org.apache.syncope.core.spring.security.AuthDataAccessor;
+import org.apache.syncope.core.spring.security.Encryptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class OIDCClientLogic extends AbstractTransactionalLogic<AbstractBaseBean> {
+
+ private static final Encryptor ENCRYPTOR = Encryptor.getInstance();
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private static final RandomBasedGenerator UUID_GENERATOR = Generators.randomBasedGenerator();
+
+ private static final String JWT_CLAIM_OP_ENTITYID = "OP_ENTITYID";
+
+ private static final String JWT_CLAIM_USERID = "USERID";
+
+ @Autowired
+ private AuthDataAccessor authDataAccessor;
+
+ @Autowired
+ private AccessTokenDataBinder accessTokenDataBinder;
+
+ @Autowired
+ private OIDCProviderDAO opDAO;
+
+ @Autowired
+ private OIDCUserManager userManager;
+
+ private OIDCProvider getOIDCProvider(final String opName) {
+ OIDCProvider op = null;
+ if (StringUtils.isBlank(opName)) {
+ List<OIDCProvider> ops = opDAO.findAll();
+ if (!ops.isEmpty()) {
+ op = ops.get(0);
+ }
+ } else {
+ op = opDAO.findByName(opName);
+ }
+ if (op == null) {
+ throw new NotFoundException(StringUtils.isBlank(opName)
+ ? "Any OIDC Provider"
+ : "OIDC Provider '" + opName + "'");
+ }
+ return op;
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.ANONYMOUS + "')")
+ public OIDCLoginRequestTO createLoginRequest(final String redirectURI, final String opName) {
+ // 1. look for Provider
+ OIDCProvider op = getOIDCProvider(opName);
+
+ // 2. create AuthnRequest
+ OIDCLoginRequestTO requestTO = new OIDCLoginRequestTO();
+ requestTO.setProviderAddress(op.getAuthorizationEndpoint());
+ requestTO.setClientId(op.getClientID());
+ requestTO.setScope("openid email profile");
+ requestTO.setResponseType("code");
+ requestTO.setRedirectURI(redirectURI);
+ requestTO.setState(UUID_GENERATOR.generate().toString());
+ return requestTO;
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.ANONYMOUS + "')")
+ public OIDCLoginResponseTO login(final String redirectURI, final String authorizationCode, final String opName) {
+ final OIDCProvider op = getOIDCProvider(opName);
+
+ // 1. get OpenID Connect tokens
+ String body = OIDCConstants.CODE + "=" + authorizationCode
+ + "&" + OIDCConstants.CLIENT_ID + "=" + op.getClientID()
+ + "&" + OIDCConstants.CLIENT_SECRET + "=" + op.getClientSecret()
+ + "&" + OIDCConstants.REDIRECT_URI + "=" + redirectURI
+ + "&" + OIDCConstants.GRANT_TYPE + "=authorization_code";
+ TokenEndpointResponse tokenEndpointResponse = getOIDCTokens(op.getTokenEndpoint(), body);
+
+ // 1. get OpenID Connect tokens
+ Consumer consumer = new Consumer(op.getClientID(), op.getClientSecret());
+
+ // 2. validate token
+ IdToken idToken = getValidatedIdToken(op, consumer, tokenEndpointResponse.getIdToken());
+
+ // 3. extract user information
+ UserInfo userInfo = getUserInfo(op, tokenEndpointResponse.getAccessToken(), idToken, consumer);
+
+ // 4. prepare the result: find matching user (if any) and return the received attributes
+ final OIDCLoginResponseTO responseTO = new OIDCLoginResponseTO();
+ responseTO.setEmail(userInfo.getEmail());
+ responseTO.setFamilyName(userInfo.getFamilyName());
+ responseTO.setGivenName(userInfo.getGivenName());
+ responseTO.setName(userInfo.getName());
+ responseTO.setSubject(userInfo.getSubject());
+
+ String keyValue = null;
+ for (OIDCProviderItem item : op.getItems()) {
+ AttrTO attrTO = new AttrTO();
+ attrTO.setSchema(item.getExtAttrName());
+ switch (item.getExtAttrName()) {
+ case UserInfo.PREFERRED_USERNAME_CLAIM:
+ attrTO.getValues().add(userInfo.getPreferredUserName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getPreferredUserName();
+ }
+ break;
+
+ case UserInfo.PROFILE_CLAIM:
+ attrTO.getValues().add(userInfo.getProfile());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getProfile();
+ }
+ break;
+
+ case UserInfo.EMAIL_CLAIM:
+ attrTO.getValues().add(userInfo.getEmail());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getEmail();
+ }
+ break;
+
+ case UserInfo.NAME_CLAIM:
+ attrTO.getValues().add(userInfo.getName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getName();
+ }
+ break;
+
+ case UserInfo.FAMILY_NAME_CLAIM:
+ attrTO.getValues().add(userInfo.getFamilyName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getFamilyName();
+ }
+ break;
+
+ case UserInfo.MIDDLE_NAME_CLAIM:
+ attrTO.getValues().add(userInfo.getMiddleName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getMiddleName();
+ }
+ break;
+
+ case UserInfo.GIVEN_NAME_CLAIM:
+ attrTO.getValues().add(userInfo.getGivenName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getGivenName();
+ }
+ break;
+
+ case UserInfo.NICKNAME_CLAIM:
+ attrTO.getValues().add(userInfo.getNickName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getNickName();
+ }
+ break;
+
+ case UserInfo.GENDER_CLAIM:
+ attrTO.getValues().add(userInfo.getGender());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getGender();
+ }
+ break;
+
+ case UserInfo.LOCALE_CLAIM:
+ attrTO.getValues().add(userInfo.getLocale());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getLocale();
+ }
+ break;
+
+ case UserInfo.ZONEINFO_CLAIM:
+ attrTO.getValues().add(userInfo.getZoneInfo());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getZoneInfo();
+ }
+ break;
+
+ case UserInfo.BIRTHDATE_CLAIM:
+ attrTO.getValues().add(userInfo.getBirthDate());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getBirthDate();
+ }
+ break;
+
+ case UserInfo.PHONE_CLAIM:
+ attrTO.getValues().add(userInfo.getPhoneNumber());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getPhoneNumber();
+ }
+ break;
+
+ case UserInfo.ADDRESS_CLAIM:
+ attrTO.getValues().add(userInfo.getUserAddress().getFormatted());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getUserAddress().getFormatted();
+ }
+ break;
+
+ case UserInfo.UPDATED_AT_CLAIM:
+ attrTO.getValues().add(Long.toString(userInfo.getUpdatedAt()));
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = Long.toString(userInfo.getUpdatedAt());
+ }
+ break;
+
+ default:
+ LOG.warn("Unsupported: {} ", item.getExtAttrName());
+ }
+ }
+
+ final List<String> matchingUsers = keyValue == null
+ ? Collections.<String>emptyList()
+ : userManager.findMatchingUser(keyValue, op.getConnObjectKeyItem());
+ LOG.debug("Found {} matching users for {}", matchingUsers.size(), keyValue);
+
+ String username;
+ if (matchingUsers.isEmpty()) {
+ if (op.isCreateUnmatching()) {
+ LOG.debug("No user matching {}, about to create", keyValue);
+
+ final String emailValue = userInfo.getEmail();
+ username = AuthContextUtils.execWithAuthContext(
+ AuthContextUtils.getDomain(), new AuthContextUtils.Executable<String>() {
+
+ @Override
+ public String exec() {
+ return userManager.create(op, responseTO, emailValue);
+ }
+ });
+ } else {
+ throw new NotFoundException("User matching the provided value " + keyValue);
+ }
+ } else if (matchingUsers.size() > 1) {
+ throw new IllegalArgumentException("Several users match the provided value " + keyValue);
+ } else {
+ if (op.isUpdateMatching()) {
+ LOG.debug("About to update {} for {}", matchingUsers.get(0), keyValue);
+
+ username = AuthContextUtils.execWithAuthContext(
+ AuthContextUtils.getDomain(), new AuthContextUtils.Executable<String>() {
+
+ @Override
+ public String exec() {
+ return userManager.update(matchingUsers.get(0), op, responseTO);
+ }
+ });
+ } else {
+ username = matchingUsers.get(0);
+ }
+
+ }
+
+ responseTO.setUsername(username);
+
+ // 5. generate JWT for further access
+ Map<String, Object> claims = new HashMap<>();
+ claims.put(JWT_CLAIM_OP_ENTITYID, idToken.getIssuer());
+ claims.put(JWT_CLAIM_USERID, idToken.getSubject());
+
+ byte[] authorities = null;
+ try {
+ authorities = ENCRYPTOR.encode(POJOHelper.serialize(
+ authDataAccessor.getAuthorities(responseTO.getUsername())), CipherAlgorithm.AES).
+ getBytes();
+ } catch (Exception e) {
+ LOG.error("Could not fetch authorities", e);
+ }
+
+ Pair<String, Date> accessTokenInfo =
+ accessTokenDataBinder.create(responseTO.getUsername(), claims, authorities, true);
+ responseTO.setAccessToken(accessTokenInfo.getLeft());
+ responseTO.setAccessTokenExpiryTime(accessTokenInfo.getRight());
+
+ return responseTO;
+ }
+
+ private TokenEndpointResponse getOIDCTokens(final String url, final String body) {
+ String oidcTokens = WebClient.create(url).
+ type(MediaType.APPLICATION_FORM_URLENCODED).accept(MediaType.APPLICATION_JSON).
+ post(body).
+ readEntity(String.class);
+ TokenEndpointResponse endpointResponse = null;
+ try {
+ endpointResponse = MAPPER.readValue(oidcTokens, TokenEndpointResponse.class);
+ } catch (Exception e) {
+ LOG.error("While getting the Tokens from the OP", e);
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+ return endpointResponse;
+ }
+
+ private IdToken getValidatedIdToken(final OIDCProvider op, final Consumer consumer, final String jwtIdToken) {
+ IdTokenReader idTokenReader = new IdTokenReader();
+ idTokenReader.setClockOffset(10);
+ idTokenReader.setIssuerId(op.getIssuer());
+ WebClient jwkSetClient = WebClient.create(
+ op.getJwksUri(), Arrays.asList(new JsonWebKeysProvider())).
+ accept(MediaType.APPLICATION_JSON);
+ idTokenReader.setJwkSetClient(jwkSetClient);
+ IdToken idToken = null;
+ try {
+ idToken = idTokenReader.getIdToken(jwtIdToken, consumer);
+ } catch (Exception e) {
+ LOG.error("While validating the id_token", e);
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+ return idToken;
+ }
+
+ private UserInfo getUserInfo(
+ final OIDCProvider op,
+ final String accessToken,
+ final IdToken idToken,
+ final Consumer consumer) {
+
+ WebClient userInfoServiceClient = WebClient.create(
+ op.getUserinfoEndpoint(), Arrays.asList(new JsonMapObjectProvider())).
+ accept(MediaType.APPLICATION_JSON);
+ ClientAccessToken clientAccessToken = new ClientAccessToken("Bearer", accessToken);
+ UserInfoClient userInfoClient = new UserInfoClient();
+ userInfoClient.setUserInfoServiceClient(userInfoServiceClient);
+ UserInfo userInfo = null;
+ try {
+ userInfo = userInfoClient.getUserInfo(clientAccessToken, idToken, consumer);
+ } catch (Exception e) {
+ LOG.error("While getting the userInfo", e);
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+ return userInfo;
+ }
+
+ @Override
+ protected AbstractBaseBean resolveReference(
+ final Method method, final Object... args) throws UnresolvedReferenceException {
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCProviderLogic.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCProviderLogic.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCProviderLogic.java
new file mode 100644
index 0000000..17873f3
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCProviderLogic.java
@@ -0,0 +1,177 @@
+/*
+ * 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.logic;
+
+import static org.apache.syncope.core.logic.AbstractLogic.LOG;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ItemTO;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.OIDCClientEntitlement;
+import org.apache.syncope.core.logic.init.OIDCClientClassPathScanImplementationLookup;
+import org.apache.syncope.core.logic.model.OIDCProviderDiscoveryDocument;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.OIDCProviderDAO;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+import org.apache.syncope.core.provisioning.api.data.OIDCProviderDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+public class OIDCProviderLogic extends AbstractTransactionalLogic<OIDCProviderTO> {
+
+ @Autowired
+ private OIDCProviderDAO opDAO;
+
+ @Autowired
+ private OIDCProviderDataBinder binder;
+
+ @Autowired
+ private OIDCClientClassPathScanImplementationLookup implLookup;
+
+ @PreAuthorize("isAuthenticated()")
+ public Set<String> getActionsClasses() {
+ return implLookup.getActionsClasses();
+ }
+
+ private OIDCProviderDiscoveryDocument getDiscoveryDocument(final String issuer) {
+ WebClient client = WebClient.create(
+ issuer + "/.well-known/openid-configuration", Arrays.asList(new JacksonJsonProvider())).
+ accept(MediaType.APPLICATION_JSON);
+ return client.get(OIDCProviderDiscoveryDocument.class);
+ }
+
+ @PreAuthorize("hasRole('" + OIDCClientEntitlement.OP_CREATE + "')")
+ public String createFromDiscovery(final OIDCProviderTO opTO) {
+ OIDCProviderDiscoveryDocument discoveryDocument = getDiscoveryDocument(opTO.getIssuer());
+
+ opTO.setAuthorizationEndpoint(discoveryDocument.getAuthorizationEndpoint());
+ opTO.setIssuer(discoveryDocument.getIssuer());
+ opTO.setJwksUri(discoveryDocument.getJwksUri());
+ opTO.setTokenEndpoint(discoveryDocument.getTokenEndpoint());
+ opTO.setUserinfoEndpoint(discoveryDocument.getUserinfoEndpoint());
+
+ return create(opTO);
+ }
+
+ @PreAuthorize("hasRole('" + OIDCClientEntitlement.OP_CREATE + "')")
+ public String create(final OIDCProviderTO opTO) {
+ if (opTO.getConnObjectKeyItem() == null) {
+ ItemTO connObjectKeyItem = new ItemTO();
+ connObjectKeyItem.setIntAttrName("username");
+ connObjectKeyItem.setExtAttrName("email");
+ opTO.setConnObjectKeyItem(connObjectKeyItem);
+ }
+
+ OIDCProvider provider = opDAO.save(binder.create(opTO));
+
+ return provider.getKey();
+ }
+
+ @PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true)
+ public List<OIDCProviderTO> list() {
+ return CollectionUtils.collect(opDAO.findAll(), new Transformer<OIDCProvider, OIDCProviderTO>() {
+
+ @Override
+ public OIDCProviderTO transform(final OIDCProvider input) {
+ return binder.getOIDCProviderTO(input);
+ }
+ }, new ArrayList<OIDCProviderTO>());
+ }
+
+ @PreAuthorize("hasRole('" + OIDCClientEntitlement.OP_READ + "')")
+ @Transactional(readOnly = true)
+ public OIDCProviderTO read(final String key) {
+ OIDCProvider op = opDAO.find(key);
+ if (op == null) {
+ throw new NotFoundException("OIDC Provider '" + key + "'");
+ }
+ return binder.getOIDCProviderTO(op);
+ }
+
+ @PreAuthorize("hasRole('" + OIDCClientEntitlement.OP_UPDATE + "')")
+ public void update(final OIDCProviderTO oidcProviderTO) {
+ OIDCProvider oidcProvider = opDAO.find(oidcProviderTO.getKey());
+ if (oidcProvider == null) {
+ throw new NotFoundException("OIDC Provider '" + oidcProviderTO.getKey() + "'");
+ }
+
+ if (!oidcProvider.getIssuer().equals(oidcProviderTO.getIssuer())) {
+ LOG.error("Issuers do not match: expected {}, found {}",
+ oidcProvider.getIssuer(), oidcProviderTO.getIssuer());
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidEntity);
+ sce.getElements().add("Issuers do not match");
+ throw sce;
+ }
+
+ opDAO.save(binder.update(oidcProvider, oidcProviderTO));
+ }
+
+ @PreAuthorize("hasRole('" + OIDCClientEntitlement.OP_DELETE + "')")
+ public void delete(final String key) {
+ OIDCProvider op = opDAO.find(key);
+ if (op == null) {
+ throw new NotFoundException("OIDC Provider '" + key + "'");
+ }
+ opDAO.delete(key);
+ }
+
+ @Override
+ protected OIDCProviderTO resolveReference(
+ final Method method, final Object... args) throws UnresolvedReferenceException {
+
+ String key = null;
+
+ if (ArrayUtils.isNotEmpty(args)) {
+ for (int i = 0; key == null && i < args.length; i++) {
+ if (args[i] instanceof String) {
+ key = (String) args[i];
+ } else if (args[i] instanceof OIDCProviderTO) {
+ key = ((OIDCProviderTO) args[i]).getKey();
+ }
+ }
+ }
+
+ if (key != null) {
+ try {
+ return binder.getOIDCProviderTO(opDAO.find(key));
+ } catch (Throwable ignore) {
+ LOG.debug("Unresolved reference", ignore);
+ throw new UnresolvedReferenceException(ignore);
+ }
+ }
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientClassPathScanImplementationLookup.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientClassPathScanImplementationLookup.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientClassPathScanImplementationLookup.java
new file mode 100644
index 0000000..82d6d8a
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientClassPathScanImplementationLookup.java
@@ -0,0 +1,78 @@
+/*
+ * 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.logic.init;
+
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.syncope.core.persistence.api.ImplementationLookup;
+import org.apache.syncope.core.persistence.api.SyncopeLoader;
+import org.apache.syncope.core.provisioning.api.OIDCProviderActions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
+import org.springframework.core.type.filter.AssignableTypeFilter;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ClassUtils;
+
+@Component
+public class OIDCClientClassPathScanImplementationLookup implements SyncopeLoader {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ImplementationLookup.class);
+
+ private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope.core";
+
+ private Set<String> actionsClasses;
+
+ @Override
+ public Integer getPriority() {
+ return Integer.MIN_VALUE;
+ }
+
+ @Override
+ public void load() {
+ actionsClasses = new HashSet<>();
+
+ ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
+ scanner.addIncludeFilter(new AssignableTypeFilter(OIDCProviderActions.class));
+
+ for (BeanDefinition bd : scanner.findCandidateComponents(DEFAULT_BASE_PACKAGE)) {
+ try {
+ Class<?> clazz = ClassUtils.resolveClassName(
+ bd.getBeanClassName(), ClassUtils.getDefaultClassLoader());
+ boolean isAbstractClazz = Modifier.isAbstract(clazz.getModifiers());
+
+ if (OIDCProviderActions.class.isAssignableFrom(clazz) && !isAbstractClazz) {
+ actionsClasses.add(clazz.getName());
+ }
+ } catch (Throwable t) {
+ LOG.warn("Could not inspect class {}", bd.getBeanClassName(), t);
+ }
+ }
+
+ actionsClasses = Collections.unmodifiableSet(actionsClasses);
+ }
+
+ public Set<String> getActionsClasses() {
+ return actionsClasses;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
new file mode 100644
index 0000000..f24eb79
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
@@ -0,0 +1,55 @@
+/*
+ * 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.logic.init;
+
+import org.apache.syncope.common.lib.types.OIDCClientEntitlement;
+import org.apache.syncope.core.persistence.api.DomainsHolder;
+import org.apache.syncope.core.persistence.api.SyncopeLoader;
+import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
+import org.apache.syncope.core.spring.security.AuthContextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class OIDCClientLoader implements SyncopeLoader {
+
+ @Autowired
+ private DomainsHolder domainsHolder;
+
+ @Override
+ public Integer getPriority() {
+ return 1000;
+ }
+
+ @Override
+ public void load() {
+ EntitlementsHolder.getInstance().init(OIDCClientEntitlement.values());
+
+ for (String domain : domainsHolder.getDomains().keySet()) {
+ AuthContextUtils.execWithAuthContext(domain, new AuthContextUtils.Executable<Void>() {
+
+ @Override
+ public Void exec() {
+ return null;
+ }
+ });
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/OIDCProviderDiscoveryDocument.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/OIDCProviderDiscoveryDocument.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/OIDCProviderDiscoveryDocument.java
new file mode 100644
index 0000000..aae3f0c
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/OIDCProviderDiscoveryDocument.java
@@ -0,0 +1,128 @@
+/*
+ * 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.logic.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonPropertyOrder({
+ "issuer",
+ "authorization_endpoint",
+ "token_endpoint",
+ "userinfo_endpoint",
+ "end_session_endpoint",
+ "jwks_uri",
+ "registration_endpoint"
+})
+public class OIDCProviderDiscoveryDocument {
+
+ @JsonProperty("issuer")
+ private String issuer;
+
+ @JsonProperty("authorization_endpoint")
+ private String authorizationEndpoint;
+
+ @JsonProperty("token_endpoint")
+ private String tokenEndpoint;
+
+ @JsonProperty("userinfo_endpoint")
+ private String userinfoEndpoint;
+
+ @JsonProperty("end_session_endpoint")
+ private String endSessionEndpoint;
+
+ @JsonProperty("jwks_uri")
+ private String jwksUri;
+
+ @JsonProperty("registration_endpoint")
+ private String registrationEndpoint;
+
+ @JsonProperty("issuer")
+ public String getIssuer() {
+ return issuer;
+ }
+
+ @JsonProperty("issuer")
+ public void setIssuer(final String issuer) {
+ this.issuer = issuer;
+ }
+
+ @JsonProperty("authorization_endpoint")
+ public String getAuthorizationEndpoint() {
+ return authorizationEndpoint;
+ }
+
+ @JsonProperty("authorization_endpoint")
+ public void setAuthorizationEndpoint(final String authorizationEndpoint) {
+ this.authorizationEndpoint = authorizationEndpoint;
+ }
+
+ @JsonProperty("token_endpoint")
+ public String getTokenEndpoint() {
+ return tokenEndpoint;
+ }
+
+ @JsonProperty("token_endpoint")
+ public void setTokenEndpoint(final String tokenEndpoint) {
+ this.tokenEndpoint = tokenEndpoint;
+ }
+
+ @JsonProperty("userinfo_endpoint")
+ public String getUserinfoEndpoint() {
+ return userinfoEndpoint;
+ }
+
+ @JsonProperty("userinfo_endpoint")
+ public void setUserinfoEndpoint(final String userinfoEndpoint) {
+ this.userinfoEndpoint = userinfoEndpoint;
+ }
+
+ @JsonProperty("end_session_endpoint")
+ public String getEndSessionEndpoint() {
+ return endSessionEndpoint;
+ }
+
+ @JsonProperty("end_session_endpoint")
+ public void setEndSessionEndpoint(final String endSessionEndpoint) {
+ this.endSessionEndpoint = endSessionEndpoint;
+ }
+
+ @JsonProperty("jwks_uri")
+ public String getJwksUri() {
+ return jwksUri;
+ }
+
+ @JsonProperty("jwks_uri")
+ public void setJwksUri(final String jwksUri) {
+ this.jwksUri = jwksUri;
+ }
+
+ @JsonProperty("registration_endpoint")
+ public String getRegistrationEndpoint() {
+ return registrationEndpoint;
+ }
+
+ @JsonProperty("registration_endpoint")
+ public void setRegistrationEndpoint(final String registrationEndpoint) {
+ this.registrationEndpoint = registrationEndpoint;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/TokenEndpointResponse.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/TokenEndpointResponse.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/TokenEndpointResponse.java
new file mode 100644
index 0000000..7908b88
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/TokenEndpointResponse.java
@@ -0,0 +1,86 @@
+/*
+ * 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.logic.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonPropertyOrder({
+ "access_token",
+ "id_token",
+ "expires_in",
+ "token_type"
+})
+public class TokenEndpointResponse {
+
+ @JsonProperty("access_token")
+ private String accessToken;
+
+ @JsonProperty("id_token")
+ private String idToken;
+
+ @JsonProperty("expires_in")
+ private int expiresIn;
+
+ @JsonProperty("token_type")
+ private String tokenType;
+
+ @JsonProperty("access_token")
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ @JsonProperty("access_token")
+ public void setAccessToken(final String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ @JsonProperty("id_token")
+ public String getIdToken() {
+ return idToken;
+ }
+
+ @JsonProperty("id_token")
+ public void setIdToken(final String idToken) {
+ this.idToken = idToken;
+ }
+
+ @JsonProperty("expires_in")
+ public int getExpiresIn() {
+ return expiresIn;
+ }
+
+ @JsonProperty("expires_in")
+ public void setExpiresIn(final int expiresIn) {
+ this.expiresIn = expiresIn;
+ }
+
+ @JsonProperty("token_type")
+ public String getTokenType() {
+ return tokenType;
+ }
+
+ @JsonProperty("token_type")
+ public void setTokenType(final String tokenType) {
+ this.tokenType = tokenType;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java
new file mode 100644
index 0000000..60a2fd8
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java
@@ -0,0 +1,306 @@
+/*
+ * 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.logic.oidc;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.AnyOperations;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.patch.UserPatch;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
+import org.apache.syncope.common.lib.to.PropagationStatus;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+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.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
+import org.apache.syncope.core.provisioning.api.OIDCProviderActions;
+import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
+import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
+import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
+import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
+import org.apache.syncope.core.provisioning.java.utils.TemplateUtils;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+public class OIDCUserManager {
+
+ private static final Logger LOG = LoggerFactory.getLogger(OIDCUserManager.class);
+
+ @Autowired
+ private UserDAO userDAO;
+
+ @Autowired
+ private PlainSchemaDAO plainSchemaDAO;
+
+ @Autowired
+ private IntAttrNameParser intAttrNameParser;
+
+ @Autowired
+ private EntityFactory entityFactory;
+
+ @Autowired
+ private TemplateUtils templateUtils;
+
+ @Autowired
+ private UserProvisioningManager provisioningManager;
+
+ @Autowired
+ private UserDataBinder binder;
+
+ @Transactional(readOnly = true)
+ public List<String> findMatchingUser(final String keyValue, final OIDCProviderItem connObjectKeyItem) {
+ List<String> result = new ArrayList<>();
+
+ String transformed = keyValue;
+ for (ItemTransformer transformer : MappingUtils.getItemTransformers(connObjectKeyItem)) {
+ List<Object> output = transformer.beforePull(
+ null,
+ null,
+ Collections.<Object>singletonList(transformed));
+ if (output != null && !output.isEmpty()) {
+ transformed = output.get(0).toString();
+ }
+ }
+
+ IntAttrName intAttrName;
+ try {
+ intAttrName = intAttrNameParser.parse(connObjectKeyItem.getIntAttrName(), AnyTypeKind.USER);
+ } catch (ParseException e) {
+ LOG.error("Invalid intAttrName '{}' specified, ignoring", connObjectKeyItem.getIntAttrName(), e);
+ return result;
+ }
+
+ if (intAttrName.getField() != null) {
+ switch (intAttrName.getField()) {
+ case "key":
+ User byKey = userDAO.find(transformed);
+ if (byKey != null) {
+ result.add(byKey.getUsername());
+ }
+ break;
+
+ case "username":
+ User byUsername = userDAO.findByUsername(transformed);
+ if (byUsername != null) {
+ result.add(byUsername.getUsername());
+ }
+ break;
+
+ default:
+ }
+ } else if (intAttrName.getSchemaType() != null) {
+ switch (intAttrName.getSchemaType()) {
+ case PLAIN:
+ PlainAttrValue value = entityFactory.newEntity(UPlainAttrValue.class);
+
+ PlainSchema schema = plainSchemaDAO.find(intAttrName.getSchemaName());
+ if (schema == null) {
+ value.setStringValue(transformed);
+ } else {
+ try {
+ value.parseValue(schema, transformed);
+ } catch (ParsingValidationException e) {
+ LOG.error("While parsing provided key value {}", transformed, e);
+ value.setStringValue(transformed);
+ }
+ }
+
+ CollectionUtils.collect(
+ userDAO.findByPlainAttrValue(intAttrName.getSchemaName(), value),
+ new Transformer<User, String>() {
+
+ @Override
+ public String transform(final User input) {
+ return input.getUsername();
+ }
+ }, result);
+ break;
+
+ case DERIVED:
+ CollectionUtils.collect(
+ userDAO.findByDerAttrValue(intAttrName.getSchemaName(), transformed),
+ new Transformer<User, String>() {
+
+ @Override
+ public String transform(final User input) {
+ return input.getUsername();
+ }
+ }, result);
+ break;
+
+ default:
+ }
+ }
+
+ return result;
+ }
+
+ private List<OIDCProviderActions> getActions(final OIDCProvider op) {
+ List<OIDCProviderActions> actions = new ArrayList<>();
+
+ for (String className : op.getActionsClassNames()) {
+ try {
+ Class<?> actionsClass = Class.forName(className);
+ OIDCProviderActions opActions = (OIDCProviderActions) ApplicationContextProvider.getBeanFactory().
+ createBean(actionsClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
+
+ actions.add(opActions);
+ } catch (Exception e) {
+ LOG.warn("Class '{}' not found", className, e);
+ }
+ }
+
+ return actions;
+ }
+
+ public void fill(final OIDCProvider op, final OIDCLoginResponseTO responseTO, final UserTO userTO) {
+ for (OIDCProviderItem item : op.getItems()) {
+ List<String> values = Collections.emptyList();
+ AttrTO oidcAttr = responseTO.getAttr(item.getExtAttrName());
+ if (oidcAttr != null && !oidcAttr.getValues().isEmpty()) {
+ values = oidcAttr.getValues();
+
+ List<Object> transformed = new ArrayList<Object>(values);
+ for (ItemTransformer transformer : MappingUtils.getItemTransformers(item)) {
+ transformed = transformer.beforePull(null, userTO, transformed);
+ }
+ values.clear();
+ for (Object value : transformed) {
+ values.add(value.toString());
+ }
+ }
+
+ IntAttrName intAttrName = null;
+ try {
+ intAttrName = intAttrNameParser.parse(item.getIntAttrName(), AnyTypeKind.USER);
+ } catch (ParseException e) {
+ LOG.error("Invalid intAttrName '{}' specified, ignoring", item.getIntAttrName(), e);
+ }
+
+ if (intAttrName != null && intAttrName.getField() != null) {
+ switch (intAttrName.getField()) {
+ case "username":
+ if (!values.isEmpty()) {
+ userTO.setUsername(values.get(0));
+ }
+ break;
+
+ default:
+ LOG.warn("Unsupported: {}", intAttrName.getField());
+ }
+ } else if (intAttrName != null && intAttrName.getSchemaType() != null) {
+ switch (intAttrName.getSchemaType()) {
+ case PLAIN:
+ AttrTO attr = userTO.getPlainAttr(intAttrName.getSchemaName());
+ if (attr == null) {
+ attr = new AttrTO.Builder().schema(intAttrName.getSchemaName()).build();
+ userTO.getPlainAttrs().add(attr);
+ }
+ attr.getValues().clear();
+ attr.getValues().addAll(values);
+ break;
+
+ default:
+ LOG.warn("Unsupported: {} {}", intAttrName.getSchemaType(), intAttrName.getSchemaName());
+ }
+ }
+ }
+ }
+
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public String create(final OIDCProvider op, final OIDCLoginResponseTO responseTO, final String email) {
+ UserTO userTO = new UserTO();
+
+ if (op.getUserTemplate() != null) {
+ templateUtils.apply(userTO, op.getUserTemplate());
+ }
+
+ List<OIDCProviderActions> actions = getActions(op);
+ for (OIDCProviderActions action : actions) {
+ userTO = action.beforeCreate(userTO, responseTO);
+ }
+
+ fill(op, responseTO, userTO);
+
+ if (userTO.getRealm() == null) {
+ userTO.setRealm(SyncopeConstants.ROOT_REALM);
+ }
+ if (userTO.getUsername() == null) {
+ userTO.setUsername(email);
+ }
+
+ Pair<String, List<PropagationStatus>> created = provisioningManager.create(userTO, false, false);
+ userTO = binder.getUserTO(created.getKey());
+
+ for (OIDCProviderActions action : actions) {
+ userTO = action.afterCreate(userTO, responseTO);
+ }
+
+ return userTO.getUsername();
+ }
+
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public String update(final String username, final OIDCProvider op, final OIDCLoginResponseTO responseTO) {
+ UserTO userTO = binder.getUserTO(userDAO.findKey(username));
+ UserTO original = SerializationUtils.clone(userTO);
+
+ fill(op, responseTO, userTO);
+
+ UserPatch userPatch = AnyOperations.diff(userTO, original, true);
+
+ List<OIDCProviderActions> actions = getActions(op);
+ for (OIDCProviderActions action : actions) {
+ userPatch = action.beforeUpdate(userPatch, responseTO);
+ }
+
+ Pair<UserPatch, List<PropagationStatus>> updated = provisioningManager.update(userPatch, false);
+ userTO = binder.getUserTO(updated.getLeft().getKey());
+
+ for (OIDCProviderActions action : actions) {
+ userTO = action.afterUpdate(userTO, responseTO);
+ }
+
+ return userTO.getUsername();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/persistence-api/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/pom.xml b/ext/oidcclient/persistence-api/pom.xml
new file mode 100644
index 0000000..c4b80e1
--- /dev/null
+++ b/ext/oidcclient/persistence-api/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.0.9-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client Persistence API</name>
+ <description>Apache Syncope Ext: OIDC Client Persistence API</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-persistence-api</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-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/f29e60f6/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/OIDCProviderDAO.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/OIDCProviderDAO.java b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/OIDCProviderDAO.java
new file mode 100644
index 0000000..793e461
--- /dev/null
+++ b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/OIDCProviderDAO.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.persistence.api.dao;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+
+public interface OIDCProviderDAO {
+
+ OIDCProvider find(String key);
+
+ OIDCProvider findByName(String name);
+
+ List<OIDCProvider> findAll();
+
+ OIDCProvider save(final OIDCProvider op);
+
+ void delete(String key);
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCEntityFactory.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCEntityFactory.java b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCEntityFactory.java
new file mode 100644
index 0000000..489ce86
--- /dev/null
+++ b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCEntityFactory.java
@@ -0,0 +1,25 @@
+/*
+ * 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.api.entity;
+
+public interface OIDCEntityFactory {
+
+ <E extends Entity> E newEntity(Class<E> reference);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProvider.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProvider.java b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProvider.java
new file mode 100644
index 0000000..cf30781
--- /dev/null
+++ b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProvider.java
@@ -0,0 +1,84 @@
+/*
+ * 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.api.entity;
+
+import java.util.List;
+import java.util.Set;
+
+public interface OIDCProvider extends Entity {
+
+ String getName();
+
+ void setName(String entityID);
+
+ String getClientID();
+
+ void setClientID(String clientId);
+
+ String getClientSecret();
+
+ void setClientSecret(String clientSecret);
+
+ String getAuthorizationEndpoint();
+
+ void setAuthorizationEndpoint(String authorizationEndpoint);
+
+ String getTokenEndpoint();
+
+ void setTokenEndpoint(String tokenEndpoint);
+
+ String getJwksUri();
+
+ void setJwksUri(String jwsUri);
+
+ String getIssuer();
+
+ void setIssuer(String issuer);
+
+ String getUserinfoEndpoint();
+
+ void setUserinfoEndpoint(String userinfoEndpoint);
+
+ boolean getHasDiscovery();
+
+ void setHasDiscovery(boolean hasDiscovery);
+
+ boolean isCreateUnmatching();
+
+ void setCreateUnmatching(boolean createUnmatching);
+
+ boolean isUpdateMatching();
+
+ void setUpdateMatching(boolean updateMatching);
+
+ OIDCUserTemplate getUserTemplate();
+
+ void setUserTemplate(OIDCUserTemplate userTemplate);
+
+ List<? extends OIDCProviderItem> getItems();
+
+ OIDCProviderItem getConnObjectKeyItem();
+
+ void setConnObjectKeyItem(OIDCProviderItem item);
+
+ boolean add(OIDCProviderItem item);
+
+ Set<String> getActionsClassNames();
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProviderItem.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProviderItem.java b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProviderItem.java
new file mode 100644
index 0000000..3047c88
--- /dev/null
+++ b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProviderItem.java
@@ -0,0 +1,29 @@
+/*
+ * 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.api.entity;
+
+import org.apache.syncope.core.persistence.api.entity.resource.Item;
+
+public interface OIDCProviderItem extends Item {
+
+ OIDCProvider getOP();
+
+ void setOP(OIDCProvider op);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCUserTemplate.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCUserTemplate.java b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCUserTemplate.java
new file mode 100644
index 0000000..339f6ec
--- /dev/null
+++ b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCUserTemplate.java
@@ -0,0 +1,27 @@
+/*
+ * 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.api.entity;
+
+public interface OIDCUserTemplate extends AnyTemplate {
+
+ OIDCProvider getOP();
+
+ void setOP(OIDCProvider op);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/persistence-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-jpa/pom.xml b/ext/oidcclient/persistence-jpa/pom.xml
new file mode 100644
index 0000000..ac404cf
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/pom.xml
@@ -0,0 +1,134 @@
+<?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.0.9-SNAPSHOT</version>
+ </parent>
+
+ <name>Apache Syncope Ext: OIDC Client Persistence JPA</name>
+ <description>Apache Syncope Ext: OIDC Client Persistence JPA</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-persistence-jpa</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-persistence-jpa</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>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa-maven-plugin</artifactId>
+ <inherited>true</inherited>
+ <dependencies>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <version>${h2.version}</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <persistenceXmlFile>${rootpom.basedir}/core/persistence-jpa/src/main/resources/persistence-enhance.xml</persistenceXmlFile>
+ <includes>org/apache/syncope/core/persistence/jpa/entity/**/*.class</includes>
+ <connectionDriverName>org.springframework.jdbc.datasource.DriverManagerDataSource</connectionDriverName>
+ <connectionProperties>
+ driverClassName=org.h2.Driver,
+ url=jdbc:h2:mem:syncopedb
+ username=sa,
+ password=
+ </connectionProperties>
+ </configuration>
+ <executions>
+ <execution>
+ <id>enhancer</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>enhance</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+
+ <testResources>
+ <testResource>
+ <directory>${rootpom.basedir}/core/persistence-jpa/src/main/resources</directory>
+ <filtering>true</filtering>
+ </testResource>
+ </testResources>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>sqlgen</id>
+
+ <properties>
+ <skipTests>true</skipTests>
+ </properties>
+
+ <build>
+ <defaultGoal>clean verify</defaultGoal>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa-maven-plugin</artifactId>
+ <inherited>true</inherited>
+ <executions>
+ <execution>
+ <id>sqlgenr</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>sql</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ </profile>
+ </profiles>
+
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAOIDCProviderDAO.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAOIDCProviderDAO.java b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAOIDCProviderDAO.java
new file mode 100644
index 0000000..91e3af0
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAOIDCProviderDAO.java
@@ -0,0 +1,78 @@
+/*
+ * 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.dao;
+
+import java.util.List;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.core.persistence.api.dao.OIDCProviderDAO;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+import org.apache.syncope.core.persistence.jpa.entity.JPAOIDCProvider;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JPAOIDCProviderDAO extends AbstractDAO<OIDCProvider> implements OIDCProviderDAO {
+
+ @Transactional(readOnly = true)
+ @Override
+ public OIDCProvider find(final String key) {
+ return entityManager().find(JPAOIDCProvider.class, key);
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public OIDCProvider findByName(final String name) {
+ TypedQuery<OIDCProvider> query = entityManager().createQuery(
+ "SELECT e FROM " + JPAOIDCProvider.class.getSimpleName()
+ + " e WHERE e.name = :name", OIDCProvider.class);
+ query.setParameter("name", name);
+
+ OIDCProvider result = null;
+ try {
+ result = query.getSingleResult();
+ } catch (NoResultException e) {
+ LOG.debug("No OIDC Provider found with name {}", name, e);
+ }
+
+ return result;
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public List<OIDCProvider> findAll() {
+ TypedQuery<OIDCProvider> query = entityManager().createQuery(
+ "SELECT e FROM " + JPAOIDCProvider.class.getSimpleName() + " e", OIDCProvider.class);
+ return query.getResultList();
+ }
+
+ @Override
+ public OIDCProvider save(final OIDCProvider op) {
+ return entityManager().merge(op);
+ }
+
+ @Override
+ public void delete(final String key) {
+ OIDCProvider op = find(key);
+ if (op != null) {
+ entityManager().remove(op);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCEntityFactory.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCEntityFactory.java b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCEntityFactory.java
new file mode 100644
index 0000000..e5870bf
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCEntityFactory.java
@@ -0,0 +1,49 @@
+/*
+ * 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 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.springframework.stereotype.Component;
+
+@Component
+public class JPAOIDCEntityFactory implements OIDCEntityFactory {
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <E extends Entity> E newEntity(final Class<E> reference) {
+ E result;
+
+ if (reference.equals(OIDCProvider.class)) {
+ result = (E) new JPAOIDCProvider();
+ } else if (reference.equals(OIDCProviderItem.class)) {
+ result = (E) new JPAOIDCProviderItem();
+ } else if (reference.equals(OIDCUserTemplate.class)) {
+ result = (E) new JPAOIDCUserTemplate();
+ } else {
+ throw new IllegalArgumentException("Could not find a JPA implementation of " + reference.getName());
+ }
+
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/f29e60f6/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProvider.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProvider.java b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProvider.java
new file mode 100644
index 0000000..5ea6468
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProvider.java
@@ -0,0 +1,257 @@
+/*
+ * 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.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+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;
+
+@Entity
+@Table(name = JPAOIDCProvider.TABLE)
+@Cacheable
+public class JPAOIDCProvider extends AbstractGeneratedKeyEntity implements OIDCProvider {
+
+ public static final String TABLE = "OIDCProvider";
+
+ private static final long serialVersionUID = 1423093003585826403L;
+
+ @Column(unique = true, nullable = false)
+ private String name;
+
+ @Column(unique = true, nullable = false)
+ private String clientID;
+
+ @Column(unique = true, nullable = false)
+ private String clientSecret;
+
+ @Column(nullable = false)
+ private String authorizationEndpoint;
+
+ @Column(nullable = false)
+ private String tokenEndpoint;
+
+ @Column(nullable = false)
+ private String jwksUri;
+
+ @Column(nullable = false)
+ private String issuer;
+
+ @Column(nullable = false)
+ private String userinfoEndpoint;
+
+ @Column(nullable = false)
+ private boolean hasDiscovery;
+
+ @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "op")
+ private JPAOIDCUserTemplate userTemplate;
+
+ @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "op")
+ private List<JPAOIDCProviderItem> items = new ArrayList<>();
+
+ @Min(0)
+ @Max(1)
+ @Column(nullable = false)
+ private Integer createUnmatching;
+
+ @Min(0)
+ @Max(1)
+ @Column(nullable = false)
+ private Integer updateMatching;
+
+ @ElementCollection(fetch = FetchType.EAGER)
+ @Column(name = "actionClassName")
+ @CollectionTable(name = TABLE + "_actionsClassNames",
+ joinColumns =
+ @JoinColumn(name = "oidcOP_id", referencedColumnName = "id"))
+ private Set<String> actionsClassNames = new HashSet<>();
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getClientID() {
+ return clientID;
+ }
+
+ @Override
+ public void setClientID(final String clientID) {
+ this.clientID = clientID;
+ }
+
+ @Override
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ @Override
+ public void setClientSecret(final String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ @Override
+ public String getAuthorizationEndpoint() {
+ return authorizationEndpoint;
+ }
+
+ @Override
+ public void setAuthorizationEndpoint(final String authorizationEndpoint) {
+ this.authorizationEndpoint = authorizationEndpoint;
+ }
+
+ @Override
+ public String getTokenEndpoint() {
+ return tokenEndpoint;
+ }
+
+ @Override
+ public void setTokenEndpoint(final String tokenEndpoint) {
+ this.tokenEndpoint = tokenEndpoint;
+ }
+
+ @Override
+ public String getJwksUri() {
+ return jwksUri;
+ }
+
+ @Override
+ public void setJwksUri(final String jwksUri) {
+ this.jwksUri = jwksUri;
+ }
+
+ @Override
+ public String getIssuer() {
+ return issuer;
+ }
+
+ @Override
+ public void setIssuer(final String issuer) {
+ this.issuer = issuer;
+ }
+
+ @Override
+ public String getUserinfoEndpoint() {
+ return userinfoEndpoint;
+ }
+
+ @Override
+ public void setUserinfoEndpoint(final String userinfoEndpoint) {
+ this.userinfoEndpoint = userinfoEndpoint;
+ }
+
+ @Override
+ public boolean getHasDiscovery() {
+ return hasDiscovery;
+ }
+
+ @Override
+ public void setHasDiscovery(final boolean hasDiscovery) {
+ this.hasDiscovery = hasDiscovery;
+ }
+
+ @Override
+ public boolean isCreateUnmatching() {
+ return isBooleanAsInteger(createUnmatching);
+ }
+
+ @Override
+ public void setCreateUnmatching(final boolean createUnmatching) {
+ this.createUnmatching = getBooleanAsInteger(createUnmatching);
+ }
+
+ @Override
+ public boolean isUpdateMatching() {
+ return isBooleanAsInteger(updateMatching);
+ }
+
+ @Override
+ public void setUpdateMatching(final boolean updateMatching) {
+ this.updateMatching = getBooleanAsInteger(updateMatching);
+ }
+
+ @Override
+ public OIDCUserTemplate getUserTemplate() {
+ return userTemplate;
+ }
+
+ @Override
+ public void setUserTemplate(final OIDCUserTemplate userTemplate) {
+ checkType(userTemplate, JPAOIDCUserTemplate.class);
+ this.userTemplate = (JPAOIDCUserTemplate) userTemplate;
+ }
+
+ @Override
+ public boolean add(final OIDCProviderItem item) {
+ checkType(item, JPAOIDCProviderItem.class);
+ return items.contains((JPAOIDCProviderItem) item) || items.add((JPAOIDCProviderItem) item);
+ }
+
+ @Override
+ public List<? extends OIDCProviderItem> getItems() {
+ return items;
+ }
+
+ @Override
+ public OIDCProviderItem getConnObjectKeyItem() {
+ return IterableUtils.find(getItems(), new Predicate<OIDCProviderItem>() {
+
+ @Override
+ public boolean evaluate(final OIDCProviderItem item) {
+ return item.isConnObjectKey();
+ }
+ });
+ }
+
+ @Override
+ public void setConnObjectKeyItem(final OIDCProviderItem item) {
+ item.setConnObjectKey(true);
+ this.add(item);
+ }
+
+ @Override
+ public Set<String> getActionsClassNames() {
+ return actionsClassNames;
+ }
+
+}
[6/8] syncope git commit: [SYNCOPE-1270] implementation for OpenID
Connect for Admin Console and Enduser - This closes #74
Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/logic/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/pom.xml b/ext/oidcclient/logic/pom.xml
new file mode 100644
index 0000000..6701bc3
--- /dev/null
+++ b/ext/oidcclient/logic/pom.xml
@@ -0,0 +1,76 @@
+<?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 Logic</name>
+ <description>Apache Syncope Ext: OIDC Client Logic</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-logic</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-logic</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-provisioning-java</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-rs-extension-providers</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-rt-rs-security-sso-oidc</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ </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/logic/src/main/java/org/apache/syncope/core/logic/OIDCClientLogic.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCClientLogic.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCClientLogic.java
new file mode 100644
index 0000000..638ae5e
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCClientLogic.java
@@ -0,0 +1,406 @@
+/*
+ * 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.logic;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.uuid.Generators;
+import com.fasterxml.uuid.impl.RandomBasedGenerator;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.provider.json.JsonMapObjectProvider;
+import org.apache.cxf.rs.security.jose.jaxrs.JsonWebKeysProvider;
+import org.apache.cxf.rs.security.oauth2.client.Consumer;
+import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken;
+import org.apache.cxf.rs.security.oidc.common.IdToken;
+import org.apache.cxf.rs.security.oidc.common.UserInfo;
+import org.apache.cxf.rs.security.oidc.rp.IdTokenReader;
+import org.apache.cxf.rs.security.oidc.rp.UserInfoClient;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.OIDCConstants;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.OIDCLoginRequestTO;
+import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.core.logic.model.TokenEndpointResponse;
+import org.apache.syncope.core.logic.oidc.OIDCUserManager;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.OIDCProviderDAO;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+import org.apache.syncope.core.persistence.api.entity.OIDCProviderItem;
+import org.apache.syncope.core.provisioning.api.data.AccessTokenDataBinder;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import org.apache.syncope.core.spring.security.AuthContextUtils;
+import org.apache.syncope.core.spring.security.AuthDataAccessor;
+import org.apache.syncope.core.spring.security.Encryptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class OIDCClientLogic extends AbstractTransactionalLogic<AbstractBaseBean> {
+
+ private static final Encryptor ENCRYPTOR = Encryptor.getInstance();
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private static final RandomBasedGenerator UUID_GENERATOR = Generators.randomBasedGenerator();
+
+ private static final String JWT_CLAIM_OP_ENTITYID = "OP_ENTITYID";
+
+ private static final String JWT_CLAIM_USERID = "USERID";
+
+ @Autowired
+ private AuthDataAccessor authDataAccessor;
+
+ @Autowired
+ private AccessTokenDataBinder accessTokenDataBinder;
+
+ @Autowired
+ private OIDCProviderDAO opDAO;
+
+ @Autowired
+ private OIDCUserManager userManager;
+
+ private OIDCProvider getOIDCProvider(final String opName) {
+ OIDCProvider op = null;
+ if (StringUtils.isBlank(opName)) {
+ List<OIDCProvider> ops = opDAO.findAll();
+ if (!ops.isEmpty()) {
+ op = ops.get(0);
+ }
+ } else {
+ op = opDAO.findByName(opName);
+ }
+ if (op == null) {
+ throw new NotFoundException(StringUtils.isBlank(opName)
+ ? "Any OIDC Provider"
+ : "OIDC Provider '" + opName + "'");
+ }
+ return op;
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.ANONYMOUS + "')")
+ public OIDCLoginRequestTO createLoginRequest(final String redirectURI, final String opName) {
+ // 1. look for Provider
+ OIDCProvider op = getOIDCProvider(opName);
+
+ // 2. create AuthnRequest
+ OIDCLoginRequestTO requestTO = new OIDCLoginRequestTO();
+ requestTO.setProviderAddress(op.getAuthorizationEndpoint());
+ requestTO.setClientId(op.getClientID());
+ requestTO.setScope("openid email profile");
+ requestTO.setResponseType("code");
+ requestTO.setRedirectURI(redirectURI);
+ requestTO.setState(UUID_GENERATOR.generate().toString());
+ return requestTO;
+ }
+
+ @PreAuthorize("hasRole('" + StandardEntitlement.ANONYMOUS + "')")
+ public OIDCLoginResponseTO login(final String redirectURI, final String authorizationCode, final String opName) {
+ OIDCProvider op = getOIDCProvider(opName);
+
+ // 1. get OpenID Connect tokens
+ String body = OIDCConstants.CODE + "=" + authorizationCode
+ + "&" + OIDCConstants.CLIENT_ID + "=" + op.getClientID()
+ + "&" + OIDCConstants.CLIENT_SECRET + "=" + op.getClientSecret()
+ + "&" + OIDCConstants.REDIRECT_URI + "=" + redirectURI
+ + "&" + OIDCConstants.GRANT_TYPE + "=authorization_code";
+ TokenEndpointResponse tokenEndpointResponse = getOIDCTokens(op.getTokenEndpoint(), body);
+
+ // 1. get OpenID Connect tokens
+ Consumer consumer = new Consumer(op.getClientID(), op.getClientSecret());
+
+ // 2. validate token
+ IdToken idToken = getValidatedIdToken(op, consumer, tokenEndpointResponse.getIdToken());
+
+ // 3. extract user information
+ UserInfo userInfo = getUserInfo(op, tokenEndpointResponse.getAccessToken(), idToken, consumer);
+
+ // 4. prepare the result: find matching user (if any) and return the received attributes
+ final OIDCLoginResponseTO responseTO = new OIDCLoginResponseTO();
+ responseTO.setEmail(userInfo.getEmail());
+ responseTO.setFamilyName(userInfo.getFamilyName());
+ responseTO.setGivenName(userInfo.getGivenName());
+ responseTO.setName(userInfo.getName());
+ responseTO.setSubject(userInfo.getSubject());
+
+ String keyValue = null;
+ for (OIDCProviderItem item : op.getItems()) {
+ AttrTO attrTO = new AttrTO();
+ attrTO.setSchema(item.getExtAttrName());
+ switch (item.getExtAttrName()) {
+ case UserInfo.PREFERRED_USERNAME_CLAIM:
+ attrTO.getValues().add(userInfo.getPreferredUserName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getPreferredUserName();
+ }
+ break;
+
+ case UserInfo.PROFILE_CLAIM:
+ attrTO.getValues().add(userInfo.getProfile());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getProfile();
+ }
+ break;
+
+ case UserInfo.EMAIL_CLAIM:
+ attrTO.getValues().add(userInfo.getEmail());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getEmail();
+ }
+ break;
+
+ case UserInfo.NAME_CLAIM:
+ attrTO.getValues().add(userInfo.getName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getName();
+ }
+ break;
+
+ case UserInfo.FAMILY_NAME_CLAIM:
+ attrTO.getValues().add(userInfo.getFamilyName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getFamilyName();
+ }
+ break;
+
+ case UserInfo.MIDDLE_NAME_CLAIM:
+ attrTO.getValues().add(userInfo.getMiddleName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getMiddleName();
+ }
+ break;
+
+ case UserInfo.GIVEN_NAME_CLAIM:
+ attrTO.getValues().add(userInfo.getGivenName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getGivenName();
+ }
+ break;
+
+ case UserInfo.NICKNAME_CLAIM:
+ attrTO.getValues().add(userInfo.getNickName());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getNickName();
+ }
+ break;
+
+ case UserInfo.GENDER_CLAIM:
+ attrTO.getValues().add(userInfo.getGender());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getGender();
+ }
+ break;
+
+ case UserInfo.LOCALE_CLAIM:
+ attrTO.getValues().add(userInfo.getLocale());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getLocale();
+ }
+ break;
+
+ case UserInfo.ZONEINFO_CLAIM:
+ attrTO.getValues().add(userInfo.getZoneInfo());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getZoneInfo();
+ }
+ break;
+
+ case UserInfo.BIRTHDATE_CLAIM:
+ attrTO.getValues().add(userInfo.getBirthDate());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getBirthDate();
+ }
+ break;
+
+ case UserInfo.PHONE_CLAIM:
+ attrTO.getValues().add(userInfo.getPhoneNumber());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getPhoneNumber();
+ }
+ break;
+
+ case UserInfo.ADDRESS_CLAIM:
+ attrTO.getValues().add(userInfo.getUserAddress().getFormatted());
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = userInfo.getUserAddress().getFormatted();
+ }
+ break;
+
+ case UserInfo.UPDATED_AT_CLAIM:
+ attrTO.getValues().add(Long.toString(userInfo.getUpdatedAt()));
+ responseTO.getAttrs().add(attrTO);
+ if (item.isConnObjectKey()) {
+ keyValue = Long.toString(userInfo.getUpdatedAt());
+ }
+ break;
+
+ default:
+ LOG.warn("Unsupported: {} ", item.getExtAttrName());
+ }
+ }
+
+ final List<String> matchingUsers = keyValue == null
+ ? Collections.<String>emptyList()
+ : userManager.findMatchingUser(keyValue, op.getConnObjectKeyItem().get());
+ LOG.debug("Found {} matching users for {}", matchingUsers.size(), keyValue);
+
+ String username;
+ if (matchingUsers.isEmpty()) {
+ if (op.isCreateUnmatching()) {
+ LOG.debug("No user matching {}, about to create", keyValue);
+
+ final String emailValue = userInfo.getEmail();
+ username = AuthContextUtils.execWithAuthContext(AuthContextUtils.getDomain(),
+ () -> userManager.create(op, responseTO, emailValue));
+ } else {
+ throw new NotFoundException("User matching the provided value " + keyValue);
+ }
+ } else if (matchingUsers.size() > 1) {
+ throw new IllegalArgumentException("Several users match the provided value " + keyValue);
+ } else {
+ if (op.isUpdateMatching()) {
+ LOG.debug("About to update {} for {}", matchingUsers.get(0), keyValue);
+
+ username = AuthContextUtils.execWithAuthContext(AuthContextUtils.getDomain(),
+ () -> userManager.update(matchingUsers.get(0), op, responseTO));
+ } else {
+ username = matchingUsers.get(0);
+ }
+
+ }
+
+ responseTO.setUsername(username);
+
+ // 5. generate JWT for further access
+ Map<String, Object> claims = new HashMap<>();
+ claims.put(JWT_CLAIM_OP_ENTITYID, idToken.getIssuer());
+ claims.put(JWT_CLAIM_USERID, idToken.getSubject());
+
+ byte[] authorities = null;
+ try {
+ authorities = ENCRYPTOR.encode(POJOHelper.serialize(
+ authDataAccessor.getAuthorities(responseTO.getUsername())), CipherAlgorithm.AES).
+ getBytes();
+ } catch (Exception e) {
+ LOG.error("Could not fetch authorities", e);
+ }
+
+ Pair<String, Date> accessTokenInfo =
+ accessTokenDataBinder.create(responseTO.getUsername(), claims, authorities, true);
+ responseTO.setAccessToken(accessTokenInfo.getLeft());
+ responseTO.setAccessTokenExpiryTime(accessTokenInfo.getRight());
+
+ return responseTO;
+ }
+
+ private TokenEndpointResponse getOIDCTokens(final String url, final String body) {
+ String oidcTokens = WebClient.create(url).
+ type(MediaType.APPLICATION_FORM_URLENCODED).accept(MediaType.APPLICATION_JSON).
+ post(body).
+ readEntity(String.class);
+ TokenEndpointResponse endpointResponse = null;
+ try {
+ endpointResponse = MAPPER.readValue(oidcTokens, TokenEndpointResponse.class);
+ } catch (Exception e) {
+ LOG.error("While getting the Tokens from the OP", e);
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+ return endpointResponse;
+ }
+
+ private IdToken getValidatedIdToken(final OIDCProvider op, final Consumer consumer, final String jwtIdToken) {
+ IdTokenReader idTokenReader = new IdTokenReader();
+ idTokenReader.setClockOffset(10);
+ idTokenReader.setIssuerId(op.getIssuer());
+ WebClient jwkSetClient = WebClient.create(
+ op.getJwksUri(), Arrays.asList(new JsonWebKeysProvider())).
+ accept(MediaType.APPLICATION_JSON);
+ idTokenReader.setJwkSetClient(jwkSetClient);
+ IdToken idToken = null;
+ try {
+ idToken = idTokenReader.getIdToken(jwtIdToken, consumer);
+ } catch (Exception e) {
+ LOG.error("While validating the id_token", e);
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+ return idToken;
+ }
+
+ private UserInfo getUserInfo(
+ final OIDCProvider op,
+ final String accessToken,
+ final IdToken idToken,
+ final Consumer consumer) {
+
+ WebClient userInfoServiceClient = WebClient.create(
+ op.getUserinfoEndpoint(), Arrays.asList(new JsonMapObjectProvider())).
+ accept(MediaType.APPLICATION_JSON);
+ ClientAccessToken clientAccessToken = new ClientAccessToken("Bearer", accessToken);
+ UserInfoClient userInfoClient = new UserInfoClient();
+ userInfoClient.setUserInfoServiceClient(userInfoServiceClient);
+ UserInfo userInfo = null;
+ try {
+ userInfo = userInfoClient.getUserInfo(clientAccessToken, idToken, consumer);
+ } catch (Exception e) {
+ LOG.error("While getting the userInfo", e);
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
+ sce.getElements().add(e.getMessage());
+ throw sce;
+ }
+ return userInfo;
+ }
+
+ @Override
+ protected AbstractBaseBean resolveReference(
+ final Method method, final Object... args) throws UnresolvedReferenceException {
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCProviderLogic.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCProviderLogic.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCProviderLogic.java
new file mode 100644
index 0000000..af8e579
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/OIDCProviderLogic.java
@@ -0,0 +1,167 @@
+/*
+ * 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.logic;
+
+import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.ws.rs.core.MediaType;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ItemTO;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.OIDCClientEntitlement;
+import org.apache.syncope.core.logic.init.OIDCClientClassPathScanImplementationLookup;
+import org.apache.syncope.core.logic.model.OIDCProviderDiscoveryDocument;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.OIDCProviderDAO;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+import org.apache.syncope.core.provisioning.api.data.OIDCProviderDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+public class OIDCProviderLogic extends AbstractTransactionalLogic<OIDCProviderTO> {
+
+ @Autowired
+ private OIDCProviderDAO opDAO;
+
+ @Autowired
+ private OIDCProviderDataBinder binder;
+
+ @Autowired
+ private OIDCClientClassPathScanImplementationLookup implLookup;
+
+ @PreAuthorize("isAuthenticated()")
+ public Set<String> getActionsClasses() {
+ return implLookup.getActionsClasses();
+ }
+
+ private OIDCProviderDiscoveryDocument getDiscoveryDocument(final String issuer) {
+ WebClient client = WebClient.create(
+ issuer + "/.well-known/openid-configuration", Arrays.asList(new JacksonJsonProvider())).
+ accept(MediaType.APPLICATION_JSON);
+ return client.get(OIDCProviderDiscoveryDocument.class);
+ }
+
+ @PreAuthorize("hasRole('" + OIDCClientEntitlement.OP_CREATE + "')")
+ public String createFromDiscovery(final OIDCProviderTO opTO) {
+ OIDCProviderDiscoveryDocument discoveryDocument = getDiscoveryDocument(opTO.getIssuer());
+
+ opTO.setAuthorizationEndpoint(discoveryDocument.getAuthorizationEndpoint());
+ opTO.setIssuer(discoveryDocument.getIssuer());
+ opTO.setJwksUri(discoveryDocument.getJwksUri());
+ opTO.setTokenEndpoint(discoveryDocument.getTokenEndpoint());
+ opTO.setUserinfoEndpoint(discoveryDocument.getUserinfoEndpoint());
+
+ return create(opTO);
+ }
+
+ @PreAuthorize("hasRole('" + OIDCClientEntitlement.OP_CREATE + "')")
+ public String create(final OIDCProviderTO opTO) {
+ if (opTO.getConnObjectKeyItem() == null) {
+ ItemTO connObjectKeyItem = new ItemTO();
+ connObjectKeyItem.setIntAttrName("username");
+ connObjectKeyItem.setExtAttrName("email");
+ opTO.setConnObjectKeyItem(connObjectKeyItem);
+ }
+
+ OIDCProvider provider = opDAO.save(binder.create(opTO));
+
+ return provider.getKey();
+ }
+
+ @PreAuthorize("isAuthenticated()")
+ @Transactional(readOnly = true)
+ public List<OIDCProviderTO> list() {
+ return opDAO.findAll().stream().map(binder::getOIDCProviderTO).collect(Collectors.toList());
+ }
+
+ @PreAuthorize("hasRole('" + OIDCClientEntitlement.OP_READ + "')")
+ @Transactional(readOnly = true)
+ public OIDCProviderTO read(final String key) {
+ OIDCProvider op = opDAO.find(key);
+ if (op == null) {
+ throw new NotFoundException("OIDC Provider '" + key + "'");
+ }
+ return binder.getOIDCProviderTO(op);
+ }
+
+ @PreAuthorize("hasRole('" + OIDCClientEntitlement.OP_UPDATE + "')")
+ public void update(final OIDCProviderTO oidcProviderTO) {
+ OIDCProvider oidcProvider = opDAO.find(oidcProviderTO.getKey());
+ if (oidcProvider == null) {
+ throw new NotFoundException("OIDC Provider '" + oidcProviderTO.getKey() + "'");
+ }
+
+ if (!oidcProvider.getIssuer().equals(oidcProviderTO.getIssuer())) {
+ LOG.error("Issuers do not match: expected {}, found {}",
+ oidcProvider.getIssuer(), oidcProviderTO.getIssuer());
+ SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidEntity);
+ sce.getElements().add("Issuers do not match");
+ throw sce;
+ }
+
+ opDAO.save(binder.update(oidcProvider, oidcProviderTO));
+ }
+
+ @PreAuthorize("hasRole('" + OIDCClientEntitlement.OP_DELETE + "')")
+ public void delete(final String key) {
+ OIDCProvider op = opDAO.find(key);
+ if (op == null) {
+ throw new NotFoundException("OIDC Provider '" + key + "'");
+ }
+ opDAO.delete(key);
+ }
+
+ @Override
+ protected OIDCProviderTO resolveReference(
+ final Method method, final Object... args) throws UnresolvedReferenceException {
+
+ String key = null;
+
+ if (ArrayUtils.isNotEmpty(args)) {
+ for (int i = 0; key == null && i < args.length; i++) {
+ if (args[i] instanceof String) {
+ key = (String) args[i];
+ } else if (args[i] instanceof OIDCProviderTO) {
+ key = ((OIDCProviderTO) args[i]).getKey();
+ }
+ }
+ }
+
+ if (key != null) {
+ try {
+ return binder.getOIDCProviderTO(opDAO.find(key));
+ } catch (Throwable ignore) {
+ LOG.debug("Unresolved reference", ignore);
+ throw new UnresolvedReferenceException(ignore);
+ }
+ }
+
+ throw new UnresolvedReferenceException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientClassPathScanImplementationLookup.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientClassPathScanImplementationLookup.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientClassPathScanImplementationLookup.java
new file mode 100644
index 0000000..82d6d8a
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientClassPathScanImplementationLookup.java
@@ -0,0 +1,78 @@
+/*
+ * 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.logic.init;
+
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.syncope.core.persistence.api.ImplementationLookup;
+import org.apache.syncope.core.persistence.api.SyncopeLoader;
+import org.apache.syncope.core.provisioning.api.OIDCProviderActions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
+import org.springframework.core.type.filter.AssignableTypeFilter;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ClassUtils;
+
+@Component
+public class OIDCClientClassPathScanImplementationLookup implements SyncopeLoader {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ImplementationLookup.class);
+
+ private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope.core";
+
+ private Set<String> actionsClasses;
+
+ @Override
+ public Integer getPriority() {
+ return Integer.MIN_VALUE;
+ }
+
+ @Override
+ public void load() {
+ actionsClasses = new HashSet<>();
+
+ ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
+ scanner.addIncludeFilter(new AssignableTypeFilter(OIDCProviderActions.class));
+
+ for (BeanDefinition bd : scanner.findCandidateComponents(DEFAULT_BASE_PACKAGE)) {
+ try {
+ Class<?> clazz = ClassUtils.resolveClassName(
+ bd.getBeanClassName(), ClassUtils.getDefaultClassLoader());
+ boolean isAbstractClazz = Modifier.isAbstract(clazz.getModifiers());
+
+ if (OIDCProviderActions.class.isAssignableFrom(clazz) && !isAbstractClazz) {
+ actionsClasses.add(clazz.getName());
+ }
+ } catch (Throwable t) {
+ LOG.warn("Could not inspect class {}", bd.getBeanClassName(), t);
+ }
+ }
+
+ actionsClasses = Collections.unmodifiableSet(actionsClasses);
+ }
+
+ public Set<String> getActionsClasses() {
+ return actionsClasses;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
new file mode 100644
index 0000000..f24eb79
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
@@ -0,0 +1,55 @@
+/*
+ * 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.logic.init;
+
+import org.apache.syncope.common.lib.types.OIDCClientEntitlement;
+import org.apache.syncope.core.persistence.api.DomainsHolder;
+import org.apache.syncope.core.persistence.api.SyncopeLoader;
+import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
+import org.apache.syncope.core.spring.security.AuthContextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class OIDCClientLoader implements SyncopeLoader {
+
+ @Autowired
+ private DomainsHolder domainsHolder;
+
+ @Override
+ public Integer getPriority() {
+ return 1000;
+ }
+
+ @Override
+ public void load() {
+ EntitlementsHolder.getInstance().init(OIDCClientEntitlement.values());
+
+ for (String domain : domainsHolder.getDomains().keySet()) {
+ AuthContextUtils.execWithAuthContext(domain, new AuthContextUtils.Executable<Void>() {
+
+ @Override
+ public Void exec() {
+ return null;
+ }
+ });
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/OIDCProviderDiscoveryDocument.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/OIDCProviderDiscoveryDocument.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/OIDCProviderDiscoveryDocument.java
new file mode 100644
index 0000000..aae3f0c
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/OIDCProviderDiscoveryDocument.java
@@ -0,0 +1,128 @@
+/*
+ * 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.logic.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonPropertyOrder({
+ "issuer",
+ "authorization_endpoint",
+ "token_endpoint",
+ "userinfo_endpoint",
+ "end_session_endpoint",
+ "jwks_uri",
+ "registration_endpoint"
+})
+public class OIDCProviderDiscoveryDocument {
+
+ @JsonProperty("issuer")
+ private String issuer;
+
+ @JsonProperty("authorization_endpoint")
+ private String authorizationEndpoint;
+
+ @JsonProperty("token_endpoint")
+ private String tokenEndpoint;
+
+ @JsonProperty("userinfo_endpoint")
+ private String userinfoEndpoint;
+
+ @JsonProperty("end_session_endpoint")
+ private String endSessionEndpoint;
+
+ @JsonProperty("jwks_uri")
+ private String jwksUri;
+
+ @JsonProperty("registration_endpoint")
+ private String registrationEndpoint;
+
+ @JsonProperty("issuer")
+ public String getIssuer() {
+ return issuer;
+ }
+
+ @JsonProperty("issuer")
+ public void setIssuer(final String issuer) {
+ this.issuer = issuer;
+ }
+
+ @JsonProperty("authorization_endpoint")
+ public String getAuthorizationEndpoint() {
+ return authorizationEndpoint;
+ }
+
+ @JsonProperty("authorization_endpoint")
+ public void setAuthorizationEndpoint(final String authorizationEndpoint) {
+ this.authorizationEndpoint = authorizationEndpoint;
+ }
+
+ @JsonProperty("token_endpoint")
+ public String getTokenEndpoint() {
+ return tokenEndpoint;
+ }
+
+ @JsonProperty("token_endpoint")
+ public void setTokenEndpoint(final String tokenEndpoint) {
+ this.tokenEndpoint = tokenEndpoint;
+ }
+
+ @JsonProperty("userinfo_endpoint")
+ public String getUserinfoEndpoint() {
+ return userinfoEndpoint;
+ }
+
+ @JsonProperty("userinfo_endpoint")
+ public void setUserinfoEndpoint(final String userinfoEndpoint) {
+ this.userinfoEndpoint = userinfoEndpoint;
+ }
+
+ @JsonProperty("end_session_endpoint")
+ public String getEndSessionEndpoint() {
+ return endSessionEndpoint;
+ }
+
+ @JsonProperty("end_session_endpoint")
+ public void setEndSessionEndpoint(final String endSessionEndpoint) {
+ this.endSessionEndpoint = endSessionEndpoint;
+ }
+
+ @JsonProperty("jwks_uri")
+ public String getJwksUri() {
+ return jwksUri;
+ }
+
+ @JsonProperty("jwks_uri")
+ public void setJwksUri(final String jwksUri) {
+ this.jwksUri = jwksUri;
+ }
+
+ @JsonProperty("registration_endpoint")
+ public String getRegistrationEndpoint() {
+ return registrationEndpoint;
+ }
+
+ @JsonProperty("registration_endpoint")
+ public void setRegistrationEndpoint(final String registrationEndpoint) {
+ this.registrationEndpoint = registrationEndpoint;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/TokenEndpointResponse.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/TokenEndpointResponse.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/TokenEndpointResponse.java
new file mode 100644
index 0000000..7908b88
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/model/TokenEndpointResponse.java
@@ -0,0 +1,86 @@
+/*
+ * 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.logic.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonPropertyOrder({
+ "access_token",
+ "id_token",
+ "expires_in",
+ "token_type"
+})
+public class TokenEndpointResponse {
+
+ @JsonProperty("access_token")
+ private String accessToken;
+
+ @JsonProperty("id_token")
+ private String idToken;
+
+ @JsonProperty("expires_in")
+ private int expiresIn;
+
+ @JsonProperty("token_type")
+ private String tokenType;
+
+ @JsonProperty("access_token")
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ @JsonProperty("access_token")
+ public void setAccessToken(final String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ @JsonProperty("id_token")
+ public String getIdToken() {
+ return idToken;
+ }
+
+ @JsonProperty("id_token")
+ public void setIdToken(final String idToken) {
+ this.idToken = idToken;
+ }
+
+ @JsonProperty("expires_in")
+ public int getExpiresIn() {
+ return expiresIn;
+ }
+
+ @JsonProperty("expires_in")
+ public void setExpiresIn(final int expiresIn) {
+ this.expiresIn = expiresIn;
+ }
+
+ @JsonProperty("token_type")
+ public String getTokenType() {
+ return tokenType;
+ }
+
+ @JsonProperty("token_type")
+ public void setTokenType(final String tokenType) {
+ this.tokenType = tokenType;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java
new file mode 100644
index 0000000..25cb784
--- /dev/null
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java
@@ -0,0 +1,292 @@
+/*
+ * 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.logic.oidc;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.AnyOperations;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.patch.UserPatch;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
+import org.apache.syncope.common.lib.to.PropagationStatus;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+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.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
+import org.apache.syncope.core.provisioning.api.OIDCProviderActions;
+import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
+import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
+import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
+import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
+import org.apache.syncope.core.provisioning.java.utils.TemplateUtils;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+public class OIDCUserManager {
+
+ private static final Logger LOG = LoggerFactory.getLogger(OIDCUserManager.class);
+
+ @Autowired
+ private UserDAO userDAO;
+
+ @Autowired
+ private PlainSchemaDAO plainSchemaDAO;
+
+ @Autowired
+ private IntAttrNameParser intAttrNameParser;
+
+ @Autowired
+ private EntityFactory entityFactory;
+
+ @Autowired
+ private TemplateUtils templateUtils;
+
+ @Autowired
+ private UserProvisioningManager provisioningManager;
+
+ @Autowired
+ private UserDataBinder binder;
+
+ @Transactional(readOnly = true)
+ public List<String> findMatchingUser(final String keyValue, final OIDCProviderItem connObjectKeyItem) {
+ List<String> result = new ArrayList<>();
+
+ String transformed = keyValue;
+ for (ItemTransformer transformer : MappingUtils.getItemTransformers(connObjectKeyItem)) {
+ List<Object> output = transformer.beforePull(
+ null,
+ null,
+ Collections.<Object>singletonList(transformed));
+ if (output != null && !output.isEmpty()) {
+ transformed = output.get(0).toString();
+ }
+ }
+
+ IntAttrName intAttrName;
+ try {
+ intAttrName = intAttrNameParser.parse(connObjectKeyItem.getIntAttrName(), AnyTypeKind.USER);
+ } catch (ParseException e) {
+ LOG.error("Invalid intAttrName '{}' specified, ignoring", connObjectKeyItem.getIntAttrName(), e);
+ return result;
+ }
+
+ if (intAttrName.getField() != null) {
+ switch (intAttrName.getField()) {
+ case "key":
+ User byKey = userDAO.find(transformed);
+ if (byKey != null) {
+ result.add(byKey.getUsername());
+ }
+ break;
+
+ case "username":
+ User byUsername = userDAO.findByUsername(transformed);
+ if (byUsername != null) {
+ result.add(byUsername.getUsername());
+ }
+ break;
+
+ default:
+ }
+ } else if (intAttrName.getSchemaType() != null) {
+ switch (intAttrName.getSchemaType()) {
+ case PLAIN:
+ PlainAttrValue value = entityFactory.newEntity(UPlainAttrValue.class);
+
+ PlainSchema schema = plainSchemaDAO.find(intAttrName.getSchemaName());
+ if (schema == null) {
+ value.setStringValue(transformed);
+ } else {
+ try {
+ value.parseValue(schema, transformed);
+ } catch (ParsingValidationException e) {
+ LOG.error("While parsing provided key value {}", transformed, e);
+ value.setStringValue(transformed);
+ }
+ }
+
+ result.addAll(userDAO.findByPlainAttrValue(intAttrName.getSchemaName(), value, false).stream().
+ map(User::getUsername).collect(Collectors.toList()));
+ break;
+
+ case DERIVED:
+ result.addAll(userDAO.findByDerAttrValue(intAttrName.getSchemaName(), transformed, false).stream().
+ map(User::getUsername).collect(Collectors.toList()));
+ break;
+
+ default:
+ }
+ }
+
+ return result;
+ }
+
+ private List<OIDCProviderActions> getActions(final OIDCProvider op) {
+ List<OIDCProviderActions> actions = new ArrayList<>();
+
+ op.getActionsClassNames().forEach(className -> {
+ try {
+ Class<?> actionsClass = Class.forName(className);
+ OIDCProviderActions opActions = (OIDCProviderActions) ApplicationContextProvider.getBeanFactory().
+ createBean(actionsClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
+
+ actions.add(opActions);
+ } catch (Exception e) {
+ LOG.warn("Class '{}' not found", className, e);
+ }
+ });
+
+ return actions;
+ }
+
+ public void fill(final OIDCProvider op, final OIDCLoginResponseTO responseTO, final UserTO userTO) {
+ op.getItems().forEach(item -> {
+ List<String> values = Collections.emptyList();
+ Optional<AttrTO> oidcAttr = responseTO.getAttr(item.getExtAttrName());
+ if (oidcAttr.isPresent() && !oidcAttr.get().getValues().isEmpty()) {
+ values = oidcAttr.get().getValues();
+
+ List<Object> transformed = new ArrayList<>(values);
+ for (ItemTransformer transformer : MappingUtils.getItemTransformers(item)) {
+ transformed = transformer.beforePull(null, userTO, transformed);
+ }
+ values.clear();
+ for (Object value : transformed) {
+ values.add(value.toString());
+ }
+ }
+
+ IntAttrName intAttrName = null;
+ try {
+ intAttrName = intAttrNameParser.parse(item.getIntAttrName(), AnyTypeKind.USER);
+ } catch (ParseException e) {
+ LOG.error("Invalid intAttrName '{}' specified, ignoring", item.getIntAttrName(), e);
+ }
+
+ if (intAttrName != null && intAttrName.getField() != null) {
+ switch (intAttrName.getField()) {
+ case "username":
+ if (!values.isEmpty()) {
+ userTO.setUsername(values.get(0));
+ }
+ break;
+
+ default:
+ LOG.warn("Unsupported: {}", intAttrName.getField());
+ }
+ } else if (intAttrName != null && intAttrName.getSchemaType() != null) {
+ switch (intAttrName.getSchemaType()) {
+ case PLAIN:
+ Optional<AttrTO> attr = userTO.getPlainAttr(intAttrName.getSchemaName());
+ if (attr.isPresent()) {
+ attr.get().getValues().clear();
+ } else {
+ attr = Optional.of(new AttrTO.Builder().schema(intAttrName.getSchemaName()).build());
+ userTO.getPlainAttrs().add(attr.get());
+ }
+ attr.get().getValues().addAll(values);
+ break;
+
+ default:
+ LOG.warn("Unsupported: {} {}", intAttrName.getSchemaType(), intAttrName.getSchemaName());
+ }
+ }
+ });
+ }
+
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public String create(final OIDCProvider op, final OIDCLoginResponseTO responseTO, final String email) {
+ UserTO userTO = new UserTO();
+
+ if (op.getUserTemplate() != null && op.getUserTemplate().get() != null) {
+ templateUtils.apply(userTO, op.getUserTemplate().get());
+ }
+
+ List<OIDCProviderActions> actions = getActions(op);
+ for (OIDCProviderActions action : actions) {
+ userTO = action.beforeCreate(userTO, responseTO);
+ }
+
+ fill(op, responseTO, userTO);
+
+ if (userTO.getRealm() == null) {
+ userTO.setRealm(SyncopeConstants.ROOT_REALM);
+ }
+ if (userTO.getUsername() == null) {
+ userTO.setUsername(email);
+ }
+
+ Pair<String, List<PropagationStatus>> created = provisioningManager.create(userTO, false, false);
+ userTO = binder.getUserTO(created.getKey());
+
+ for (OIDCProviderActions action : actions) {
+ userTO = action.afterCreate(userTO, responseTO);
+ }
+
+ return userTO.getUsername();
+ }
+
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public String update(final String username, final OIDCProvider op, final OIDCLoginResponseTO responseTO) {
+ UserTO userTO = binder.getUserTO(userDAO.findKey(username));
+ UserTO original = SerializationUtils.clone(userTO);
+
+ fill(op, responseTO, userTO);
+
+ UserPatch userPatch = AnyOperations.diff(userTO, original, true);
+
+ List<OIDCProviderActions> actions = getActions(op);
+ for (OIDCProviderActions action : actions) {
+ userPatch = action.beforeUpdate(userPatch, responseTO);
+ }
+
+ Pair<UserPatch, List<PropagationStatus>> updated = provisioningManager.update(userPatch, false);
+ userTO = binder.getUserTO(updated.getLeft().getKey());
+
+ for (OIDCProviderActions action : actions) {
+ userTO = action.afterUpdate(userTO, responseTO);
+ }
+
+ return userTO.getUsername();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/persistence-api/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/pom.xml b/ext/oidcclient/persistence-api/pom.xml
new file mode 100644
index 0000000..321602b
--- /dev/null
+++ b/ext/oidcclient/persistence-api/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 Persistence API</name>
+ <description>Apache Syncope Ext: OIDC Client Persistence API</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-persistence-api</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-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/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/OIDCProviderDAO.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/OIDCProviderDAO.java b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/OIDCProviderDAO.java
new file mode 100644
index 0000000..793e461
--- /dev/null
+++ b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/OIDCProviderDAO.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.persistence.api.dao;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+
+public interface OIDCProviderDAO {
+
+ OIDCProvider find(String key);
+
+ OIDCProvider findByName(String name);
+
+ List<OIDCProvider> findAll();
+
+ OIDCProvider save(final OIDCProvider op);
+
+ void delete(String key);
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCEntityFactory.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCEntityFactory.java b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCEntityFactory.java
new file mode 100644
index 0000000..489ce86
--- /dev/null
+++ b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCEntityFactory.java
@@ -0,0 +1,25 @@
+/*
+ * 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.api.entity;
+
+public interface OIDCEntityFactory {
+
+ <E extends Entity> E newEntity(Class<E> reference);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProvider.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProvider.java b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProvider.java
new file mode 100644
index 0000000..b0c7dee
--- /dev/null
+++ b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProvider.java
@@ -0,0 +1,85 @@
+/*
+ * 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.api.entity;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+
+public interface OIDCProvider extends Entity {
+
+ String getName();
+
+ void setName(String entityID);
+
+ String getClientID();
+
+ void setClientID(String clientId);
+
+ String getClientSecret();
+
+ void setClientSecret(String clientSecret);
+
+ String getAuthorizationEndpoint();
+
+ void setAuthorizationEndpoint(String authorizationEndpoint);
+
+ String getTokenEndpoint();
+
+ void setTokenEndpoint(String tokenEndpoint);
+
+ String getJwksUri();
+
+ void setJwksUri(String jwsUri);
+
+ String getIssuer();
+
+ void setIssuer(String issuer);
+
+ String getUserinfoEndpoint();
+
+ void setUserinfoEndpoint(String userinfoEndpoint);
+
+ boolean getHasDiscovery();
+
+ void setHasDiscovery(boolean hasDiscovery);
+
+ boolean isCreateUnmatching();
+
+ void setCreateUnmatching(boolean createUnmatching);
+
+ boolean isUpdateMatching();
+
+ void setUpdateMatching(boolean updateMatching);
+
+ OIDCUserTemplate getUserTemplate();
+
+ void setUserTemplate(OIDCUserTemplate userTemplate);
+
+ List<? extends OIDCProviderItem> getItems();
+
+ Optional<? extends OIDCProviderItem> getConnObjectKeyItem();
+
+ void setConnObjectKeyItem(OIDCProviderItem item);
+
+ boolean add(OIDCProviderItem item);
+
+ Set<String> getActionsClassNames();
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProviderItem.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProviderItem.java b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProviderItem.java
new file mode 100644
index 0000000..3047c88
--- /dev/null
+++ b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCProviderItem.java
@@ -0,0 +1,29 @@
+/*
+ * 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.api.entity;
+
+import org.apache.syncope.core.persistence.api.entity.resource.Item;
+
+public interface OIDCProviderItem extends Item {
+
+ OIDCProvider getOP();
+
+ void setOP(OIDCProvider op);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCUserTemplate.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCUserTemplate.java b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCUserTemplate.java
new file mode 100644
index 0000000..339f6ec
--- /dev/null
+++ b/ext/oidcclient/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/OIDCUserTemplate.java
@@ -0,0 +1,27 @@
+/*
+ * 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.api.entity;
+
+public interface OIDCUserTemplate extends AnyTemplate {
+
+ OIDCProvider getOP();
+
+ void setOP(OIDCProvider op);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/persistence-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-jpa/pom.xml b/ext/oidcclient/persistence-jpa/pom.xml
new file mode 100644
index 0000000..f642ef6
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/pom.xml
@@ -0,0 +1,134 @@
+<?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 Persistence JPA</name>
+ <description>Apache Syncope Ext: OIDC Client Persistence JPA</description>
+ <groupId>org.apache.syncope.ext.oidcclient</groupId>
+ <artifactId>syncope-ext-oidcclient-persistence-jpa</artifactId>
+ <packaging>jar</packaging>
+
+ <properties>
+ <rootpom.basedir>${basedir}/../../..</rootpom.basedir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.syncope.core</groupId>
+ <artifactId>syncope-core-persistence-jpa</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>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa-maven-plugin</artifactId>
+ <inherited>true</inherited>
+ <dependencies>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <version>${h2.version}</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <persistenceXmlFile>${rootpom.basedir}/core/persistence-jpa/src/main/resources/persistence-enhance.xml</persistenceXmlFile>
+ <includes>org/apache/syncope/core/persistence/jpa/entity/**/*.class</includes>
+ <connectionDriverName>org.springframework.jdbc.datasource.DriverManagerDataSource</connectionDriverName>
+ <connectionProperties>
+ driverClassName=org.h2.Driver,
+ url=jdbc:h2:mem:syncopedb
+ username=sa,
+ password=
+ </connectionProperties>
+ </configuration>
+ <executions>
+ <execution>
+ <id>enhancer</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>enhance</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ </plugins>
+
+ <testResources>
+ <testResource>
+ <directory>${rootpom.basedir}/core/persistence-jpa/src/main/resources</directory>
+ <filtering>true</filtering>
+ </testResource>
+ </testResources>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>sqlgen</id>
+
+ <properties>
+ <skipTests>true</skipTests>
+ </properties>
+
+ <build>
+ <defaultGoal>clean verify</defaultGoal>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.openjpa</groupId>
+ <artifactId>openjpa-maven-plugin</artifactId>
+ <inherited>true</inherited>
+ <executions>
+ <execution>
+ <id>sqlgenr</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>sql</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ </profile>
+ </profiles>
+
+</project>
http://git-wip-us.apache.org/repos/asf/syncope/blob/797fd1cb/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAOIDCProviderDAO.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAOIDCProviderDAO.java b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAOIDCProviderDAO.java
new file mode 100644
index 0000000..91e3af0
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAOIDCProviderDAO.java
@@ -0,0 +1,78 @@
+/*
+ * 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.dao;
+
+import java.util.List;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.core.persistence.api.dao.OIDCProviderDAO;
+import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
+import org.apache.syncope.core.persistence.jpa.entity.JPAOIDCProvider;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JPAOIDCProviderDAO extends AbstractDAO<OIDCProvider> implements OIDCProviderDAO {
+
+ @Transactional(readOnly = true)
+ @Override
+ public OIDCProvider find(final String key) {
+ return entityManager().find(JPAOIDCProvider.class, key);
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public OIDCProvider findByName(final String name) {
+ TypedQuery<OIDCProvider> query = entityManager().createQuery(
+ "SELECT e FROM " + JPAOIDCProvider.class.getSimpleName()
+ + " e WHERE e.name = :name", OIDCProvider.class);
+ query.setParameter("name", name);
+
+ OIDCProvider result = null;
+ try {
+ result = query.getSingleResult();
+ } catch (NoResultException e) {
+ LOG.debug("No OIDC Provider found with name {}", name, e);
+ }
+
+ return result;
+ }
+
+ @Transactional(readOnly = true)
+ @Override
+ public List<OIDCProvider> findAll() {
+ TypedQuery<OIDCProvider> query = entityManager().createQuery(
+ "SELECT e FROM " + JPAOIDCProvider.class.getSimpleName() + " e", OIDCProvider.class);
+ return query.getResultList();
+ }
+
+ @Override
+ public OIDCProvider save(final OIDCProvider op) {
+ return entityManager().merge(op);
+ }
+
+ @Override
+ public void delete(final String key) {
+ OIDCProvider op = find(key);
+ if (op != null) {
+ entityManager().remove(op);
+ }
+ }
+
+}
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/JPAOIDCEntityFactory.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCEntityFactory.java b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCEntityFactory.java
new file mode 100644
index 0000000..e5870bf
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCEntityFactory.java
@@ -0,0 +1,49 @@
+/*
+ * 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 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.springframework.stereotype.Component;
+
+@Component
+public class JPAOIDCEntityFactory implements OIDCEntityFactory {
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <E extends Entity> E newEntity(final Class<E> reference) {
+ E result;
+
+ if (reference.equals(OIDCProvider.class)) {
+ result = (E) new JPAOIDCProvider();
+ } else if (reference.equals(OIDCProviderItem.class)) {
+ result = (E) new JPAOIDCProviderItem();
+ } else if (reference.equals(OIDCUserTemplate.class)) {
+ result = (E) new JPAOIDCUserTemplate();
+ } else {
+ throw new IllegalArgumentException("Could not find a JPA implementation of " + reference.getName());
+ }
+
+ return result;
+ }
+
+}
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/JPAOIDCProvider.java
----------------------------------------------------------------------
diff --git a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProvider.java b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProvider.java
new file mode 100644
index 0000000..c32f91e
--- /dev/null
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProvider.java
@@ -0,0 +1,250 @@
+/*
+ * 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.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+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;
+
+@Entity
+@Table(name = JPAOIDCProvider.TABLE)
+@Cacheable
+public class JPAOIDCProvider extends AbstractGeneratedKeyEntity implements OIDCProvider {
+
+ public static final String TABLE = "OIDCProvider";
+
+ private static final long serialVersionUID = 1423093003585826403L;
+
+ @Column(unique = true, nullable = false)
+ private String name;
+
+ @Column(unique = true, nullable = false)
+ private String clientID;
+
+ @Column(unique = true, nullable = false)
+ private String clientSecret;
+
+ @Column(nullable = false)
+ private String authorizationEndpoint;
+
+ @Column(nullable = false)
+ private String tokenEndpoint;
+
+ @Column(nullable = false)
+ private String jwksUri;
+
+ @Column(nullable = false)
+ private String issuer;
+
+ @Column(nullable = false)
+ private String userinfoEndpoint;
+
+ @Column(nullable = false)
+ private boolean hasDiscovery;
+
+ @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "op")
+ private JPAOIDCUserTemplate userTemplate;
+
+ @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "op")
+ private List<JPAOIDCProviderItem> items = new ArrayList<>();
+
+ @Min(0)
+ @Max(1)
+ @Column(nullable = false)
+ private Integer createUnmatching;
+
+ @Min(0)
+ @Max(1)
+ @Column(nullable = false)
+ private Integer updateMatching;
+
+ @ElementCollection(fetch = FetchType.EAGER)
+ @Column(name = "actionClassName")
+ @CollectionTable(name = TABLE + "_actionsClassNames",
+ joinColumns =
+ @JoinColumn(name = "oidcOP_id", referencedColumnName = "id"))
+ private Set<String> actionsClassNames = new HashSet<>();
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getClientID() {
+ return clientID;
+ }
+
+ @Override
+ public void setClientID(final String clientID) {
+ this.clientID = clientID;
+ }
+
+ @Override
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ @Override
+ public void setClientSecret(final String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ @Override
+ public String getAuthorizationEndpoint() {
+ return authorizationEndpoint;
+ }
+
+ @Override
+ public void setAuthorizationEndpoint(final String authorizationEndpoint) {
+ this.authorizationEndpoint = authorizationEndpoint;
+ }
+
+ @Override
+ public String getTokenEndpoint() {
+ return tokenEndpoint;
+ }
+
+ @Override
+ public void setTokenEndpoint(final String tokenEndpoint) {
+ this.tokenEndpoint = tokenEndpoint;
+ }
+
+ @Override
+ public String getJwksUri() {
+ return jwksUri;
+ }
+
+ @Override
+ public void setJwksUri(final String jwksUri) {
+ this.jwksUri = jwksUri;
+ }
+
+ @Override
+ public String getIssuer() {
+ return issuer;
+ }
+
+ @Override
+ public void setIssuer(final String issuer) {
+ this.issuer = issuer;
+ }
+
+ @Override
+ public String getUserinfoEndpoint() {
+ return userinfoEndpoint;
+ }
+
+ @Override
+ public void setUserinfoEndpoint(final String userinfoEndpoint) {
+ this.userinfoEndpoint = userinfoEndpoint;
+ }
+
+ @Override
+ public boolean getHasDiscovery() {
+ return hasDiscovery;
+ }
+
+ @Override
+ public void setHasDiscovery(final boolean hasDiscovery) {
+ this.hasDiscovery = hasDiscovery;
+ }
+
+ @Override
+ public boolean isCreateUnmatching() {
+ return isBooleanAsInteger(createUnmatching);
+ }
+
+ @Override
+ public void setCreateUnmatching(final boolean createUnmatching) {
+ this.createUnmatching = getBooleanAsInteger(createUnmatching);
+ }
+
+ @Override
+ public boolean isUpdateMatching() {
+ return isBooleanAsInteger(updateMatching);
+ }
+
+ @Override
+ public void setUpdateMatching(final boolean updateMatching) {
+ this.updateMatching = getBooleanAsInteger(updateMatching);
+ }
+
+ @Override
+ public OIDCUserTemplate getUserTemplate() {
+ return userTemplate;
+ }
+
+ @Override
+ public void setUserTemplate(final OIDCUserTemplate userTemplate) {
+ checkType(userTemplate, JPAOIDCUserTemplate.class);
+ this.userTemplate = (JPAOIDCUserTemplate) userTemplate;
+ }
+
+ @Override
+ public boolean add(final OIDCProviderItem item) {
+ checkType(item, JPAOIDCProviderItem.class);
+ return items.contains((JPAOIDCProviderItem) item) || items.add((JPAOIDCProviderItem) item);
+ }
+
+ @Override
+ public List<? extends OIDCProviderItem> getItems() {
+ return items;
+ }
+
+ @Override
+ public Optional<? extends OIDCProviderItem> getConnObjectKeyItem() {
+ return getItems().stream().filter(item -> item.isConnObjectKey()).findFirst();
+ }
+
+ @Override
+ public void setConnObjectKeyItem(final OIDCProviderItem item) {
+ item.setConnObjectKey(true);
+ this.add(item);
+ }
+
+ @Override
+ public Set<String> getActionsClassNames() {
+ return actionsClassNames;
+ }
+
+}