http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/persistence-api/pom.xml
----------------------------------------------------------------------
diff --git a/ext/saml2sp/persistence-api/pom.xml 
b/ext/saml2sp/persistence-api/pom.xml
new file mode 100644
index 0000000..bd98b58
--- /dev/null
+++ b/ext/saml2sp/persistence-api/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-saml2sp</artifactId>
+    <version>2.0.3-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Extensions: SAML 2.0 SP Persistence API</name>
+  <description>Apache Syncope Extensions: SAML 2.0 SP Persistence 
API</description>
+  <groupId>org.apache.syncope.ext.saml2sp</groupId>
+  <artifactId>syncope-ext-saml2sp-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>
+  </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/d9079e13/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SAML2IdPDAO.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SAML2IdPDAO.java
 
b/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SAML2IdPDAO.java
new file mode 100644
index 0000000..234d653
--- /dev/null
+++ 
b/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SAML2IdPDAO.java
@@ -0,0 +1,36 @@
+/*
+ * 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.SAML2IdP;
+
+public interface SAML2IdPDAO extends DAO<SAML2IdP> {
+
+    SAML2IdP find(String key);
+
+    SAML2IdP findByEntityID(String entityID);
+
+    List<SAML2IdP> findAll();
+
+    SAML2IdP save(SAML2IdP idp);
+
+    void delete(String key);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2EntityFactory.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2EntityFactory.java
 
b/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2EntityFactory.java
new file mode 100644
index 0000000..991463c
--- /dev/null
+++ 
b/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2EntityFactory.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 SAML2EntityFactory {
+
+    <E extends Entity> E newEntity(Class<E> reference);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
 
b/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
new file mode 100644
index 0000000..d3372c2
--- /dev/null
+++ 
b/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
@@ -0,0 +1,46 @@
+/*
+ * 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 org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+
+public interface SAML2IdP extends Entity {
+
+    String getEntityID();
+
+    void setEntityID(String entityID);
+
+    byte[] getMetadata();
+
+    void setMetadata(byte[] metadata);
+
+    boolean isUseDeflateEncoding();
+
+    void setUseDeflateEncoding(boolean useDeflateEncoding);
+
+    MappingItem getConnObjectKeyItem();
+
+    void setConnObjectKeyItem(MappingItem item);
+
+    boolean add(MappingItem item);
+
+    List<? extends MappingItem> getMappingItems();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/persistence-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/ext/saml2sp/persistence-jpa/pom.xml 
b/ext/saml2sp/persistence-jpa/pom.xml
new file mode 100644
index 0000000..857ee01
--- /dev/null
+++ b/ext/saml2sp/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-saml2sp</artifactId>
+    <version>2.0.3-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Extensions: SAML 2.0 SP Persistence JPA</name>
+  <description>Apache Syncope Extensions: SAML 2.0 SP Persistence 
JPA</description>
+  <groupId>org.apache.syncope.ext.saml2sp</groupId>
+  <artifactId>syncope-ext-saml2sp-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.saml2sp</groupId>
+      <artifactId>syncope-ext-saml2sp-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/d9079e13/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASAML2IdPDAO.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASAML2IdPDAO.java
 
b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASAML2IdPDAO.java
new file mode 100644
index 0000000..ccf67b6
--- /dev/null
+++ 
b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASAML2IdPDAO.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.core.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.core.persistence.api.dao.SAML2IdPDAO;
+import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
+import org.apache.syncope.core.persistence.jpa.entity.JPASAML2IdP;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class JPASAML2IdPDAO extends AbstractDAO<SAML2IdP> implements 
SAML2IdPDAO {
+
+    @Transactional(readOnly = true)
+    @Override
+    public SAML2IdP find(final String key) {
+        return entityManager().find(JPASAML2IdP.class, key);
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public SAML2IdP findByEntityID(final String entityID) {
+        TypedQuery<SAML2IdP> query = entityManager().createQuery("SELECT e 
FROM " + JPASAML2IdP.class.getSimpleName()
+                + " e WHERE e.entityID = :entityID", SAML2IdP.class);
+        query.setParameter("entityID", entityID);
+
+        SAML2IdP result = null;
+        try {
+            result = query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No IdP found with entityID {}", entityID, e);
+        }
+
+        return result;
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public List<SAML2IdP> findAll() {
+        TypedQuery<SAML2IdP> query = entityManager().createQuery(
+                "SELECT e FROM " + JPASAML2IdP.class.getSimpleName() + " e", 
SAML2IdP.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public SAML2IdP save(final SAML2IdP idp) {
+        return entityManager().merge(idp);
+    }
+
+    @Override
+    public void delete(final String key) {
+        SAML2IdP idp = find(key);
+        if (idp != null) {
+            entityManager().remove(idp);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2EntityFactory.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2EntityFactory.java
 
b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2EntityFactory.java
new file mode 100644
index 0000000..d99d5d9
--- /dev/null
+++ 
b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2EntityFactory.java
@@ -0,0 +1,43 @@
+/*
+ * 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.SAML2EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
+import org.springframework.stereotype.Component;
+
+@Component
+public class JPASAML2EntityFactory implements SAML2EntityFactory {
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <E extends Entity> E newEntity(final Class<E> reference) {
+        E result;
+
+        if (reference.equals(SAML2IdP.class)) {
+            result = (E) new JPASAML2IdP();
+        } 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/d9079e13/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
 
b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
new file mode 100644
index 0000000..1b46051
--- /dev/null
+++ 
b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
@@ -0,0 +1,125 @@
+/*
+ * 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.Basic;
+import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Lob;
+import javax.persistence.OneToMany;
+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.commons.lang3.ArrayUtils;
+import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.persistence.jpa.entity.resource.JPAMappingItem;
+import org.apache.syncope.core.persistence.jpa.validation.entity.SAML2IdPCheck;
+
+@Entity
+@Table(name = JPASAML2IdP.TABLE)
+@Cacheable
+@SAML2IdPCheck
+public class JPASAML2IdP extends AbstractGeneratedKeyEntity implements 
SAML2IdP {
+
+    private static final long serialVersionUID = -392372595500355552L;
+
+    public static final String TABLE = "SAML2IdP";
+
+    @Column(nullable = false)
+    private String entityID;
+
+    @Lob
+    @Basic(fetch = FetchType.EAGER)
+    private Byte[] metadata;
+
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = 
FetchType.EAGER)
+    private List<JPAMappingItem> mappingItems = new ArrayList<>();
+
+    @Min(0)
+    @Max(1)
+    @Column(nullable = false)
+    private Integer useDeflateEncoding;
+
+    @Override
+    public String getEntityID() {
+        return entityID;
+    }
+
+    @Override
+    public void setEntityID(final String entityID) {
+        this.entityID = entityID;
+    }
+
+    @Override
+    public byte[] getMetadata() {
+        return metadata == null ? null : ArrayUtils.toPrimitive(metadata);
+    }
+
+    @Override
+    public void setMetadata(final byte[] metadata) {
+        this.metadata = metadata == null ? null : 
ArrayUtils.toObject(metadata);
+    }
+
+    @Override
+    public boolean isUseDeflateEncoding() {
+        return isBooleanAsInteger(useDeflateEncoding);
+    }
+
+    @Override
+    public void setUseDeflateEncoding(final boolean useDeflateEncoding) {
+        this.useDeflateEncoding = getBooleanAsInteger(useDeflateEncoding);
+    }
+
+    @Override
+    public boolean add(final MappingItem item) {
+        checkType(item, JPAMappingItem.class);
+        return mappingItems.contains((JPAMappingItem) item) || 
mappingItems.add((JPAMappingItem) item);
+    }
+
+    @Override
+    public List<? extends MappingItem> getMappingItems() {
+        return mappingItems;
+    }
+
+    @Override
+    public MappingItem getConnObjectKeyItem() {
+        return IterableUtils.find(getMappingItems(), new 
Predicate<MappingItem>() {
+
+            @Override
+            public boolean evaluate(final MappingItem item) {
+                return item.isConnObjectKey();
+            }
+        });
+    }
+
+    @Override
+    public void setConnObjectKeyItem(final MappingItem item) {
+        item.setConnObjectKey(true);
+        this.add(item);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPCheck.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPCheck.java
 
b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPCheck.java
new file mode 100644
index 0000000..2598ab1
--- /dev/null
+++ 
b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.validation.entity;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = SAML2IdPValidator.class)
+@Documented
+public @interface SAML2IdPCheck {
+
+    String message() default 
"{org.apache.syncope.core.persistence.validation.saml2idp}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
 
b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
new file mode 100644
index 0000000..3e5968c
--- /dev/null
+++ 
b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.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.core.persistence.jpa.validation.entity;
+
+import static 
org.apache.syncope.core.persistence.jpa.validation.entity.AbstractValidator.LOG;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
+
+public class SAML2IdPValidator extends AbstractValidator<SAML2IdPCheck, 
SAML2IdP> {
+
+    @Override
+    public boolean isValid(final SAML2IdP value, final 
ConstraintValidatorContext context) {
+        long connObjectKeys = 
IterableUtils.countMatches(value.getMappingItems(), new 
Predicate<MappingItem>() {
+
+            @Override
+            public boolean evaluate(final MappingItem item) {
+                return item.isConnObjectKey();
+            }
+        });
+        if (!value.getMappingItems().isEmpty() && connObjectKeys != 1) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidMapping, "Single 
ConnObjectKey mapping is required")).
+                    
addPropertyNode("connObjectKey.size").addConstraintViolation();
+            return false;
+        }
+
+        boolean isValid = true;
+
+        long passwords = IterableUtils.countMatches(value.getMappingItems(), 
new Predicate<MappingItem>() {
+
+            @Override
+            public boolean evaluate(final MappingItem item) {
+                return item.isPassword();
+            }
+        });
+        if (passwords > 0) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidMapping, "No 
password mapping is allowed")).
+                    addPropertyNode("password.size").addConstraintViolation();
+            isValid = false;
+        }
+
+        for (MappingItem item : value.getMappingItems()) {
+            for (String className : 
item.getMappingItemTransformerClassNames()) {
+                Class<?> actionsClass = null;
+                boolean isAssignable = false;
+                try {
+                    actionsClass = Class.forName(className);
+                    isAssignable = 
MappingItemTransformer.class.isAssignableFrom(actionsClass);
+                } catch (Exception e) {
+                    LOG.error("Invalid MappingItemTransformer specified: {}", 
className, e);
+                }
+
+                if (actionsClass == null || !isAssignable) {
+                    context.buildConstraintViolationWithTemplate(
+                            getTemplate(EntityViolationType.InvalidMapping,
+                                    "Invalid mapping item trasformer class 
name")).
+                            
addPropertyNode("mappingItemTransformerClassName").addConstraintViolation();
+                    isValid = false;
+                }
+            }
+        }
+
+        return isValid;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/pom.xml
----------------------------------------------------------------------
diff --git a/ext/saml2sp/pom.xml b/ext/saml2sp/pom.xml
new file mode 100644
index 0000000..dc0af30
--- /dev/null
+++ b/ext/saml2sp/pom.xml
@@ -0,0 +1,52 @@
+<?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.3-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Extensions: SAML 2.0 SP</name>
+  <description>Apache Syncope Extensions: SAML 2.0 SP</description>
+  <groupId>org.apache.syncope.ext</groupId>
+  <artifactId>syncope-ext-saml2sp</artifactId>
+  <packaging>pom</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../..</rootpom.basedir>
+  </properties>
+  
+  <modules>
+    <module>common-lib</module>
+    <module>persistence-api</module>
+    <module>persistence-jpa</module>
+    <module>provisioning-api</module>
+    <module>provisioning-java</module>
+    <module>rest-api</module>
+    <module>logic</module>
+    <module>rest-cxf</module>
+    <module>agent</module>
+  </modules>
+
+</project>

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/provisioning-api/pom.xml
----------------------------------------------------------------------
diff --git a/ext/saml2sp/provisioning-api/pom.xml 
b/ext/saml2sp/provisioning-api/pom.xml
new file mode 100644
index 0000000..e422189
--- /dev/null
+++ b/ext/saml2sp/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-saml2sp</artifactId>
+    <version>2.0.3-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Extensions: SAML 2.0 SP Provisioning API</name>
+  <description>Apache Syncope Extensions: SAML 2.0 SP Provisioning 
API</description>
+  <groupId>org.apache.syncope.ext.saml2sp</groupId>
+  <artifactId>syncope-ext-saml2sp-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.saml2sp</groupId>
+      <artifactId>syncope-ext-saml2sp-persistence-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.saml2sp</groupId>
+      <artifactId>syncope-ext-saml2sp-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/d9079e13/ext/saml2sp/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/SAML2IdPDataBinder.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/SAML2IdPDataBinder.java
 
b/ext/saml2sp/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/SAML2IdPDataBinder.java
new file mode 100644
index 0000000..4caec8f
--- /dev/null
+++ 
b/ext/saml2sp/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/SAML2IdPDataBinder.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.SAML2IdPTO;
+import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
+
+public interface SAML2IdPDataBinder {
+
+    SAML2IdPTO getIdPTO(SAML2IdP idp);
+
+    SAML2IdP create(SAML2IdPTO idpTO);
+
+    SAML2IdP update(SAML2IdP idp, SAML2IdPTO idpTO);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/provisioning-java/pom.xml
----------------------------------------------------------------------
diff --git a/ext/saml2sp/provisioning-java/pom.xml 
b/ext/saml2sp/provisioning-java/pom.xml
new file mode 100644
index 0000000..ac7bbac
--- /dev/null
+++ b/ext/saml2sp/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-saml2sp</artifactId>
+    <version>2.0.3-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Extensions: SAML 2.0 SP Provisioning Java</name>
+  <description>Apache Syncope Extensions: SAML 2.0 SP Provisioning 
Java</description>
+  <groupId>org.apache.syncope.ext.saml2sp</groupId>
+  <artifactId>syncope-ext-saml2sp-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.saml2sp</groupId>
+      <artifactId>syncope-ext-saml2sp-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/d9079e13/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
 
b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
new file mode 100644
index 0000000..2687e0b
--- /dev/null
+++ 
b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
@@ -0,0 +1,221 @@
+/*
+ * 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 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.MappingItemTO;
+import org.apache.syncope.common.lib.to.SAML2IdPTO;
+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.SAML2IdPDAO;
+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.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.SAML2EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
+import org.apache.syncope.core.provisioning.api.data.SAML2IdPDataBinder;
+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.identityconnectors.common.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SAML2IdPDataBinderImpl implements SAML2IdPDataBinder {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(SAML2IdPDataBinder.class);
+
+    private static final String[] MAPPINGITEM_IGNORE_PROPERTIES = { "key", 
"mapping", "purpose" };
+
+    @Autowired
+    private AnyTypeDAO anyTypeDAO;
+
+    @Autowired
+    private SAML2IdPDAO saml2IdPDAO;
+
+    @Autowired
+    private EntityFactory entityFactory;
+
+    @Autowired
+    private SAML2EntityFactory saml2EntityFactory;
+
+    @Autowired
+    private IntAttrNameParser intAttrNameParser;
+
+    @Override
+    public SAML2IdP create(final SAML2IdPTO idpTO) {
+        return update(saml2EntityFactory.newEntity(SAML2IdP.class), idpTO);
+    }
+
+    private void populateMapping(
+            final SAML2IdPTO idpTO,
+            final SAML2IdP idp,
+            final AnyTypeClassTO allowedSchemas) {
+
+        SyncopeClientCompositeException scce = 
SyncopeClientException.buildComposite();
+        SyncopeClientException invalidMapping = 
SyncopeClientException.build(ClientExceptionType.InvalidMapping);
+        SyncopeClientException requiredValuesMissing = 
SyncopeClientException.build(
+                ClientExceptionType.RequiredValuesMissing);
+
+        for (MappingItemTO itemTO : idpTO.getMappingItems()) {
+            if (itemTO == null) {
+                LOG.error("Null {}", MappingItemTO.class.getSimpleName());
+                invalidMapping.getElements().add("Null " + 
MappingItemTO.class.getSimpleName());
+            } else if (itemTO.getIntAttrName() == null) {
+                requiredValuesMissing.getElements().add("intAttrName");
+                scce.addException(requiredValuesMissing);
+            } else {
+                IntAttrName intAttrName = 
intAttrNameParser.parse(itemTO.getIntAttrName(), AnyTypeKind.USER);
+
+                if (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);
+                        }
+
+                        MappingItem item = 
entityFactory.newEntity(MappingItem.class);
+                        BeanUtils.copyProperties(itemTO, item, 
MAPPINGITEM_IGNORE_PROPERTIES);
+                        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");
+                            }
+
+                            idp.setConnObjectKeyItem(item);
+                        } else {
+                            idp.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 SAML2IdP update(final SAML2IdP idp, final SAML2IdPTO idpTO) {
+        idp.setEntityID(idpTO.getEntityID());
+        idp.setMetadata(Base64.decode(idpTO.getMetadata()));
+        idp.setUseDeflateEncoding(idpTO.isUseDeflateEncoding());
+
+        idp.getMappingItems().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()));
+        }
+        populateMapping(idpTO, idp, allowedSchemas);
+
+        return saml2IdPDAO.save(idp);
+    }
+
+    private void populateMappingTO(final SAML2IdP idp, final SAML2IdPTO idpTO) 
{
+        for (MappingItem item : idp.getMappingItems()) {
+            MappingItemTO itemTO = new MappingItemTO();
+            itemTO.setKey(item.getKey());
+            BeanUtils.copyProperties(item, itemTO, 
MAPPINGITEM_IGNORE_PROPERTIES);
+            itemTO.setPurpose(MappingPurpose.NONE);
+
+            if (itemTO.isConnObjectKey()) {
+                idpTO.setConnObjectKeyItem(itemTO);
+            } else {
+                idpTO.add(itemTO);
+            }
+        }
+    }
+
+    @Override
+    public SAML2IdPTO getIdPTO(final SAML2IdP idp) {
+        SAML2IdPTO idpTO = new SAML2IdPTO();
+
+        idpTO.setKey(idp.getKey());
+        idpTO.setEntityID(idp.getEntityID());
+        idpTO.setUseDeflateEncoding(idp.isUseDeflateEncoding());
+        idpTO.setMetadata(Base64.encode(idp.getMetadata()));
+
+        populateMappingTO(idp, idpTO);
+
+        return idpTO;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/rest-api/pom.xml
----------------------------------------------------------------------
diff --git a/ext/saml2sp/rest-api/pom.xml b/ext/saml2sp/rest-api/pom.xml
new file mode 100644
index 0000000..d7737f2
--- /dev/null
+++ b/ext/saml2sp/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-saml2sp</artifactId>
+    <version>2.0.3-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Extensions: SAML 2.0 SP REST API</name>
+  <description>Apache Syncope Extensions: SAML 2.0 SP REST API</description>
+  <groupId>org.apache.syncope.ext.saml2sp</groupId>
+  <artifactId>syncope-ext-saml2sp-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.saml2sp</groupId>
+      <artifactId>syncope-ext-saml2sp-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/d9079e13/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPService.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPService.java
 
b/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPService.java
new file mode 100644
index 0000000..5761c01
--- /dev/null
+++ 
b/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPService.java
@@ -0,0 +1,90 @@
+/*
+ * 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 java.io.InputStream;
+import java.util.List;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.SAML2IdPTO;
+
+/**
+ * REST operations for SAML 2.0 Identity Providers.
+ */
+@Path("saml2sp/identityProviders")
+public interface SAML2IdPService extends JAXRSService {
+
+    /**
+     * Returns a list of all defined SAML 2.0 Identity Providers.
+     *
+     * @return list of all defined SAML 2.0 Identity Providers
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    List<SAML2IdPTO> list();
+
+    /**
+     * Returns the SAML 2.0 Identity Provider with matching entityID, if 
available.
+     *
+     * @param key SAML 2.0 Identity Provider's entityID
+     * @return SAML 2.0 Identity Provider with matching entityID, if available
+     */
+    @GET
+    @Path("{key}")
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    SAML2IdPTO read(@PathParam("key") String key);
+
+    /**
+     * Imports the SAML 2.0 Identity Provider definitions available in the 
provided XML metadata.
+     *
+     * @param input XML metadata
+     * @return the entityID values for all imported SAML 2.0 Identity Providers
+     */
+    @POST
+    @Consumes({ MediaType.APPLICATION_XML })
+    Response importFromMetadata(@NotNull InputStream input);
+
+    /**
+     * Updates the SAML 2.0 Identity Provider with matching entityID.
+     *
+     * @param saml2IdpTO idp configuration to be stored
+     */
+    @PUT
+    @Path("{key}")
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    void update(@NotNull SAML2IdPTO saml2IdpTO);
+
+    /**
+     * Deletes the SAML 2.0 Identity Provider with matching entityID.
+     *
+     * @param key SAML 2.0 Identity Provider's entityID
+     */
+    @DELETE
+    @Path("{key}")
+    void delete(@PathParam("key") String key);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2SPService.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2SPService.java
 
b/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2SPService.java
new file mode 100644
index 0000000..f9c2cf4
--- /dev/null
+++ 
b/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2SPService.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.rest.api.service;
+
+import java.io.InputStream;
+import javax.ws.rs.GET;
+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 javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.SAML2RequestTO;
+import org.apache.syncope.common.lib.to.SAML2LoginResponseTO;
+
+/**
+ * REST operations for the provided SAML 2.0 Service Provider.
+ */
+@Path("saml2sp/serviceProvider")
+public interface SAML2SPService extends JAXRSService {
+
+    /**
+     * Returns the XML metadata for the provided SAML 2.0 Service Provider.
+     *
+     * @param spEntityID SAML 2.0 SP entity ID.
+     * @return XML metadata for the provided SAML 2.0 Service Provider
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_XML })
+    Response getMetadata(@QueryParam("spEntityID") String spEntityID);
+
+    /**
+     * Generates SAML 2.0 authentication request for the IdP matching the 
provided entity ID.
+     *
+     * @param spEntityID SAML 2.0 SP entity ID.
+     * @param idpEntityID SAML 2.0 IdP entity ID.
+     * @return SAML 2.0 authentication request
+     */
+    @POST
+    @Path("loginRequest")
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    SAML2RequestTO createLoginRequest(
+            @QueryParam("spEntityID") String spEntityID,
+            @QueryParam("idpEntityID") String idpEntityID);
+
+    /**
+     * Validates the received SAML 2.0 authentication response and creates JWT 
for the matching user, if found.
+     *
+     * @param response SAML 2.0 authentication response
+     * @return JWT for the matching user plus attributes returned in the 
response
+     */
+    @POST
+    @Path("loginResponse")
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    SAML2LoginResponseTO validateLoginResponse(InputStream response);
+
+    /**
+     * Generates SAML 2.0 logout request for the IdP matching the requesting 
access token.
+     *
+     * @param spEntityID SAML 2.0 SP entity ID.
+     * @return SAML 2.0 logout request
+     */
+    @POST
+    @Path("logoutRequest")
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    SAML2RequestTO createLogoutRequest(@QueryParam("spEntityID") String 
spEntityID);
+
+    /**
+     * Validates the received SAML 2.0 logout response.
+     *
+     * @param response SAML 2.0 logout response
+     */
+    @POST
+    @Path("logoutResponse")
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    void validateLogoutResponse(InputStream response);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/rest-cxf/pom.xml
----------------------------------------------------------------------
diff --git a/ext/saml2sp/rest-cxf/pom.xml b/ext/saml2sp/rest-cxf/pom.xml
new file mode 100644
index 0000000..60959a3
--- /dev/null
+++ b/ext/saml2sp/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-saml2sp</artifactId>
+    <version>2.0.3-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Extensions: SAML 2.0 SP REST CXF</name>
+  <description>Apache Syncope Extensions: SAML 2.0 SP REST CXF</description>
+  <groupId>org.apache.syncope.ext.saml2sp</groupId>
+  <artifactId>syncope-ext-saml2sp-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.saml2sp</groupId>
+      <artifactId>syncope-ext-saml2sp-rest-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.saml2sp</groupId>
+      <artifactId>syncope-ext-saml2sp-rest-api</artifactId>
+      <version>${project.version}</version>
+      <classifier>javadoc</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.syncope.ext.saml2sp</groupId>
+      <artifactId>syncope-ext-saml2sp-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/d9079e13/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPServiceImpl.java
 
b/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPServiceImpl.java
new file mode 100644
index 0000000..1f2790f
--- /dev/null
+++ 
b/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPServiceImpl.java
@@ -0,0 +1,67 @@
+/*
+ * 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.io.InputStream;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.SAML2IdPTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.SAML2IdPService;
+import org.apache.syncope.core.logic.SAML2IdPLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SAML2IdPServiceImpl extends AbstractServiceImpl implements 
SAML2IdPService {
+
+    @Autowired
+    private SAML2IdPLogic logic;
+
+    @Override
+    public List<SAML2IdPTO> list() {
+        return logic.list();
+    }
+
+    @Override
+    public SAML2IdPTO read(final String key) {
+        return logic.read(key);
+    }
+
+    @Override
+    public Response importFromMetadata(final InputStream input) {
+        List<String> imported = logic.importFromMetadata(input);
+        if (imported.isEmpty()) {
+            return Response.ok().build();
+        } else {
+            return Response.ok().header(RESTHeaders.RESOURCE_KEY, 
imported).build();
+        }
+    }
+
+    @Override
+    public void update(final SAML2IdPTO saml2IdpTO) {
+        logic.update(saml2IdpTO);
+    }
+
+    @Override
+    public void delete(final String key) {
+        logic.delete(key);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2SPServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2SPServiceImpl.java
 
b/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2SPServiceImpl.java
new file mode 100644
index 0000000..d9d3dc6
--- /dev/null
+++ 
b/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2SPServiceImpl.java
@@ -0,0 +1,82 @@
+/*
+ * 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.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.SAML2RequestTO;
+import org.apache.syncope.common.lib.to.SAML2LoginResponseTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.SAML2SPService;
+import org.apache.syncope.core.logic.SAML2SPLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SAML2SPServiceImpl extends AbstractServiceImpl implements 
SAML2SPService {
+
+    @Autowired
+    private SAML2SPLogic logic;
+
+    @Override
+    public Response getMetadata(final String spEntityID) {
+        StreamingOutput sout = new StreamingOutput() {
+
+            @Override
+            public void write(final OutputStream os) throws IOException {
+                logic.getMetadata(StringUtils.appendIfMissing(spEntityID, 
"/"), os);
+            }
+        };
+        return Response.ok(sout).
+                type(MediaType.APPLICATION_XML).
+                build();
+    }
+
+    @Override
+    public SAML2RequestTO createLoginRequest(
+            final String spEntityID, final String idpEntityID) {
+
+        return 
logic.createLoginRequest(StringUtils.appendIfMissing(spEntityID, "/"), 
idpEntityID);
+    }
+
+    @Override
+    public SAML2LoginResponseTO validateLoginResponse(final InputStream 
response) {
+        return logic.validateLoginResponse(response);
+    }
+
+    @Override
+    public SAML2RequestTO createLogoutRequest(final String spEntityID) {
+        return logic.createLogoutRequest(
+                
messageContext.getHttpHeaders().getHeaderString(RESTHeaders.TOKEN),
+                StringUtils.appendIfMissing(spEntityID, "/"));
+    }
+
+    @Override
+    public void validateLogoutResponse(final InputStream response) {
+        logic.validateLogoutResponse(
+                
messageContext.getHttpHeaders().getHeaderString(RESTHeaders.TOKEN),
+                response);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/fit/console-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/pom.xml b/fit/console-reference/pom.xml
index 8115369..2d589d9 100644
--- a/fit/console-reference/pom.xml
+++ b/fit/console-reference/pom.xml
@@ -63,6 +63,12 @@ under the License.
     </dependency>
     
     <dependency>
+      <groupId>org.apache.syncope.ext.saml2sp</groupId>
+      <artifactId>syncope-ext-saml2sp-agent</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/d9079e13/fit/console-reference/src/main/resources/saml2sp-agent.properties
----------------------------------------------------------------------
diff --git a/fit/console-reference/src/main/resources/saml2sp-agent.properties 
b/fit/console-reference/src/main/resources/saml2sp-agent.properties
new file mode 100644
index 0000000..1d53d49
--- /dev/null
+++ b/fit/console-reference/src/main/resources/saml2sp-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/d9079e13/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 9d5bc81..022ee5d 100644
--- a/fit/console-reference/src/test/resources/rebel.xml
+++ b/fit/console-reference/src/test/resources/rebel.xml
@@ -28,6 +28,8 @@ under the License.
     </dir>
     <dir name="${basedir}/../../ext/camel/client-console/target/classes">
     </dir>
+    <dir name="${basedir}/../../ext/saml2sp/agent/target/classes">
+    </dir>
   </classpath>
 
   <web>

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/fit/core-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml
index 9b9ad4c..5daa5a8 100644
--- a/fit/core-reference/pom.xml
+++ b/fit/core-reference/pom.xml
@@ -345,6 +345,16 @@ under the License.
       <testResource>
         <directory>src/test/resources</directory>
         <filtering>true</filtering>
+       <excludes>
+         <exclude>keystore</exclude>
+       </excludes>
+      </testResource>
+      <testResource>
+        <directory>src/test/resources</directory>
+        <filtering>false</filtering>
+       <includes>
+         <include>keystore</include>
+       </includes>
       </testResource>
       <testResource>
         
<directory>${basedir}/../../core/rest-cxf/src/main/resources</directory>
@@ -974,6 +984,17 @@ under the License.
         </dependency>
         
         <dependency>
+          <groupId>org.apache.syncope.ext.saml2sp</groupId>
+          <artifactId>syncope-ext-saml2sp-rest-cxf</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.syncope.ext.saml2sp</groupId>
+          <artifactId>syncope-ext-saml2sp-persistence-jpa</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+        
+        <dependency>
           <groupId>org.apache.syncope.ext</groupId>
           <artifactId>syncope-ext-swagger-ui</artifactId>
           <version>${project.version}</version>

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/fit/core-reference/src/main/resources/all/saml2sp-logic.properties
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/all/saml2sp-logic.properties 
b/fit/core-reference/src/main/resources/all/saml2sp-logic.properties
new file mode 100644
index 0000000..2d7e918
--- /dev/null
+++ b/fit/core-reference/src/main/resources/all/saml2sp-logic.properties
@@ -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.
+conf.directory=${conf.directory}
+
+keystore.name=keystore
+keystore.type=jks
+keystore.storepass=changeit
+keystore.keypass=changeit
+sp.cert.alias=sp

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/fit/core-reference/src/main/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/log4j2.xml 
b/fit/core-reference/src/main/resources/log4j2.xml
index 9b58bc5..bc4771c 100644
--- a/fit/core-reference/src/main/resources/log4j2.xml
+++ b/fit/core-reference/src/main/resources/log4j2.xml
@@ -148,10 +148,26 @@ under the License.
       <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
+    <asyncLogger name="org.apache.wss4j" additivity="false" level="ERROR">
+      <appender-ref ref="mainFile"/>
+      <appender-ref ref="main"/>
+    </asyncLogger>
+    <asyncLogger name="org.apache.xml" additivity="false" level="ERROR">
+      <appender-ref ref="mainFile"/>
+      <appender-ref ref="main"/>
+    </asyncLogger>
+    <asyncLogger name="org.opensaml" additivity="false" level="ERROR">
+      <appender-ref ref="mainFile"/>
+      <appender-ref ref="main"/>
+    </asyncLogger>
     <asyncLogger name="io.swagger" additivity="false" level="ERROR">
       <appender-ref ref="mainFile"/>
       <appender-ref ref="main"/>
     </asyncLogger>
+    <asyncLogger name="org.reflections" additivity="false" level="ERROR">
+      <appender-ref ref="mainFile"/>
+      <appender-ref ref="main"/>
+    </asyncLogger>
     
     <root level="INFO">
       <appender-ref ref="mainFile"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/fit/core-reference/src/test/resources/keystore
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/keystore 
b/fit/core-reference/src/test/resources/keystore
new file mode 100644
index 0000000..8c3f670
Binary files /dev/null and b/fit/core-reference/src/test/resources/keystore 
differ

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/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 06e50e0..e5bb258 100644
--- a/fit/core-reference/src/test/resources/rebel.xml
+++ b/fit/core-reference/src/test/resources/rebel.xml
@@ -65,6 +65,23 @@ under the License.
     <dir name="${basedir}/../../ext/camel/provisioning-camel/target/classes">
       <exclude name="provisioningCamelContext.xml"/>
     </dir>
+    <dir name="${basedir}/../../ext/saml2sp/common-lib/target/classes">
+    </dir>
+    <dir name="${basedir}/../../ext/saml2sp/logic/target/classes">
+    </dir>
+    <dir name="${basedir}/../../ext/saml2sp/persistence-api/target/classes">
+    </dir>
+    <dir name="${basedir}/../../ext/saml2sp/persistence-jpa/target/classes">
+      <exclude name="org/apache/syncope/core/persistence/jpa/entity/**"/>
+    </dir>
+    <dir name="${basedir}/../../ext/saml2sp/provisioning-api/target/classes">
+    </dir>
+    <dir name="${basedir}/../../ext/saml2sp/provisioning-java/target/classes">
+    </dir>
+    <dir name="${basedir}/../../ext/saml2sp/rest-api/target/classes">
+    </dir>
+    <dir name="${basedir}/../../ext/saml2sp/rest-cxf/target/classes">
+    </dir>
   </classpath>
 
   <web>

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index b128970..254c8e1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -381,6 +381,8 @@ under the License.
     <camel.version>2.17.6</camel.version>      
 
     <slf4j.version>1.7.25</slf4j.version>
+    <opensaml.version>3.2.0</opensaml.version>
+
     <log4j.version>2.8.1</log4j.version>
     <disruptor.version>3.3.6</disruptor.version>
 
@@ -569,6 +571,40 @@ under the License.
         <artifactId>cxf-rt-rs-client</artifactId>
         <version>${cxf.version}</version>
       </dependency>
+      <dependency>
+       <groupId>org.apache.cxf</groupId>
+       <artifactId>cxf-rt-rs-security-sso-saml</artifactId>
+       <version>${cxf.version}</version>
+       <exclusions>
+          <exclusion>
+            <groupId>org.opensaml</groupId>
+            <artifactId>opensaml-xacml-impl</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.opensaml</groupId>
+            <artifactId>opensaml-xacml-saml-impl</artifactId>
+          </exclusion>
+         <exclusion>
+            <groupId>org.apache.wss4j</groupId>
+            <artifactId>wss4j-ws-security-dom</artifactId>
+         </exclusion>
+       </exclusions>
+      </dependency>
+      <dependency>
+       <groupId>org.apache.wss4j</groupId>
+        <artifactId>wss4j-ws-security-dom</artifactId>
+       <version>2.1.9-SNAPSHOT</version>
+       <exclusions>
+         <exclusion>
+           <groupId>org.jasypt</groupId>
+           <artifactId>jasypt</artifactId>
+         </exclusion>
+          <exclusion>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-javamail_1.4_spec</artifactId>
+          </exclusion>
+       </exclusions>
+      </dependency>
       <!-- /CXF -->
 
       <!-- Swagger -->      
@@ -637,6 +673,40 @@ under the License.
       </dependency>
       <!-- /Camel -->
       
+      <!-- OpenSAML -->
+      <dependency>
+        <groupId>org.opensaml</groupId>
+        <artifactId>opensaml-saml-impl</artifactId>
+        <version>${opensaml.version}</version>
+        <exclusions>
+          <exclusion>
+            <groupId>org.opensaml</groupId>
+            <artifactId>opensaml-soap-impl</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.opensaml</groupId>
+            <artifactId>opensaml-storage-api</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.opensaml</groupId>
+            <artifactId>opensaml-messaging-api</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.apache.velocity</groupId>
+            <artifactId>velocity</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+          </exclusion>
+          <exclusion>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <!-- /OpenSAML -->
+          
       <dependency>
         <groupId>org.apache.openjpa</groupId>
         <artifactId>openjpa-jdbc</artifactId>

http://git-wip-us.apache.org/repos/asf/syncope/blob/d9079e13/standalone/pom.xml
----------------------------------------------------------------------
diff --git a/standalone/pom.xml b/standalone/pom.xml
index b9fecf7..93af0f3 100644
--- a/standalone/pom.xml
+++ b/standalone/pom.xml
@@ -142,6 +142,8 @@ under the License.
                 <copy 
todir="${work.dir}/apache-tomcat-${tomcat.version}/webapps/syncope/WEB-INF/classes"
 overwrite="true">
                   <fileset dir="${project.build.outputDirectory}/core" />
                 </copy>
+                <copy file="../fit/core-reference/target/test-classes/keystore"
+                      
todir="${work.dir}/apache-tomcat-${tomcat.version}/webapps/syncope/WEB-INF/classes"
 overwrite="true"/>
 
                 <!-- Syncope console -->
                 <copy 
todir="${work.dir}/apache-tomcat-${tomcat.version}/webapps/syncope-console">

Reply via email to