You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by md...@apache.org on 2015/08/14 10:30:33 UTC

[04/31] syncope git commit: [SYNCOPE-652] Preliminary work (still struggling with OpenJPA slices)

[SYNCOPE-652] Preliminary work (still struggling with OpenJPA slices)


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/252b1510
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/252b1510
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/252b1510

Branch: refs/heads/SYNCOPE-156
Commit: 252b1510dcced12abca84c14c77288cf48d9d32e
Parents: ba7f1a5
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Fri Jul 17 12:05:06 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Aug 13 17:16:50 2015 +0200

----------------------------------------------------------------------
 .travis.yml                                     |   3 +-
 .../client/lib/SyncopeClientFactoryBean.java    |  32 +++--
 .../syncope/common/lib/SyncopeConstants.java    |   2 +
 .../syncope/common/lib/jaxb/package-info.java   |  23 ++++
 .../apache/syncope/common/lib/to/DomainTO.java  |  62 +++++++++
 .../syncope/common/lib/types/Entitlement.java   |  10 ++
 .../syncope/common/rest/api/RESTHeaders.java    |   2 +
 .../common/rest/api/service/DomainService.java  |  96 +++++++++++++
 .../syncope/core/logic/AbstractLogic.java       |   3 -
 .../syncope/core/logic/AnyTypeClassLogic.java   |  36 ++---
 .../apache/syncope/core/logic/AnyTypeLogic.java |   2 +-
 .../apache/syncope/core/logic/DomainLogic.java  | 136 +++++++++++++++++++
 .../apache/syncope/core/logic/GroupLogic.java   |   2 +-
 core/misc/pom.xml                               |   7 +-
 .../core/misc/security/AuthContextUtils.java    |  23 +++-
 .../security/SyncopeAuthenticationDetails.java  |  86 ++++++++++++
 .../SyncopeAuthenticationDetailsSource.java     |  32 +++++
 .../security/SyncopeAuthenticationProvider.java |  51 ++++---
 .../misc/src/main/resources/securityContext.xml |   5 +-
 .../syncope/core/persistence/api/dao/DAO.java   |   2 +
 .../core/persistence/api/dao/DomainDAO.java     |  33 +++++
 .../core/persistence/api/entity/Domain.java     |  32 +++++
 core/persistence-jpa/pom.xml                    |  11 +-
 .../core/persistence/jpa/dao/AbstractDAO.java   |  12 ++
 .../persistence/jpa/dao/JPAAnySearchDAO.java    |   9 +-
 .../core/persistence/jpa/dao/JPADomainDAO.java  |  57 ++++++++
 .../core/persistence/jpa/dao/JPAUserDAO.java    |   4 +-
 .../jpa/entity/AnnotatedEntityListener.java     |   2 +-
 .../core/persistence/jpa/entity/JPADomain.java  |  79 +++++++++++
 .../jpa/entity/JPAEntityFactory.java            |   5 +-
 .../jpa/slice/DomainDistributionPolicy.java     |  36 +++++
 .../jpa/slice/DomainFinderTargetPolicy.java     |  38 ++++++
 .../jpa/slice/DomainQueryTargetPolicy.java      |  41 ++++++
 .../jpa/validation/entity/DomainCheck.java      |  41 ++++++
 .../jpa/validation/entity/DomainValidator.java  |  42 ++++++
 .../src/main/resources/persistence.properties   |   4 +-
 .../resources/persistenceContextEMFactory.xml   |  32 ++++-
 .../core/persistence/jpa/inner/UserTest.java    |  16 +--
 .../src/test/resources/persistence.properties   |   4 +-
 .../provisioning/api/data/DomainDataBinder.java |  31 +++++
 core/provisioning-java/pom.xml                  |   6 +
 .../java/data/DomainDataBinderImpl.java         |  70 ++++++++++
 .../java/data/UserDataBinderImpl.java           |   8 +-
 .../java/sync/AbstractProvisioningJob.java      |  22 +--
 .../syncope/core/rest/cxf/AddDomainFilter.java  |  39 ++++++
 .../syncope/core/rest/cxf/AddETagFilter.java    |  48 +++++++
 .../core/rest/cxf/service/AddETagFilter.java    |  50 -------
 .../rest/cxf/service/DomainServiceImpl.java     |  66 +++++++++
 .../src/main/resources/restCXFContext.xml       |   6 +-
 .../activiti/ActivitiUserWorkflowAdapter.java   |  10 +-
 fit/core-reference/pom.xml                      |   2 +-
 pom.xml                                         |   9 +-
 52 files changed, 1326 insertions(+), 154 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 0e6f5c4..e17fd2c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,6 +19,7 @@ jdk:
 # default install is mvn install --quiet -DskipTests=true
 install: mvn --show-version --quiet -P all,skipTests
 #invoker.streamLogs: we cannot access to log files through Travis web ui, so display everything in the console
-script: mvn --show-version --quiet clean install -Dinvoker.streamLogs=true
+#script: mvn --show-version --quiet clean install -Dinvoker.streamLogs=true
+script: mvn --show-version --quiet -PskipTests -Dinvoker.streamLogs=true
 notifications:
   webhooks: http://rovere.tirasa.net/cgi-bin/travis.cgi

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
----------------------------------------------------------------------
diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
index 24923f1..a3a271c 100644
--- a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.lib;
 
 import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -31,6 +32,7 @@ import org.apache.cxf.feature.LoggingFeature;
 import org.apache.cxf.jaxrs.provider.JAXBElementProvider;
 import org.apache.cxf.staxutils.DocumentDepthProperties;
 import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
 
 /**
  * Factory bean for creating instances of {@link SyncopeClient}.
@@ -62,8 +64,7 @@ public class SyncopeClientFactoryBean {
 
     private JacksonJaxbJsonProvider jsonProvider;
 
-    @SuppressWarnings("rawtypes")
-    private JAXBElementProvider jaxbProvider;
+    private JAXBElementProvider<?> jaxbProvider;
 
     private RestClientExceptionMapper exceptionMapper;
 
@@ -71,21 +72,23 @@ public class SyncopeClientFactoryBean {
 
     private ContentType contentType;
 
+    private String domain;
+
     private RestClientFactoryBean restClientFactoryBean;
 
     protected JacksonJaxbJsonProvider defaultJsonProvider() {
         return new JacksonJaxbJsonProvider();
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    protected JAXBElementProvider defaultJAXBProvider() {
-        JAXBElementProvider defaultJAXBProvider = new JAXBElementProvider();
+    @SuppressWarnings({ "rawtypes" })
+    protected JAXBElementProvider<?> defaultJAXBProvider() {
+        JAXBElementProvider<?> defaultJAXBProvider = new JAXBElementProvider();
 
         DocumentDepthProperties depthProperties = new DocumentDepthProperties();
         depthProperties.setInnerElementCountThreshold(500);
         defaultJAXBProvider.setDepthProperties(depthProperties);
 
-        Map marshallerProperties = new HashMap();
+        Map<String, Object> marshallerProperties = new HashMap<>();
         marshallerProperties.put(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
         defaultJAXBProvider.setMarshallerProperties(marshallerProperties);
 
@@ -108,6 +111,10 @@ public class SyncopeClientFactoryBean {
         }
         defaultRestClientFactoryBean.setAddress(address);
 
+        if (StringUtils.isNotBlank(domain)) {
+            defaultRestClientFactoryBean.setHeaders(Collections.singletonMap(RESTHeaders.DOMAIN, domain));
+        }
+
         defaultRestClientFactoryBean.setThreadSafe(true);
         defaultRestClientFactoryBean.setInheritHeaders(true);
 
@@ -134,13 +141,13 @@ public class SyncopeClientFactoryBean {
         this.jsonProvider = jsonProvider;
     }
 
-    public JAXBElementProvider getJaxbProvider() {
+    public JAXBElementProvider<?> getJaxbProvider() {
         return jaxbProvider == null
                 ? defaultJAXBProvider()
                 : jaxbProvider;
     }
 
-    public SyncopeClientFactoryBean setJaxbProvider(final JAXBElementProvider jaxbProvider) {
+    public SyncopeClientFactoryBean setJaxbProvider(final JAXBElementProvider<?> jaxbProvider) {
         this.jaxbProvider = jaxbProvider;
         return this;
     }
@@ -181,6 +188,15 @@ public class SyncopeClientFactoryBean {
         return this;
     }
 
+    public String getDomain() {
+        return domain;
+    }
+
+    public SyncopeClientFactoryBean setDomain(final String domain) {
+        this.domain = domain;
+        return this;
+    }
+
     public RestClientFactoryBean getRestClientFactoryBean() {
         return restClientFactoryBean == null
                 ? defaultRestClientFactoryBean()

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
index 6538ec0..dbce5de 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java
@@ -27,6 +27,8 @@ public final class SyncopeConstants {
 
     public static final String NAMESPACE = "http://syncope.apache.org/2.0";
 
+    public static final String MASTER_DOMAIN = "Master";
+
     public static final String ROOT_REALM = "/";
 
     public static final Set<String> FULL_ADMIN_REALMS = Collections.singleton("/");

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/package-info.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/package-info.java b/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/package-info.java
new file mode 100644
index 0000000..a04b95d
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/package-info.java
@@ -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.
+ */
+@XmlSchema(namespace = SyncopeConstants.NAMESPACE)
+package org.apache.syncope.common.lib.jaxb;
+
+import javax.xml.bind.annotation.XmlSchema;
+import org.apache.syncope.common.lib.SyncopeConstants;

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/common/lib/src/main/java/org/apache/syncope/common/lib/to/DomainTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/DomainTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/DomainTO.java
new file mode 100644
index 0000000..3f05e19
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/DomainTO.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+
+@XmlRootElement(name = "domain")
+@XmlType
+public class DomainTO extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -7938075259986084934L;
+
+    private String key;
+
+    private String adminPwd;
+
+    private CipherAlgorithm adminCipherAlgorithm;
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(final String key) {
+        this.key = key;
+    }
+
+    public String getAdminPwd() {
+        return adminPwd;
+    }
+
+    public void setAdminPwd(final String adminPwd) {
+        this.adminPwd = adminPwd;
+    }
+
+    public CipherAlgorithm getAdminCipherAlgorithm() {
+        return adminCipherAlgorithm;
+    }
+
+    public void setAdminCipherAlgorithm(final CipherAlgorithm adminCipherAlgorithm) {
+        this.adminCipherAlgorithm = adminCipherAlgorithm;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
index 806aaa4..85befc6 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
@@ -28,6 +28,16 @@ public final class Entitlement {
 
     public static final String ANONYMOUS = "ANONYMOUS";
 
+    public static final String DOMAIN_LIST = "DOMAIN_LIST";
+
+    public static final String DOMAIN_CREATE = "DOMAIN_CREATE";
+
+    public static final String DOMAIN_READ = "DOMAIN_READ";
+
+    public static final String DOMAIN_UPDATE = "DOMAIN_UPDATE";
+
+    public static final String DOMAIN_DELETE = "DOMAIN_DELETE";
+
     public static final String REALM_LIST = "REALM_LIST";
 
     public static final String REALM_CREATE = "REALM_CREATE";

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/RESTHeaders.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/RESTHeaders.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/RESTHeaders.java
index 4d19e31..13b30df 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/RESTHeaders.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/RESTHeaders.java
@@ -23,6 +23,8 @@ package org.apache.syncope.common.rest.api;
  */
 public final class RESTHeaders {
 
+    public static final String DOMAIN = "X-Syncope-Domain";
+
     public static final String USER_KEY = "X-Syncope-User-Key";
 
     public static final String USERNAME = "X-Syncope-Username";

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/DomainService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/DomainService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/DomainService.java
new file mode 100644
index 0000000..4076dc1
--- /dev/null
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/DomainService.java
@@ -0,0 +1,96 @@
+/*
+ * 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.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.cxf.jaxrs.model.wadl.Description;
+import org.apache.cxf.jaxrs.model.wadl.Descriptions;
+import org.apache.cxf.jaxrs.model.wadl.DocTarget;
+import org.apache.syncope.common.lib.to.DomainTO;
+
+/**
+ * REST operations for domains.
+ */
+@Path("domains")
+public interface DomainService extends JAXRSService {
+
+    /**
+     * Returns a list of all domains.
+     *
+     * @return list of all domains.
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    List<DomainTO> list();
+
+    /**
+     * Returns domain with matching key.
+     *
+     * @param key domain key to be read
+     * @return domain with matching key
+     */
+    @GET
+    @Path("{key}")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    DomainTO read(@NotNull @PathParam("key") String key);
+
+    /**
+     * Creates a new domain.
+     *
+     * @param domainTO domain to be created
+     * @return <tt>Response</tt> object featuring <tt>Location</tt> header of created domain
+     */
+    @Descriptions({
+        @Description(target = DocTarget.RESPONSE,
+                value = "Featuring <tt>Location</tt> header of created domain")
+    })
+    @POST
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    Response create(@NotNull DomainTO domainTO);
+
+    /**
+     * Updates the domain matching the provided key.
+     *
+     * @param domainTO domain to be stored
+     */
+    @PUT
+    @Path("{key}")
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    void update(@NotNull DomainTO domainTO);
+
+    /**
+     * Deletes the domain matching the provided key.
+     *
+     * @param key domain key to be deleted
+     */
+    @DELETE
+    @Path("{key}")
+    void delete(@NotNull @PathParam("key") String key);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java
index 35e806a..6aa375c 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java
@@ -31,9 +31,6 @@ import org.springframework.transaction.annotation.Transactional;
  */
 abstract class AbstractLogic<T extends AbstractBaseBean> {
 
-    /**
-     * Logger.
-     */
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractLogic.class);
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
index 8747631..1743370 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
@@ -42,11 +42,11 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO
     private AnyTypeClassDataBinder binder;
 
     @Autowired
-    private AnyTypeClassDAO anyTypeDAO;
+    private AnyTypeClassDAO anyTypeClassDAO;
 
     @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_READ + "')")
     public AnyTypeClassTO read(final String key) {
-        AnyTypeClass anyType = anyTypeDAO.find(key);
+        AnyTypeClass anyType = anyTypeClassDAO.find(key);
         if (anyType == null) {
             LOG.error("Could not find anyType '" + key + "'");
 
@@ -58,7 +58,7 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO
 
     @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_LIST + "')")
     public List<AnyTypeClassTO> list() {
-        return CollectionUtils.collect(anyTypeDAO.findAll(), new Transformer<AnyTypeClass, AnyTypeClassTO>() {
+        return CollectionUtils.collect(anyTypeClassDAO.findAll(), new Transformer<AnyTypeClass, AnyTypeClassTO>() {
 
             @Override
             public AnyTypeClassTO transform(final AnyTypeClass input) {
@@ -68,35 +68,35 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO
     }
 
     @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_CREATE + "')")
-    public AnyTypeClassTO create(final AnyTypeClassTO anyTypeTO) {
-        return binder.getAnyTypeClassTO(anyTypeDAO.save(binder.create(anyTypeTO)));
+    public AnyTypeClassTO create(final AnyTypeClassTO anyTypeClassTO) {
+        return binder.getAnyTypeClassTO(anyTypeClassDAO.save(binder.create(anyTypeClassTO)));
     }
 
     @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_UPDATE + "')")
-    public AnyTypeClassTO update(final AnyTypeClassTO anyTypeTO) {
-        AnyTypeClass anyType = anyTypeDAO.find(anyTypeTO.getKey());
+    public AnyTypeClassTO update(final AnyTypeClassTO anyTypeClassTO) {
+        AnyTypeClass anyType = anyTypeClassDAO.find(anyTypeClassTO.getKey());
         if (anyType == null) {
-            LOG.error("Could not find anyType '" + anyTypeTO.getKey() + "'");
-            throw new NotFoundException(String.valueOf(anyTypeTO.getKey()));
+            LOG.error("Could not find anyTypeClass '" + anyTypeClassTO.getKey() + "'");
+            throw new NotFoundException(String.valueOf(anyTypeClassTO.getKey()));
         }
 
-        binder.update(anyType, anyTypeTO);
-        anyType = anyTypeDAO.save(anyType);
+        binder.update(anyType, anyTypeClassTO);
+        anyType = anyTypeClassDAO.save(anyType);
 
         return binder.getAnyTypeClassTO(anyType);
     }
 
     @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_DELETE + "')")
     public AnyTypeClassTO delete(final String key) {
-        AnyTypeClass anyType = anyTypeDAO.find(key);
-        if (anyType == null) {
-            LOG.error("Could not find anyType '" + key + "'");
+        AnyTypeClass anyTypeClass = anyTypeClassDAO.find(key);
+        if (anyTypeClass == null) {
+            LOG.error("Could not find anyTypeClass '" + key + "'");
 
             throw new NotFoundException(String.valueOf(key));
         }
 
-        AnyTypeClassTO deleted = binder.getAnyTypeClassTO(anyType);
-        anyTypeDAO.delete(key);
+        AnyTypeClassTO deleted = binder.getAnyTypeClassTO(anyTypeClass);
+        anyTypeClassDAO.delete(key);
         return deleted;
     }
 
@@ -108,7 +108,7 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO
 
         if (ArrayUtils.isNotEmpty(args)) {
             for (int i = 0; key == null && i < args.length; i++) {
-                if (args[i] instanceof Long) {
+                if (args[i] instanceof String) {
                     key = (String) args[i];
                 } else if (args[i] instanceof AnyTypeClassTO) {
                     key = ((AnyTypeClassTO) args[i]).getKey();
@@ -118,7 +118,7 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO
 
         if (StringUtils.isNotBlank(key)) {
             try {
-                return binder.getAnyTypeClassTO(anyTypeDAO.find(key));
+                return binder.getAnyTypeClassTO(anyTypeClassDAO.find(key));
             } catch (Throwable ignore) {
                 LOG.debug("Unresolved reference", ignore);
                 throw new UnresolvedReferenceException(ignore);

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
index b0cfa03..1ff60c7 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
@@ -116,7 +116,7 @@ public class AnyTypeLogic extends AbstractTransactionalLogic<AnyTypeTO> {
 
         if (ArrayUtils.isNotEmpty(args)) {
             for (int i = 0; key == null && i < args.length; i++) {
-                if (args[i] instanceof Long) {
+                if (args[i] instanceof String) {
                     key = (String) args[i];
                 } else if (args[i] instanceof AnyTypeTO) {
                     key = ((AnyTypeTO) args[i]).getKey();

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
new file mode 100644
index 0000000..58f717d
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java
@@ -0,0 +1,136 @@
+/*
+ * 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 java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.DomainTO;
+import org.apache.syncope.common.lib.types.Entitlement;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.DomainDAO;
+import org.apache.syncope.core.persistence.api.entity.Domain;
+import org.apache.syncope.core.provisioning.api.data.DomainDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DomainLogic extends AbstractTransactionalLogic<DomainTO> {
+
+    @Autowired
+    private DomainDataBinder binder;
+
+    @Autowired
+    private DomainDAO domainDAO;
+
+    @PreAuthorize("hasRole('" + Entitlement.DOMAIN_READ + "') and authentication.details.domain == "
+            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
+    public DomainTO read(final String key) {
+        Domain domain = domainDAO.find(key);
+        if (domain == null) {
+            LOG.error("Could not find domain '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        return binder.getDomainTO(domain);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.DOMAIN_LIST + "') and authentication.details.domain == "
+            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
+    public List<DomainTO> list() {
+        return CollectionUtils.collect(domainDAO.findAll(), new Transformer<Domain, DomainTO>() {
+
+            @Override
+            public DomainTO transform(final Domain input) {
+                return binder.getDomainTO(input);
+            }
+        }, new ArrayList<DomainTO>());
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.DOMAIN_CREATE + "') and authentication.details.domain == "
+            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
+    public DomainTO create(final DomainTO domainTO) {
+        return binder.getDomainTO(domainDAO.save(binder.create(domainTO)));
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.DOMAIN_UPDATE + "') and authentication.details.domain == "
+            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
+    public DomainTO update(final DomainTO domainTO) {
+        Domain domain = domainDAO.find(domainTO.getKey());
+        if (domain == null) {
+            LOG.error("Could not find domain '" + domainTO.getKey() + "'");
+            throw new NotFoundException(String.valueOf(domainTO.getKey()));
+        }
+
+        binder.update(domain, domainTO);
+        domain = domainDAO.save(domain);
+
+        return binder.getDomainTO(domain);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.DOMAIN_DELETE + "') and authentication.details.domain == "
+            + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN")
+    public DomainTO delete(final String key) {
+        Domain domain = domainDAO.find(key);
+        if (domain == null) {
+            LOG.error("Could not find domain '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        DomainTO deleted = binder.getDomainTO(domain);
+        domainDAO.delete(key);
+        return deleted;
+    }
+
+    @Override
+    protected DomainTO 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 DomainTO) {
+                    key = ((DomainTO) args[i]).getKey();
+                }
+            }
+        }
+
+        if (StringUtils.isNotBlank(key)) {
+            try {
+                return binder.getDomainTO(domainDAO.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/252b1510/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
index ff5cd64..f476210 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
@@ -103,7 +103,7 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
     @Transactional(readOnly = true)
     public List<GroupTO> own() {
         return CollectionUtils.collect(
-                userDAO.findAllGroups(userDAO.find(AuthContextUtils.getAuthenticatedUsername())),
+                userDAO.findAllGroups(userDAO.find(AuthContextUtils.getUsername())),
                 new Transformer<Group, GroupTO>() {
 
                     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/misc/pom.xml
----------------------------------------------------------------------
diff --git a/core/misc/pom.xml b/core/misc/pom.xml
index d330ad6..d9c6049 100644
--- a/core/misc/pom.xml
+++ b/core/misc/pom.xml
@@ -100,11 +100,16 @@ under the License.
       <groupId>org.springframework.security</groupId>
       <artifactId>spring-security-web</artifactId>
     </dependency>
-        
+
     <dependency>
       <groupId>org.apache.syncope.core</groupId>
       <artifactId>syncope-core-provisioning-api</artifactId>
       <version>${project.version}</version>
+    </dependency>        
+    <dependency>
+      <groupId>org.apache.syncope.common</groupId>
+      <artifactId>syncope-common-rest-api</artifactId>
+      <version>${project.version}</version>
     </dependency>
     
     <!-- TEST -->

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthContextUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthContextUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthContextUtils.java
index 6eebf01..932627d 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthContextUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthContextUtils.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
@@ -32,24 +33,25 @@ import org.springframework.security.core.userdetails.User;
 
 public final class AuthContextUtils {
 
-    public static String getAuthenticatedUsername() {
+    public static String getUsername() {
         Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
         return authentication == null ? SyncopeConstants.UNAUTHENTICATED : authentication.getName();
     }
 
-    public static void updateAuthenticatedUsername(final String newUsername) {
+    public static void updateUsername(final String newUsername) {
         Authentication auth = SecurityContextHolder.getContext().getAuthentication();
 
-        Authentication newAuth = new UsernamePasswordAuthenticationToken(
+        UsernamePasswordAuthenticationToken newAuth = new UsernamePasswordAuthenticationToken(
                 new User(newUsername, "FAKE_PASSWORD", auth.getAuthorities()),
                 auth.getCredentials(), auth.getAuthorities());
+        newAuth.setDetails(auth.getDetails());
         SecurityContextHolder.getContext().setAuthentication(newAuth);
     }
 
     public static Map<String, Set<String>> getAuthorizations() {
         Map<String, Set<String>> result = null;
 
-        final SecurityContext ctx = SecurityContextHolder.getContext();
+        SecurityContext ctx = SecurityContextHolder.getContext();
         if (ctx != null && ctx.getAuthentication() != null && ctx.getAuthentication().getAuthorities() != null) {
             result = new HashMap<>();
             for (GrantedAuthority authority : ctx.getAuthentication().getAuthorities()) {
@@ -64,6 +66,19 @@ public final class AuthContextUtils {
         return MapUtils.emptyIfNull(result);
     }
 
+    public static String getDomain() {
+        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+
+        String domainKey = auth != null && auth.getDetails() instanceof SyncopeAuthenticationDetails
+                ? SyncopeAuthenticationDetails.class.cast(auth.getDetails()).getDomain()
+                : null;
+        if (StringUtils.isBlank(domainKey)) {
+            domainKey = SyncopeConstants.MASTER_DOMAIN;
+        }
+
+        return domainKey;
+    }
+
     /**
      * Private default constructor, for static-only classes.
      */

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetails.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetails.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetails.java
new file mode 100644
index 0000000..68b27f4
--- /dev/null
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetails.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.misc.security;
+
+import java.io.Serializable;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+
+public class SyncopeAuthenticationDetails implements Serializable {
+
+    private static final long serialVersionUID = -5899959397393502897L;
+
+    private final String remoteAddress;
+
+    private final String sessionId;
+
+    private String domain;
+
+    public SyncopeAuthenticationDetails(final HttpServletRequest request) {
+        this.remoteAddress = request.getRemoteAddr();
+
+        HttpSession session = request.getSession(false);
+        this.sessionId = session == null ? null : session.getId();
+
+        this.domain = request.getHeader(RESTHeaders.DOMAIN);
+    }
+
+    public SyncopeAuthenticationDetails(final String domain) {
+        this.remoteAddress = null;
+        this.sessionId = null;
+        this.domain = domain;
+    }
+
+    public String getRemoteAddress() {
+        return remoteAddress;
+    }
+
+    public String getSessionId() {
+        return sessionId;
+    }
+
+    public String getDomain() {
+        return domain;
+    }
+
+    public void setDomain(final String domain) {
+        this.domain = domain;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public String toString() {
+        return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetailsSource.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetailsSource.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetailsSource.java
new file mode 100644
index 0000000..b943edf
--- /dev/null
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetailsSource.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.misc.security;
+
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.security.authentication.AuthenticationDetailsSource;
+
+public class SyncopeAuthenticationDetailsSource
+        implements AuthenticationDetailsSource<HttpServletRequest, SyncopeAuthenticationDetails> {
+
+    @Override
+    public SyncopeAuthenticationDetails buildDetails(final HttpServletRequest context) {
+        return new SyncopeAuthenticationDetails(context);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java
index 80d2b48..01abb93 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java
@@ -23,14 +23,14 @@ import java.util.Iterator;
 import java.util.Set;
 import javax.annotation.Resource;
 import org.apache.commons.collections4.SetUtils;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditElements.Result;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
@@ -39,7 +39,10 @@ import org.apache.syncope.core.provisioning.api.ConnectorFactory;
 import org.apache.syncope.core.misc.AuditManager;
 import org.apache.syncope.core.misc.MappingUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.DomainDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
+import org.apache.syncope.core.persistence.api.entity.Domain;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.identityconnectors.framework.common.objects.Uid;
 import org.slf4j.Logger;
@@ -57,15 +60,15 @@ import org.springframework.transaction.annotation.Transactional;
 @Configurable
 public class SyncopeAuthenticationProvider implements AuthenticationProvider {
 
-    /**
-     * Logger.
-     */
     protected static final Logger LOG = LoggerFactory.getLogger(SyncopeAuthenticationProvider.class);
 
     @Autowired
     protected AuditManager auditManager;
 
     @Autowired
+    protected DomainDAO domainDAO;
+
+    @Autowired
     protected ConfDAO confDAO;
 
     @Autowired
@@ -131,18 +134,36 @@ public class SyncopeAuthenticationProvider implements AuthenticationProvider {
     @Transactional(noRollbackFor = { BadCredentialsException.class, DisabledException.class })
     public Authentication authenticate(final Authentication authentication) {
         boolean authenticated = false;
-        User user = null;
 
-        String username = authentication.getName();
-        if (anonymousUser.equals(username)) {
+        String domainKey = authentication.getDetails() instanceof SyncopeAuthenticationDetails
+                ? SyncopeAuthenticationDetails.class.cast(authentication.getDetails()).getDomain()
+                : null;
+        if (StringUtils.isBlank(domainKey)) {
+            domainKey = SyncopeConstants.MASTER_DOMAIN;
+        }
+        SyncopeAuthenticationDetails.class.cast(authentication.getDetails()).setDomain(domainKey);
+
+        if (anonymousUser.equals(authentication.getName())) {
             authenticated = authentication.getCredentials().toString().equals(anonymousKey);
-        } else if (adminUser.equals(username)) {
-            authenticated = encryptor.verify(
-                    authentication.getCredentials().toString(),
-                    CipherAlgorithm.valueOf(adminPasswordAlgorithm),
-                    adminPassword);
+        } else if (adminUser.equals(authentication.getName())) {
+            if (SyncopeConstants.MASTER_DOMAIN.equals(domainKey)) {
+                authenticated = encryptor.verify(
+                        authentication.getCredentials().toString(),
+                        CipherAlgorithm.valueOf(adminPasswordAlgorithm),
+                        adminPassword);
+            } else {
+                Domain domain = domainDAO.find(domainKey);
+                if (domain == null) {
+                    throw new NotFoundException("Could not find domain " + domainKey);
+                }
+
+                authenticated = encryptor.verify(
+                        authentication.getCredentials().toString(),
+                        domain.getAdminCipherAlgorithm(),
+                        domain.getAdminPwd());
+            }
         } else {
-            user = userDAO.find(username);
+            User user = userDAO.find(authentication.getName());
 
             if (user != null) {
                 if (user.isSuspended() != null && user.isSuspended()) {
@@ -166,7 +187,6 @@ public class SyncopeAuthenticationProvider implements AuthenticationProvider {
                     authentication.getPrincipal(),
                     null,
                     userDetailsService.loadUserByUsername(authentication.getPrincipal().toString()).getAuthorities());
-
             token.setDetails(authentication.getDetails());
 
             auditManager.audit(
@@ -257,7 +277,6 @@ public class SyncopeAuthenticationProvider implements AuthenticationProvider {
         boolean authenticated = encryptor.verify(password, user.getCipherAlgorithm(), user.getPassword());
         LOG.debug("{} authenticated on internal storage: {}", user.getUsername(), authenticated);
 
-        AnyUtils attrUtils = attrUtilsFactory.getInstance(AnyTypeKind.USER);
         for (Iterator<? extends ExternalResource> itor = getPassthroughResources(user).iterator();
                 itor.hasNext() && !authenticated;) {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/misc/src/main/resources/securityContext.xml
----------------------------------------------------------------------
diff --git a/core/misc/src/main/resources/securityContext.xml b/core/misc/src/main/resources/securityContext.xml
index 00ced82..57b1980 100644
--- a/core/misc/src/main/resources/securityContext.xml
+++ b/core/misc/src/main/resources/securityContext.xml
@@ -49,9 +49,12 @@ under the License.
     <constructor-arg ref="securityContextRepository"/>
   </bean>
 
+  <bean id="syncopeAuthenticationDetailsSource"
+        class="org.apache.syncope.core.misc.security.SyncopeAuthenticationDetailsSource"/>
+
   <security:http security-context-repository-ref="securityContextRepository" realm="Apache Syncope authentication" 
                  use-expressions="false" disable-url-rewriting="false">
-    <security:http-basic/>
+    <security:http-basic authentication-details-source-ref="syncopeAuthenticationDetailsSource"/>
     <security:anonymous username="${anonymousUser}"/>
     <security:intercept-url pattern="/**"/>
     

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DAO.java
index 4452890..eb00a0d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DAO.java
@@ -22,6 +22,8 @@ import org.apache.syncope.core.persistence.api.entity.Entity;
 
 public interface DAO<E extends Entity<KEY>, KEY> {
 
+    String getDomain(E entity);
+
     void refresh(E entity);
 
     void detach(E entity);

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DomainDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DomainDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DomainDAO.java
new file mode 100644
index 0000000..ece1b16
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DomainDAO.java
@@ -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.
+ */
+package org.apache.syncope.core.persistence.api.dao;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.Domain;
+
+public interface DomainDAO extends DAO<Domain, String> {
+
+    Domain find(String key);
+
+    List<Domain> findAll();
+
+    Domain save(Domain domain);
+
+    void delete(String key);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Domain.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Domain.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Domain.java
new file mode 100644
index 0000000..7c496f0
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Domain.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.persistence.api.entity;
+
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+
+public interface Domain extends Entity<String> {
+
+    void setKey(String name);
+
+    String getAdminPwd();
+
+    CipherAlgorithm getAdminCipherAlgorithm();
+
+    void setPassword(String password, CipherAlgorithm cipherAlgoritm);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/pom.xml b/core/persistence-jpa/pom.xml
index d48ef77..0ab9e82 100644
--- a/core/persistence-jpa/pom.xml
+++ b/core/persistence-jpa/pom.xml
@@ -55,7 +55,11 @@ under the License.
       <groupId>org.apache.openjpa</groupId>
       <artifactId>openjpa-persistence-jdbc</artifactId>
     </dependency>
-
+    <dependency>
+      <groupId>org.apache.openjpa</groupId>
+      <artifactId>openjpa-slice</artifactId>
+    </dependency>
+    
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-dbcp2</artifactId>
@@ -105,6 +109,11 @@ under the License.
     </dependency>
         
     <!-- TEST -->
+    <dependency> 
+      <groupId>javax.servlet</groupId> 
+      <artifactId>javax.servlet-api</artifactId> 
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-simple</artifactId>

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java
index a4ff529..c2d5ae6 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java
@@ -25,6 +25,8 @@ import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.PersistenceContextType;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.openjpa.slice.SlicePersistence;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.core.persistence.api.dao.DAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.Entity;
@@ -93,6 +95,16 @@ public abstract class AbstractDAO<E extends Entity<KEY>, KEY> implements DAO<E,
     }
 
     @Override
+    public String getDomain(final E entity) {
+        try {
+            return SlicePersistence.getSlice(entity);
+        } catch (Exception e) {
+            LOG.debug("While fetching slice for {}", entity, e);
+            return SyncopeConstants.MASTER_DOMAIN;
+        }
+    }
+
+    @Override
     public void refresh(final E entity) {
         entityManager.refresh(entity);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index b8ab75d..e0eae6a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -387,12 +387,9 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?, ?, ?>, Long> implements
         List<T> result = new ArrayList<>();
 
         for (Object anyKey : query.getResultList()) {
-            long actualKey;
-            if (anyKey instanceof Object[]) {
-                actualKey = ((Number) ((Object[]) anyKey)[0]).longValue();
-            } else {
-                actualKey = ((Number) anyKey).longValue();
-            }
+            long actualKey = anyKey instanceof Object[]
+                    ? ((Number) ((Object[]) anyKey)[0]).longValue()
+                    : ((Number) anyKey).longValue();
 
             T any = typeKind == AnyTypeKind.USER
                     ? (T) userDAO.find(actualKey)

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java
new file mode 100644
index 0000000..37a4cd2
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.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.core.persistence.jpa.dao;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.core.persistence.api.dao.DomainDAO;
+import org.apache.syncope.core.persistence.api.entity.Domain;
+import org.apache.syncope.core.persistence.jpa.entity.JPADomain;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class JPADomainDAO extends AbstractDAO<Domain, String> implements DomainDAO {
+
+    @Override
+    public Domain find(final String key) {
+        return entityManager.find(JPADomain.class, key);
+    }
+
+    @Override
+    public List<Domain> findAll() {
+        TypedQuery<Domain> query = entityManager.createQuery(
+                "SELECT e FROM " + JPADomain.class.getSimpleName() + " e ", Domain.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public Domain save(final Domain anyTypeClass) {
+        return entityManager.merge(anyTypeClass);
+    }
+
+    @Override
+    public void delete(final String key) {
+        Domain domain = find(key);
+        if (domain == null) {
+            return;
+        }
+
+        entityManager.remove(domain);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
index 7045ddc..3b413c0 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
@@ -74,8 +74,8 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
     protected void securityChecks(final User user) {
         // Allows anonymous (during self-registration) and self (during self-update) to read own user,
         // otherwise goes through security checks to see if required entitlements are owned
-        if (!AuthContextUtils.getAuthenticatedUsername().equals(anonymousUser)
-                && !AuthContextUtils.getAuthenticatedUsername().equals(user.getUsername())) {
+        if (!AuthContextUtils.getUsername().equals(anonymousUser)
+                && !AuthContextUtils.getUsername().equals(user.getUsername())) {
 
             Set<String> authRealms = AuthContextUtils.getAuthorizations().get(Entitlement.USER_READ);
             boolean authorized = CollectionUtils.exists(authRealms, new Predicate<String>() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java
index 8a9547e..4e8044d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java
@@ -33,7 +33,7 @@ public class AnnotatedEntityListener {
     @PrePersist
     @PreUpdate
     public void setSysInfo(final AnnotatedEntity<?> entity) {
-        final String username = AuthContextUtils.getAuthenticatedUsername();
+        final String username = AuthContextUtils.getUsername();
         LOG.debug("Set system properties for '{}'", entity);
 
         final Date now = new Date();

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java
new file mode 100644
index 0000000..3e9169e
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.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 javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.core.misc.security.Encryptor;
+import org.apache.syncope.core.persistence.api.entity.Domain;
+import org.apache.syncope.core.persistence.jpa.validation.entity.DomainCheck;
+
+@Entity
+@Table(name = JPADomain.TABLE)
+@DomainCheck
+public class JPADomain extends AbstractEntity<String> implements Domain {
+
+    private static final long serialVersionUID = -5891241943464285840L;
+
+    public static final String TABLE = "SyncopeDomain";
+
+    @Id
+    private String name;
+
+    private String adminPwd;
+
+    @Enumerated(EnumType.STRING)
+    private CipherAlgorithm adminCipherAlgorithm;
+
+    @Override
+    public String getKey() {
+        return name;
+    }
+
+    @Override
+    public void setKey(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String getAdminPwd() {
+        return adminPwd;
+    }
+
+    @Override
+    public CipherAlgorithm getAdminCipherAlgorithm() {
+        return adminCipherAlgorithm;
+    }
+
+    @Override
+    public void setPassword(final String password, final CipherAlgorithm cipherAlgoritm) {
+        try {
+            this.adminPwd = Encryptor.getInstance().encode(password, cipherAlgoritm);
+            this.adminCipherAlgorithm = cipherAlgoritm;
+        } catch (Exception e) {
+            LOG.error("Could not encode password", e);
+            this.adminPwd = null;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
index ad6304e..41d3f74 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
@@ -27,6 +27,7 @@ import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.ConnInstance;
 import org.apache.syncope.core.persistence.api.entity.ConnPoolConf;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.Domain;
 import org.apache.syncope.core.persistence.api.entity.user.DynRoleMembership;
 import org.apache.syncope.core.persistence.api.entity.Entity;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
@@ -129,7 +130,9 @@ public class JPAEntityFactory implements EntityFactory {
     public <KEY, T extends Entity<KEY>> T newEntity(final Class<T> reference) {
         T result;
 
-        if (reference.equals(Realm.class)) {
+        if (reference.equals(Domain.class)) {
+            result = (T) new JPADomain();
+        } else if (reference.equals(Realm.class)) {
             result = (T) new JPARealm();
         } else if (reference.equals(AccountPolicy.class)) {
             result = (T) new JPAAccountPolicy();

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainDistributionPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainDistributionPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainDistributionPolicy.java
new file mode 100644
index 0000000..2e61b06
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainDistributionPolicy.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.jpa.slice;
+
+import java.util.List;
+import org.apache.openjpa.slice.DistributionPolicy;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.core.misc.security.AuthContextUtils;
+import org.apache.syncope.core.persistence.api.entity.Domain;
+
+public class DomainDistributionPolicy implements DistributionPolicy {
+
+    @Override
+    public String distribute(final Object pc, final List<String> slices, final Object context) {
+        return (pc instanceof Domain)
+                ? SyncopeConstants.MASTER_DOMAIN
+                : AuthContextUtils.getDomain();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainFinderTargetPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainFinderTargetPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainFinderTargetPolicy.java
new file mode 100644
index 0000000..c6cad6e
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainFinderTargetPolicy.java
@@ -0,0 +1,38 @@
+/*
+ * 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.slice;
+
+import java.util.List;
+import org.apache.openjpa.slice.FinderTargetPolicy;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.core.misc.security.AuthContextUtils;
+import org.apache.syncope.core.persistence.jpa.entity.JPADomain;
+
+public class DomainFinderTargetPolicy implements FinderTargetPolicy {
+
+    @Override
+    public String[] getTargets(final Class<?> cls, final Object oid, final List<String> slices, final Object context) {
+        return new String[] {
+            JPADomain.class.equals(cls)
+            ? SyncopeConstants.MASTER_DOMAIN
+            : AuthContextUtils.getDomain()
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainQueryTargetPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainQueryTargetPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainQueryTargetPolicy.java
new file mode 100644
index 0000000..193ef2b
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainQueryTargetPolicy.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.slice;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.openjpa.slice.QueryTargetPolicy;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.core.misc.security.AuthContextUtils;
+import org.apache.syncope.core.persistence.jpa.entity.JPADomain;
+
+public class DomainQueryTargetPolicy implements QueryTargetPolicy {
+
+    @Override
+    public String[] getTargets(final String query, final Map<Object, Object> params, final String language,
+            final List<String> slices, final Object context) {
+
+        return new String[] {
+            query.contains(JPADomain.class.getSimpleName())
+            ? SyncopeConstants.MASTER_DOMAIN
+            : AuthContextUtils.getDomain()
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainCheck.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainCheck.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainCheck.java
new file mode 100644
index 0000000..f40c37e
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainCheck.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 = DomainValidator.class)
+@Documented
+public @interface DomainCheck {
+
+    String message() default "{org.apache.syncope.core.persistence.validation.domain}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java
new file mode 100644
index 0000000..2e585e4
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java
@@ -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.
+ */
+package org.apache.syncope.core.persistence.jpa.validation.entity;
+
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.core.persistence.api.entity.Domain;
+
+public class DomainValidator extends AbstractValidator<DomainCheck, Domain> {
+
+    @Override
+    public boolean isValid(final Domain object, final ConstraintValidatorContext context) {
+        context.disableDefaultConstraintViolation();
+
+        boolean isValid = !SyncopeConstants.MASTER_DOMAIN.equals(object.getKey());
+
+        if (!isValid) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidName, "Reserved: " + SyncopeConstants.MASTER_DOMAIN)).
+                    addPropertyNode("name").addConstraintViolation();
+        }
+
+        return isValid;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/resources/persistence.properties
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/persistence.properties b/core/persistence-jpa/src/main/resources/persistence.properties
index 5afa1a6..054808d 100644
--- a/core/persistence-jpa/src/main/resources/persistence.properties
+++ b/core/persistence-jpa/src/main/resources/persistence.properties
@@ -22,8 +22,8 @@ jpa.password=syncope
 jpa.dialect=org.apache.openjpa.jdbc.sql.PostgresDictionary
 jpa.pool.validationQuery=SELECT 1
 jpa.orm=META-INF/spring-orm.xml
-#note: other connection pool settings can also be configured here, see persistenceContext.xml
+# note: other connection pool settings can also be configured here, see persistenceContext.xml
 quartz.jobstore=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
 quartz.sql=tables_postgres.sql
 audit.sql=audit.sql
-database.schema=
+database.schema=
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml b/core/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml
index 3b3b86b..d3a7e45 100644
--- a/core/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml
+++ b/core/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml
@@ -21,7 +21,7 @@ under the License.
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd">
-
+  
   <bean id="entityManagerFactory"
         class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
     <property name="packagesToScan" value="org.apache.syncope.core.persistence.jpa.entity"/>
@@ -47,19 +47,41 @@ under the License.
     </property>
     <property name="jpaPropertyMap">
       <map>
+        <entry key="openjpa.Log" value="DefaultLevel=INFO, Runtime=TRACE, Tool=TRACE, SQL=TRACE"/>
+        
         <!--<entry key="openjpa.Log" value="SQL=TRACE"/>
         <entry key="openjpa.ConnectionFactoryProperties" 
         value="PrintParameters=true, PrettyPrint=true, PrettyPrintLineLength=80"/>-->
-                                
+        
         <entry key="openjpa.NontransactionalWrite" value="false"/>
         <entry key="openjpa.AutoDetach" value="close, commit, nontx-read, rollback"/>
 
         <entry key="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)"/>
-        <entry key="openjpa.jdbc.MappingDefaults" value="ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict"/>
-                
+        <entry key="openjpa.jdbc.MappingDefaults" 
+               value="ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict"/>
+                        
         <entry key="openjpa.DataCache" value="true"/>
-        <entry key="openjpa.QueryCache" value="true"/>
+        <entry key="openjpa.QueryCache" value="false"/>
+        <entry key="openjpa.QueryCompilationCache" value="false"/>
         <entry key="openjpa.RemoteCommitProvider" value="sjvm"/>
+        
+        <entry key="openjpa.BrokerFactory" value="slice"/>       
+        <entry key="openjpa.BrokerImpl" value="org.apache.openjpa.slice.DistributedBrokerImpl"/> 
+        <entry key="openjpa.slice.Lenient" value="false"/>
+        
+        <entry key="openjpa.slice.DistributionPolicy" 
+               value="org.apache.syncope.core.persistence.jpa.slice.DomainDistributionPolicy"/>
+        <entry key="openjpa.slice.QueryTargetPolicy" 
+               value="org.apache.syncope.core.persistence.jpa.slice.DomainQueryTargetPolicy"/>
+        <entry key="openjpa.slice.FinderTargetPolicy" 
+               value="org.apache.syncope.core.persistence.jpa.slice.DomainFinderTargetPolicy"/>
+
+        <entry key="openjpa.slice.Names" value="Master"/>        
+        <entry key="openjpa.slice.Master"  value="Master"/>
+        <entry key="openjpa.slice.Lenient" value="false"/>
+        
+        <entry key="openjpa.slice.Master.ConnectionFactory" value-ref="dataSource"/>
+        <entry key="openjpa.slice.Master.jdbc.DBDictionary" value="${jpa.dialect}"/>
       </map>
     </property>
   </bean>

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
index 587f31d..a709638 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
@@ -54,7 +54,7 @@ public class UserTest extends AbstractTest {
     @Test
     public void findAll() {
         List<User> list = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 1, 100);
-        assertEquals("did not get expected number of users ", 5, list.size());
+        assertEquals("did not get expected number of users", 5, list.size());
     }
 
     @Test
@@ -68,25 +68,25 @@ public class UserTest extends AbstractTest {
     public void findAllByPageAndSize() {
         // get first page
         List<User> list = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 1, 2);
-        assertEquals("did not get expected number of users ", 2, list.size());
+        assertEquals("did not get expected number of users", 2, list.size());
 
         // get second page
         list = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 2, 2);
-        assertEquals("did not get expected number of users ", 2, list.size());
+        assertEquals("did not get expected number of users", 2, list.size());
 
         // get second page with uncomplete set
         list = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 2, 3);
-        assertEquals("did not get expected number of users ", 2, list.size());
+        assertEquals("did not get expected number of users", 2, list.size());
 
         // get unexistent page
         list = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 3, 2);
-        assertEquals("did not get expected number of users ", 1, list.size());
+        assertEquals("did not get expected number of users", 1, list.size());
     }
 
     @Test
     public void findByDerAttributeValue() {
         final List<User> list = userDAO.findByDerAttrValue("cn", "Vivaldi, Antonio");
-        assertEquals("did not get expected number of users ", 1, list.size());
+        assertEquals("did not get expected number of users", 1, list.size());
     }
 
     @Test(expected = IllegalArgumentException.class)
@@ -105,7 +105,7 @@ public class UserTest extends AbstractTest {
         fullnameValue.setStringValue("Gioacchino Rossini");
 
         final List<User> list = userDAO.findByAttrValue("fullname", fullnameValue);
-        assertEquals("did not get expected number of users ", 1, list.size());
+        assertEquals("did not get expected number of users", 1, list.size());
     }
 
     @Test
@@ -114,7 +114,7 @@ public class UserTest extends AbstractTest {
         coolValue.setBooleanValue(true);
 
         final List<User> list = userDAO.findByAttrValue("cool", coolValue);
-        assertEquals("did not get expected number of users ", 1, list.size());
+        assertEquals("did not get expected number of users", 1, list.size());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/252b1510/core/persistence-jpa/src/test/resources/persistence.properties
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/persistence.properties b/core/persistence-jpa/src/test/resources/persistence.properties
index 92b0cbc..6993a0b 100644
--- a/core/persistence-jpa/src/test/resources/persistence.properties
+++ b/core/persistence-jpa/src/test/resources/persistence.properties
@@ -22,9 +22,9 @@ jpa.password=
 jpa.dialect=org.apache.openjpa.jdbc.sql.H2Dictionary
 jpa.pool.validationQuery=SELECT 1
 jpa.orm=META-INF/spring-orm.xml
-#note: other connection pool settings can also be configured here, see persistenceContext.xml
+# note: other connection pool settings can also be configured here, see persistenceContext.xml
 quartz.jobstore=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
 quartz.scheduler.idleWaitTime=5000
 quartz.sql=tables_h2.sql
 audit.sql=audit.sql
-database.schema=
+database.schema=
\ No newline at end of file