You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by an...@apache.org on 2015/12/31 10:38:49 UTC

syncope git commit: [SYNCOPE-719] Added CSRF/XSRF protection by http cookie provided to angular

Repository: syncope
Updated Branches:
  refs/heads/master 6a93860d8 -> 8e8368e19


[SYNCOPE-719] Added CSRF/XSRF protection by http cookie provided to angular


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

Branch: refs/heads/master
Commit: 8e8368e19772c5e39baa0a152e81a890f2cb6c3e
Parents: 6a93860
Author: Andrea Patricelli <an...@tirasa.net>
Authored: Thu Dec 31 10:38:28 2015 +0100
Committer: Andrea Patricelli <an...@tirasa.net>
Committed: Thu Dec 31 10:38:28 2015 +0100

----------------------------------------------------------------------
 .../client/enduser/SyncopeEnduserConstants.java |  8 ++-
 .../client/enduser/SyncopeEnduserSession.java   |  9 ++++
 .../enduser/resources/AbstractBaseResource.java | 10 ++++
 .../enduser/resources/CaptchaResource.java      |  6 +--
 .../resources/CaptchaValidateResource.java      | 12 ++++-
 .../client/enduser/resources/InfoResource.java  | 15 +++++-
 .../client/enduser/resources/LoginResource.java | 42 +++++++++-------
 .../enduser/resources/LogoutResource.java       |  2 +-
 .../enduser/resources/SchemaResource.java       |  9 ++++
 .../resources/SecurityQuestionResource.java     |  9 ++++
 .../resources/SyncopeResourceResource.java      |  9 ++++
 .../resources/UserSelfCreateResource.java       |  6 +++
 .../enduser/resources/UserSelfReadResource.java | 13 ++++-
 .../resources/UserSelfUpdateResource.java       | 11 ++++-
 .../resources/META-INF/resources/app/index.html |  2 +-
 .../resources/META-INF/resources/app/js/app.js  | 52 +++++++++++++++-----
 .../app/js/controllers/LoginController.js       | 49 +++---------------
 .../resources/app/js/services/infoService.js    |  3 +-
 .../META-INF/resources/app/views/self.html      |  4 +-
 client/lib/pom.xml                              |  5 ++
 .../syncope/client/lib/SaltGenerator.java       | 42 ++++++++++++++++
 21 files changed, 228 insertions(+), 90 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java
index daa0e15..4600166 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserConstants.java
@@ -20,10 +20,14 @@ package org.apache.syncope.client.enduser;
 
 public final class SyncopeEnduserConstants {
 
-    public static final String CAPTCHA_SESSION_KEY  = "captcha";
+    public static final String CAPTCHA_SESSION_KEY = "captcha";
+
+    public static final String XSRF_COOKIE = "XSRF-TOKEN";
+
+    public static final String XSRF_HEADER_NAME = "X-XSRF-TOKEN";
 
     private SyncopeEnduserConstants() {
         // private constructor for utility class
     }
-    
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
index bbea57b..cb51436 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java
@@ -37,6 +37,7 @@ import org.apache.syncope.common.rest.api.service.SyncopeService;
 import org.apache.wicket.Session;
 import org.apache.wicket.protocol.http.WebSession;
 import org.apache.wicket.request.Request;
+import org.apache.wicket.util.cookies.CookieUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -62,6 +63,8 @@ public class SyncopeEnduserSession extends WebSession {
     private UserTO selfTO;
 
     private final Map<Class<?>, Object> services = Collections.synchronizedMap(new HashMap<Class<?>, Object>());
+    
+    private final CookieUtils cookieUtils;
 
     public static SyncopeEnduserSession get() {
         return (SyncopeEnduserSession) Session.get();
@@ -69,6 +72,8 @@ public class SyncopeEnduserSession extends WebSession {
 
     public SyncopeEnduserSession(final Request request) {
         super(request);
+        // define cookie utility to manage application cookies
+        cookieUtils = new CookieUtils();
 
         anonymousClient = SyncopeEnduserApplication.get().getClientFactory().create(
                 SyncopeEnduserApplication.get().getAnonymousUser(),
@@ -173,4 +178,8 @@ public class SyncopeEnduserSession extends WebSession {
         return DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale);
     }
 
+    public CookieUtils getCookieUtils() {
+        return cookieUtils;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/AbstractBaseResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/AbstractBaseResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/AbstractBaseResource.java
index 69fe72f..3f9e037 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/AbstractBaseResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/AbstractBaseResource.java
@@ -18,6 +18,9 @@
  */
 package org.apache.syncope.client.enduser.resources;
 
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.SyncopeEnduserConstants;
 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.wicket.request.resource.AbstractResource;
@@ -43,4 +46,11 @@ public abstract class AbstractBaseResource extends AbstractResource {
                 : result;
     }
 
+    protected final boolean xsrfCheck(final HttpServletRequest request) {
+        final String requestXSRFHeader = request.getHeader(SyncopeEnduserConstants.XSRF_HEADER_NAME);
+        return StringUtils.isNotBlank(requestXSRFHeader)
+                && SyncopeEnduserSession.get().getCookieUtils().getCookie(SyncopeEnduserConstants.XSRF_COOKIE).
+                getValue().equals(requestXSRFHeader);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java
index ad71a85..d856629 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaResource.java
@@ -21,7 +21,6 @@ package org.apache.syncope.client.enduser.resources;
 import javax.servlet.http.HttpServletRequest;
 import org.apache.syncope.client.enduser.SyncopeEnduserConstants;
 import org.apache.wicket.extensions.markup.html.captcha.CaptchaImageResource;
-import org.apache.wicket.request.Request;
 import org.apache.wicket.request.cycle.RequestCycle;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,11 +48,10 @@ public class CaptchaResource extends CaptchaImageResource {
     protected byte[] render() {
         LOG.info("Generate captcha");
         final String captcha = randomString(6, 8);
-        Request request = RequestCycle.get().getRequest();
-        HttpServletRequest httpRequest = ((HttpServletRequest) request.getContainerRequest());
+        HttpServletRequest httpRequest = ((HttpServletRequest) RequestCycle.get().getRequest().getContainerRequest());
         // store the captcha in the current session
         httpRequest.getSession().setAttribute(SyncopeEnduserConstants.CAPTCHA_SESSION_KEY, captcha);
-        
+
         getChallengeIdModel().setObject(captcha);
         return super.render();
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaValidateResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaValidateResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaValidateResource.java
index be07096..e8749b8 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaValidateResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/CaptchaValidateResource.java
@@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.enduser.SyncopeEnduserConstants;
 import org.apache.syncope.client.enduser.model.CaptchaRequest;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
+import org.apache.wicket.request.resource.AbstractResource;
 import org.apache.wicket.request.resource.IResource;
 import org.apache.wicket.util.io.IOUtils;
 import org.slf4j.Logger;
@@ -41,9 +42,16 @@ public class CaptchaValidateResource extends AbstractBaseResource {
 
         LOG.debug("Validate captcha request");
 
-        ResourceResponse response = new ResourceResponse();
+        AbstractResource.ResourceResponse response = new AbstractResource.ResourceResponse();
         try {
             HttpServletRequest currentRequest = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+
+            if (!xsrfCheck(currentRequest)) {
+                LOG.error("XSRF TOKEN does not match");
+                response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN does not match");
+                return response;
+            }
+
             final CaptchaRequest enteredCaptcha = POJOHelper.deserialize(IOUtils.toString(currentRequest.
                     getInputStream()), CaptchaRequest.class);
 
@@ -57,7 +65,7 @@ public class CaptchaValidateResource extends AbstractBaseResource {
                 LOG.info("Could not validate captcha: current session captcha or inserted captcha are empty or null");
                 response.setError(Response.Status.BAD_REQUEST.getStatusCode(),
                         "ErrorMessage{{ Could not validate captcha: current session captcha or entered captcha are "
-                                + "empty or null }}");
+                        + "empty or null }}");
             } else {
                 LOG.info("Is entered captcha equal to current session captcha? {}", enteredCaptcha.getValue().equals(
                         currentCaptcha));

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/InfoResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/InfoResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/InfoResource.java
index 530112b..1449cf0 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/InfoResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/InfoResource.java
@@ -20,10 +20,14 @@ package org.apache.syncope.client.enduser.resources;
 
 import java.io.IOException;
 import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.enduser.SyncopeEnduserConstants;
 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.client.enduser.adapters.SyncopeTOAdapter;
+import org.apache.syncope.client.lib.SaltGenerator;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
 import org.apache.wicket.request.resource.IResource;
+import org.apache.wicket.util.cookies.CookieUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,6 +49,15 @@ public class InfoResource extends AbstractBaseResource {
         ResourceResponse response = new ResourceResponse();
 
         try {
+            final CookieUtils sessionCookieUtils = SyncopeEnduserSession.get().getCookieUtils();
+//            HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+            // set XSRF_TOKEN cookie
+            if (sessionCookieUtils.getCookie(SyncopeEnduserConstants.XSRF_COOKIE) == null || StringUtils.isBlank(
+                    sessionCookieUtils.getCookie(SyncopeEnduserConstants.XSRF_COOKIE).getValue())) {
+                LOG.info("Set XSRF-TOKEN cookie");
+                sessionCookieUtils.save(SyncopeEnduserConstants.XSRF_COOKIE, SaltGenerator.generate(
+                        SyncopeEnduserSession.get().getId()));
+            }
             response.setWriteCallback(new WriteCallback() {
 
                 @Override
@@ -53,7 +66,7 @@ public class InfoResource extends AbstractBaseResource {
                             SyncopeEnduserSession.get().getSyncopeTO())));
                 }
             });
-        response.setStatusCode(Response.Status.OK.getStatusCode());
+            response.setStatusCode(Response.Status.OK.getStatusCode());
         } catch (Exception e) {
             LOG.error("Error retrieving syncope info", e);
             response.setError(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), new StringBuilder()

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LoginResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LoginResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LoginResource.java
index e481d2c..28d19a3 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LoginResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LoginResource.java
@@ -25,6 +25,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.enduser.model.Credentials;
 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.apache.wicket.request.resource.IResource;
 import org.apache.wicket.util.io.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -39,12 +41,19 @@ public class LoginResource extends AbstractBaseResource {
     }
 
     @Override
-    protected ResourceResponse newResourceResponse(final Attributes attributes) {
+    protected ResourceResponse newResourceResponse(final IResource.Attributes attributes) {
 
-        ResourceResponse response = new ResourceResponse();
+        AbstractResource.ResourceResponse response = new AbstractResource.ResourceResponse();
 
         try {
             HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+
+            if (!xsrfCheck(request)) {
+                LOG.error("XSRF TOKEN does not match");
+                response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN does not match");
+                return response;
+            }
+
             Credentials credentials = POJOHelper.deserialize(IOUtils.toString(request.getInputStream()),
                     Credentials.class);
             final String username = credentials.getUsername();
@@ -56,22 +65,21 @@ public class LoginResource extends AbstractBaseResource {
                 LOG.error("Could not read credentials from request: username is blank!");
                 response.setError(Response.Status.BAD_REQUEST.getStatusCode(),
                         "ErrorMessage{{ Could not read credentials from request: username is blank! }}");
-            } else // authenticate user
-             if (SyncopeEnduserSession.get().authenticate(username, password)) {
-                    // user has been authenticated successfully
-                    response.setWriteCallback(new WriteCallback() {
+            } else if (SyncopeEnduserSession.get().authenticate(username, password)) {
+                // user has been authenticated successfully
+                response.setWriteCallback(new WriteCallback() {
 
-                        @Override
-                        public void writeData(final Attributes attributes) throws IOException {
-                            attributes.getResponse().write(username);
-                        }
-                    });
-                    response.setStatusCode(Response.Status.OK.getStatusCode());
-                } else {
-                    // not authenticated
-                    response.setError(Response.Status.UNAUTHORIZED.getStatusCode(),
-                            "ErrorMessage{{ Username or password are incorrect }}");
-                }
+                    @Override
+                    public void writeData(final Attributes attributes) throws IOException {
+                        attributes.getResponse().write(username);
+                    }
+                });
+                response.setStatusCode(Response.Status.OK.getStatusCode());
+            } else {
+                // not authenticated
+                response.setError(Response.Status.UNAUTHORIZED.getStatusCode(),
+                        "ErrorMessage{{ Username or password are incorrect }}");
+            }
         } catch (Exception e) {
             LOG.error("Could not read credentials from request", e);
             response.setError(Response.Status.BAD_REQUEST.getStatusCode(), new StringBuilder()

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LogoutResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LogoutResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LogoutResource.java
index 545b44d..3101332 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LogoutResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/LogoutResource.java
@@ -31,7 +31,7 @@ public class LogoutResource extends AbstractBaseResource {
     @Override
     protected ResourceResponse newResourceResponse(final Attributes attributes) {
 
-        LOG.debug("Enduser logout");
+        LOG.debug("Logout from enduser application");
         
         SyncopeEnduserSession.get().invalidate();
         

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SchemaResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SchemaResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SchemaResource.java
index b909767..12ce2f1 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SchemaResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SchemaResource.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.enduser.resources;
 
 import java.io.IOException;
 import java.util.List;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.client.enduser.model.SchemaResponse;
@@ -61,6 +62,14 @@ public class SchemaResource extends AbstractBaseResource {
         AbstractResource.ResourceResponse response = new AbstractResource.ResourceResponse();
 
         try {
+            HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+
+            if (!xsrfCheck(request)) {
+                LOG.error("XSRF TOKEN does not match");
+                response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN does not match");
+                return response;
+            }
+
             final AnyTypeTO anyTypeUserTO = anyTypeService.read(AnyTypeKind.USER.name());
 
             final List<PlainSchemaTO> plainSchemas = schemaService.list(

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SecurityQuestionResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SecurityQuestionResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SecurityQuestionResource.java
index 4a03601..3f6c0ea 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SecurityQuestionResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SecurityQuestionResource.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.enduser.resources;
 
 import java.io.IOException;
 import java.util.List;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.common.lib.to.SecurityQuestionTO;
@@ -51,6 +52,14 @@ public class SecurityQuestionResource extends AbstractBaseResource {
 
         try {
 
+            HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+
+            if (!xsrfCheck(request)) {
+                LOG.error("XSRF TOKEN does not match");
+                response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN does not match");
+                return response;
+            }
+
             final List<SecurityQuestionTO> securityQuestionTOs = securityQuestionService.list();
 
             response.setWriteCallback(new AbstractResource.WriteCallback() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SyncopeResourceResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SyncopeResourceResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SyncopeResourceResource.java
index 0331ce1..350d442 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SyncopeResourceResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/SyncopeResourceResource.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.enduser.resources;
 
 import java.io.IOException;
 import java.util.List;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.client.enduser.adapters.ResourceTOAdapter;
@@ -54,6 +55,14 @@ public class SyncopeResourceResource extends AbstractBaseResource {
         AbstractResource.ResourceResponse response = new AbstractResource.ResourceResponse();
 
         try {
+
+            HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+            if (!xsrfCheck(request)) {
+                LOG.error("XSRF TOKEN does not match");
+                response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN does not match");
+                return response;
+            }
+
             final List<ResourceTO> resourceTOs = resourceService.list();
 
             response.setWriteCallback(new AbstractResource.WriteCallback() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
index d22b267..42b45fc 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfCreateResource.java
@@ -54,6 +54,12 @@ public class UserSelfCreateResource extends AbstractBaseResource {
         try {
             HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
 
+            if (!xsrfCheck(request)) {
+                LOG.error("XSRF TOKEN is not matching");
+                response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN is not matching");
+                return response;
+            }
+            
             final UserTORequest userTORequest = POJOHelper.deserialize(IOUtils.toString(request.getInputStream()),
                     UserTORequest.class);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
index c1d465f..fc4413b 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfReadResource.java
@@ -19,15 +19,17 @@
 package org.apache.syncope.client.enduser.resources;
 
 import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.enduser.SyncopeEnduserSession;
 import org.apache.syncope.client.enduser.adapters.UserTOAdapter;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
 import org.apache.wicket.request.resource.AbstractResource;
+import org.apache.wicket.request.resource.IResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class UserSelfReadResource extends AbstractResource {
+public class UserSelfReadResource extends AbstractBaseResource {
 
     private static final long serialVersionUID = -9184809392631523912L;
 
@@ -43,13 +45,20 @@ public class UserSelfReadResource extends AbstractResource {
     }
 
     @Override
-    protected ResourceResponse newResourceResponse(final Attributes attributes) {
+    protected ResourceResponse newResourceResponse(final IResource.Attributes attributes) {
 
         LOG.debug("Requested user self information");
 
         AbstractResource.ResourceResponse response = new AbstractResource.ResourceResponse();
         try {
 
+            HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+            if (!xsrfCheck(request)) {
+                LOG.error("XSRF TOKEN does not match");
+                response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN does not match");
+                return response;
+            }
+
             final String selfTOJson = POJOHelper.serialize(userTOAdapter.toUserTORequest(SyncopeEnduserSession.get().
                     getSelfTO()));
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
index 2737bdb..a44d53e 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
@@ -27,6 +27,8 @@ import org.apache.syncope.client.enduser.model.UserTORequest;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.rest.api.service.UserSelfService;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.apache.wicket.request.resource.IResource;
 import org.apache.wicket.util.io.IOUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -47,12 +49,17 @@ public class UserSelfUpdateResource extends AbstractBaseResource {
     }
 
     @Override
-    protected ResourceResponse newResourceResponse(final Attributes attributes) {
+    protected ResourceResponse newResourceResponse(final IResource.Attributes attributes) {
 
-        ResourceResponse response = new ResourceResponse();
+        AbstractResource.ResourceResponse response = new AbstractResource.ResourceResponse();
 
         try {
             HttpServletRequest request = (HttpServletRequest) attributes.getRequest().getContainerRequest();
+            if (!xsrfCheck(request)) {
+                LOG.error("XSRF TOKEN does not match");
+                response.setError(Response.Status.BAD_REQUEST.getStatusCode(), "XSRF TOKEN does not match");
+                return response;
+            }
 
             final UserTORequest userTOResponse = POJOHelper.deserialize(IOUtils.toString(request.getInputStream()),
                     UserTORequest.class);

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/resources/META-INF/resources/app/index.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/index.html b/client/enduser/src/main/resources/META-INF/resources/app/index.html
index 21f88d0..b684455 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/index.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/index.html
@@ -41,7 +41,7 @@ under the License.
     <![endif]-->
 
     <!--<div ng-view ng-cloak ng-controller="ApplicationController"></div>-->
-    <div ui-view ng-cloak ng-controller="ApplicationController"></div>
+    <div ui-view ng-cloak ng-controller="ApplicationController" ng-init="initApplication()"></div>
 
     <!--    <footer id="footer" class="hidden-print">
           <ul class="nav pull-right">

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
index 4792ea4..da0e46f 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/app.js
@@ -84,13 +84,13 @@ app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', 'growlProvi
               templateUrl: 'views/user-plain-schemas.html'
             })
             .state('create.derivedSchemas', {
-             url: '/derivedSchemas',
-             templateUrl: 'views/user-derived-schemas.html'
-             })
-             .state('create.virtualSchemas', {
-             url: '/virtualSchemas',
-             templateUrl: 'views/user-virtual-schemas.html'
-             })
+              url: '/derivedSchemas',
+              templateUrl: 'views/user-derived-schemas.html'
+            })
+            .state('create.virtualSchemas', {
+              url: '/virtualSchemas',
+              templateUrl: 'views/user-virtual-schemas.html'
+            })
             .state('create.resources', {
               url: '/resources',
               templateUrl: 'views/user-resources.html'
@@ -181,6 +181,8 @@ app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', 'growlProvi
 
     // HTTP service configuration
     $httpProvider.defaults.withCredentials = true;
+    $httpProvider.defaults.xsrfCookieName = 'XSRF-TOKEN';
+    $httpProvider.defaults.xsrfHeaderName = 'X-XSRF-TOKEN';
 
     $httpProvider.interceptors.push(function ($q, $rootScope, $location) {
       var numLoadings = 0;
@@ -268,23 +270,49 @@ app.run(['$rootScope', '$location', '$cookies', '$state',
 //        });
   }]);
 
-app.controller('ApplicationController', function ($scope) {
+app.controller('ApplicationController', ['$scope', '$rootScope', 'InfoService', function ($scope, $rootScope,
+          InfoService) {
 // DO NOTHING
+
+// get syncope info and set cookie, first call
+    $scope.initApplication = function () {
+// call info service
+      $rootScope.selfRegAllowed = false;
+      $rootScope.pwdResetAllowed = false;
+      $rootScope.version = "";
+      //info settings are initialized every time an user open the login page
+      InfoService.getInfo().then(
+              function (response) {
+                $rootScope.pwdResetAllowed = response.pwdResetAllowed;
+                $rootScope.selfRegAllowed = response.selfRegAllowed;
+                $rootScope.version = response.version;
+              },
+              function (response) {
+                console.log("Something went wrong while accessing info resource", response);
+              });
+
+      $rootScope.isSelfRegAllowed = function () {
+        return $rootScope.selfRegAllowed === true;
+      };
+      $rootScope.isPwdResetAllowed = function () {
+        return $rootScope.pwdResetAllowed === true;
+      };
+      $rootScope.getVersion = function () {
+        return $rootScope.version;
+      };
 //  $scope.$on('success', function (event, args) {
 //    console.log("IN CONFIG EVENTO: ", event)
 //    $scope.$broadcast("error", "success");
 //  });
-});
-
+    }
+  }]);
 app.factory('AuthenticationHelper', ['$q', '$rootScope',
   function ($q, $rootScope) {
     return {
       authenticated: function () {
 
         var currentUser = $rootScope.currentUser;
-
         console.log("AuthenticationHelper, currentUser: ", currentUser);
-
         if (angular.isDefined(currentUser) && currentUser) {
           return true;
         } else {

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
index 8c00fc8..46ac8ea 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/LoginController.js
@@ -20,8 +20,7 @@
 'use strict';
 
 angular.module("login").controller("LoginController", ['$scope', '$rootScope', '$http', '$location', '$cookies',
-  'AuthService', 'growl', 'InfoService', function ($scope, $rootScope, $http, $location, $cookies, AuthService, growl,
-          InfoService) {
+  'AuthService', 'growl', function ($scope, $rootScope, $http, $location, $cookies, AuthService, growl) {
 
     $scope.credentials = {
       username: '',
@@ -31,19 +30,14 @@ angular.module("login").controller("LoginController", ['$scope', '$rootScope', '
 
     $scope.login = function (credentials) {
 
-      console.log("CREDENTIALS FROM PAGE: ", credentials);
-      console.log("AUTHSERVICE: ", AuthService);
-
       AuthService.login($scope.credentials).then(function (user) {
-        console.log("LOGIN SUCCESS FOR: ", user);
-        console.log("DOPO AVER SETTATO CURRENT USER: ", $rootScope.currentUser);
-        console.log("COOKIE CURRENT USER: ", $cookies.get('currentUser'));
+        console.log("Login success for: ", user);
         // reset error message
         $scope.credentials.errorMessage = '';
         // got to update page
         $location.path("/self/update");
       }, function (response) {
-        console.log("LOGIN FAILED: ", response);
+        console.log("Login failed for: ", response);
         var errorMessage;
         // parse error response 
         if (response !== undefined) {
@@ -56,13 +50,10 @@ angular.module("login").controller("LoginController", ['$scope', '$rootScope', '
     };
 
     $scope.logout = function () {
-
-      console.log("PERFORMING LOGOUT");
-
       AuthService.logout().then(function (response) {
-        console.log("LOGOUT SUCCESS: ", response);
-      }, function () {
-        console.log("LOGOUT FAILED");
+        console.log("Logout successfully");
+      }, function (response) {
+        console.log("Logout failed: ", response);
       });
     };
 
@@ -96,32 +87,4 @@ angular.module("login").controller("LoginController", ['$scope', '$rootScope', '
         console.log("schemaAPI response: ", data);
       });
     };
-
-    $scope.selfRegAllowed = false;
-    $scope.pwdResetAllowed = false;
-    $scope.version = "";
-    
-    //info settings are initialized every time an user open the login page
-    InfoService.getInfo().then(
-            function (response) {
-              $scope.pwdResetAllowed = response.pwdResetAllowed;              
-              $scope.selfRegAllowed = response.selfRegAllowed;
-              $scope.version = response.version;
-            },
-            function () {
-              console.log("Something went wrong while accessing info resource", response);
-            });
-            
-    $scope.isSelfRegAllowed = function () {
-      return $scope.selfRegAllowed == true;
-    };
-    
-    $scope.isPwdResetAllowed = function () {
-      return $scope.pwdResetAllowed == true;
-    };
-
-    $scope.getVersion = function () {
-      return $scope.version;
-    };
-
   }]);

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/resources/META-INF/resources/app/js/services/infoService.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/infoService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/infoService.js
index 1f71e27..9c58cf7 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/services/infoService.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/infoService.js
@@ -19,7 +19,7 @@
 
 'use strict';
 
-angular.module('info')
+angular.module('SyncopeEnduserApp')
         .factory('InfoService', ['$resource', '$q', '$http',
           function ($resource, $q, $http) {
 
@@ -32,6 +32,7 @@ angular.module('info')
                         return response.data;
                       }, function (response) {
                         console.log("Something went wrong while retrieving info resource", response);
+                        return $q.reject(response.data || response.statusText);
                       });
             };
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/views/self.html b/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
index 93d85fb..a684ec6 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/views/self.html
@@ -84,14 +84,14 @@ under the License.
           </div>
 
         </div>
-        <div class="text-center" ng-show="!isLogged() && isSelfRegAllowed()">
+        <div class="text-center" ng-show="!isLogged() && $root.isSelfRegAllowed()">
           <a href="javascript:void(0);" class="btn btn-link" ng-click="selfCreate()">Self Registration</a>
 
           <!--      <div id="initialLoaderDiv">
                   <img src="img/busy.gif" class="ajax-loader"/>
                 </div>-->
         </div>
-        <div class="text-center" ng-show="!isLogged() && isPwdResetAllowed()">
+        <div class="text-center" ng-show="!isLogged() && $root.isPwdResetAllowed()">
           <a href="javascript:void(0);" class="btn btn-link" ng-click="passwordReset()">Password Reset</a>
         </div>
         <!-- /#login-container -->

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/lib/pom.xml
----------------------------------------------------------------------
diff --git a/client/lib/pom.xml b/client/lib/pom.xml
index ef5481c..134497e 100644
--- a/client/lib/pom.xml
+++ b/client/lib/pom.xml
@@ -62,6 +62,11 @@ under the License.
     </dependency>  
     
     <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
+    
+    <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e8368e1/client/lib/src/main/java/org/apache/syncope/client/lib/SaltGenerator.java
----------------------------------------------------------------------
diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/SaltGenerator.java b/client/lib/src/main/java/org/apache/syncope/client/lib/SaltGenerator.java
new file mode 100644
index 0000000..911a49b
--- /dev/null
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SaltGenerator.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.client.lib;
+
+import java.security.SecureRandom;
+import java.util.Base64;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class SaltGenerator {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SaltGenerator.class);
+
+    public static String generate(final String input) {
+        // generate salt
+        byte[] salt = new byte[16];
+        // fill array with random bytes
+        new SecureRandom().nextBytes(salt);
+        // create digest with MD5
+        return DigestUtils.md2Hex(input + Base64.getEncoder().encodeToString(salt));
+    }
+
+    private SaltGenerator() {
+    }
+}