You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by sk...@apache.org on 2018/03/29 11:57:35 UTC

syncope git commit: [SYNCOPE-1148] Added new option for SAML extension - SAML-initiated self-registration

Repository: syncope
Updated Branches:
  refs/heads/2_0_X b513d7af3 -> 31493e5d2


[SYNCOPE-1148] Added new option for SAML extension - SAML-initiated self-registration


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

Branch: refs/heads/2_0_X
Commit: 31493e5d2fc95e94460e02b8fa884ffc50758017
Parents: b513d7a
Author: skylark17 <ma...@tirasa.net>
Authored: Thu Mar 29 13:57:24 2018 +0200
Committer: skylark17 <ma...@tirasa.net>
Committed: Thu Mar 29 13:57:24 2018 +0200

----------------------------------------------------------------------
 .../markup/html/form/AjaxCheckBoxPanel.html     |  2 +-
 .../syncope/client/enduser/pages/HomePage.java  |  2 +
 .../META-INF/resources/app/css/app.css          |  4 +-
 .../resources/META-INF/resources/app/index.html |  2 +
 .../resources/META-INF/resources/app/js/app.js  | 13 ++++
 .../app/js/controllers/LoginController.js       |  4 ++
 .../app/js/controllers/SAML2SPController.js     | 29 +++++++++
 .../app/js/controllers/UserController.js        | 30 +++++++++
 .../app/js/services/saml2IdPService.js          |  3 +-
 .../resources/app/js/services/saml2SPService.js | 42 +++++++++++++
 .../META-INF/resources/app/views/self.html      |  6 +-
 .../ext/saml2lsp/agent/AssertionConsumer.java   | 38 +++++++++---
 .../syncope/ext/saml2lsp/agent/Constants.java   |  4 ++
 .../client/console/pages/SAML2SPSelfReg.java    | 38 ++++++++++++
 .../console/wizards/SAML2IdPWizardBuilder.java  |  4 ++
 .../panels/SAML2IdPsDirectoryPanel.properties   |  1 +
 .../SAML2IdPsDirectoryPanel_it.properties       |  1 +
 .../SAML2IdPsDirectoryPanel_pt_BR.properties    |  1 +
 .../SAML2IdPsDirectoryPanel_ru.properties       |  1 +
 .../client/enduser/pages/SAML2SPSelfReg.java    | 50 +++++++++++++++
 .../resources/SAML2SPUserAttrsResource.java     | 65 ++++++++++++++++++++
 .../syncope/common/lib/to/SAML2IdPTO.java       | 10 +++
 .../common/lib/to/SAML2LoginResponseTO.java     | 10 +++
 .../apache/syncope/core/logic/SAML2SPLogic.java | 17 +++++
 .../core/logic/saml2/SAML2IdPEntity.java        |  4 ++
 .../core/logic/saml2/SAML2UserManager.java      |  2 +-
 .../core/persistence/api/entity/SAML2IdP.java   |  4 ++
 .../persistence/jpa/entity/JPASAML2IdP.java     | 15 +++++
 .../validation/entity/SAML2IdPValidator.java    | 10 +++
 .../java/data/SAML2IdPDataBinderImpl.java       |  2 +
 .../src/main/webapp/WEB-INF/web.xml             |  5 ++
 .../src/main/webapp/WEB-INF/web.xml             |  5 ++
 32 files changed, 410 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.html
index 17289db..e2efccd 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.html
@@ -23,7 +23,7 @@ under the License.
   <body>
     <wicket:extend>
       <div class="checkbox">
-        <label  style="width:100%">
+        <label style="width:100%">
           <input type="checkbox" wicket:id="checkboxField" />
           <wicket:enclosure child="field-label">
             <label wicket:id="field-label">[LABEL]</label><span wicket:id="required"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/client/enduser/src/main/java/org/apache/syncope/client/enduser/pages/HomePage.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/pages/HomePage.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/pages/HomePage.java
index ef9ab90..1e78222 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/pages/HomePage.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/pages/HomePage.java
@@ -38,6 +38,8 @@ public class HomePage extends WebPage {
         } else if (!parameters.get("successMessage").isNull()) {
             redirectUrl.append("#!self?successMessage=");
             appendMessage(redirectUrl, parameters.get("successMessage").toString());
+        } else if (!parameters.get("saml2SPUserAttrs").isNull()) {
+            redirectUrl.append("#!self-saml2sp");
         }
         throw new NonResettingRestartException(redirectUrl.toString());
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/client/enduser/src/main/resources/META-INF/resources/app/css/app.css
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/css/app.css b/client/enduser/src/main/resources/META-INF/resources/app/css/app.css
index 1e7b3c4..721abf7 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/css/app.css
+++ b/client/enduser/src/main/resources/META-INF/resources/app/css/app.css
@@ -72,10 +72,10 @@ under the License.
   z-index : 10001;
 }
 
-treasure-overlay-spinner.treasure-overlay-spinner-active .treasure-overlay-spinner-content {
+treasure-overlay-spinner .treasure-overlay-spinner-content {
   height: 100%;
 }
-treasure-overlay-spinner.treasure-overlay-spinner-active {
+treasure-overlay-spinner {
   height: 100%;
   top: 0;
   bottom: 0;

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/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 33b8f07..cd4542a 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/index.html
+++ b/client/enduser/src/main/resources/META-INF/resources/app/index.html
@@ -100,9 +100,11 @@ under the License.
   <script src="js/services/groupService.js"></script>
   <script src="js/services/anyService.js"></script>
   <script src="js/services/saml2IdPService.js"></script>
+  <script src="js/services/saml2SPService.js"></script>
   <!--controllers-->
   <script src="js/controllers/HomeController.js"></script>
   <script src="js/controllers/LoginController.js"></script>
+  <script src="js/controllers/SAML2SPController.js"></script>
   <script src="js/controllers/UserController.js"></script>
   <!--directives-->
   <script src="js/directives/dynamicPlainAttribute.js"></script>

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/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 c1f47df..d4857a0 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
@@ -73,6 +73,19 @@ app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider', '$translate
               url: '/self?errorMessage',
               templateUrl: 'views/self.html'
             })
+            /* <Extensions> */
+            .state('self-saml2sp', {
+              url: '/self-saml2sp',
+              templateUrl: 'views/self.html',
+              controller: 'SAML2SPController',
+              resolve: {
+                'userAttrs': ['SAML2SPService',
+                  function (SAML2SPService) {
+                    return SAML2SPService.getSAML2SPUserAttrs();
+                  }]
+              }
+            })
+            /* <Extensions> */
             .state('user-self-update', {
               url: '/user-self-update',
               templateUrl: 'views/home.html',

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/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 1b68e07..b58aced 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
@@ -61,12 +61,15 @@ angular.module("login").controller("LoginController", ['$scope', '$rootScope', '
         console.error("error retrieving user login status", response);
       });
     };
+
     $scope.selfCreate = function () {
       $location.path("/self/create");
     };
+
     $scope.passwordReset = function () {
       $location.path("/passwordreset");
     };
+
     $scope.$watch(function () {
       return $location.search().successMessage;
     }, function (successMessage) {
@@ -76,6 +79,7 @@ angular.module("login").controller("LoginController", ['$scope', '$rootScope', '
         delete $location.$$search.successMessage;
       }
     });
+
     $scope.$watch(function () {
       return $location.search().errorMessage;
     }, function (errorMessage) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/SAML2SPController.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/SAML2SPController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/SAML2SPController.js
new file mode 100644
index 0000000..05adf18
--- /dev/null
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/SAML2SPController.js
@@ -0,0 +1,29 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+'use strict';
+angular.module("login").controller("SAML2SPController", function ($scope, $rootScope, $location, userAttrs) {
+  $scope.selfCreate = function () {
+    $location.path("/self/create");
+  };
+
+  $rootScope.saml2idps.userAttrs = userAttrs;
+
+  $scope.selfCreate();
+});

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js
index d682cde..ec380bd 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/controllers/UserController.js
@@ -43,6 +43,10 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l
       value: ""
     };
 
+    /* <Extensions> */
+    $scope.loadFromSAML2AuthSelfReg = $rootScope.saml2idps.userAttrs && $rootScope.saml2idps.userAttrs.length;
+    /* <Extensions> */
+
     $scope.initUser = function () {
       $scope.dynamicForm = {
         plainSchemas: [],
@@ -61,6 +65,12 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l
         groupSchemas: ['own']
       };
 
+      var findLoadedSAML2AttrValue = function (schemaKey) {
+        var found = $filter('filter')($rootScope.saml2idps.userAttrs, {"schema": schemaKey}, true);
+        return (found && found.length && found[0].values && found[0].values.length)
+                ? found[0].values : [];
+      };
+
       var initUserSchemas = function (anyTypeClass, group) {
         // initialization is done here synchronously to have all schema fields populated correctly
         var schemaService;
@@ -113,6 +123,11 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l
               schema: plainSchemaKey,
               values: initialAttributeValues
             };
+
+            if ($scope.loadFromSAML2AuthSelfReg) {
+              $scope.user.plainAttrs[plainSchemaKey].values = findLoadedSAML2AttrValue(plainSchemaKey);
+            }
+
             if (schemas.plainSchemas[i].multivalue) {
               // initialize multivalue schema and support table: create mode, default multivalues
               if (initialAttributeValues.length > 0) {
@@ -162,6 +177,11 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l
               schema: virSchemaKey,
               values: []
             };
+
+            if ($scope.loadFromSAML2AuthSelfReg) {
+              $scope.user.virAttrs[virSchemaKey].values = findLoadedSAML2AttrValue(virSchemaKey);
+            }
+
             // initialize multivalue attribute and support table: create mode, only first value
             $scope.dynamicForm.virtualAttributeTable[schemas.virSchemas[i].key] = {
               fields: [schemas.virSchemas[i].key + "_" + 0]
@@ -182,6 +202,9 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l
         $scope.dynamicForm.plainSchemas = $scope.dynamicForm.plainSchemas.concat(schemas.plainSchemas);
         $scope.dynamicForm.derSchemas = $scope.dynamicForm.derSchemas.concat(schemas.derSchemas);
         $scope.dynamicForm.virSchemas = $scope.dynamicForm.virSchemas.concat(schemas.virSchemas);
+
+        //clean SAML Self Reg user attributes variable
+        delete $rootScope.saml2idps.userAttrs;
       };
 
       var initSecurityQuestions = function () {
@@ -421,6 +444,13 @@ angular.module("self").controller("UserController", ['$scope', '$rootScope', '$l
           initUserSchemas(null, $scope.dynamicForm.selectedGroups[index]);
         }
         initProperties();
+
+        if ($scope.loadFromSAML2AuthSelfReg) {
+          var username = findLoadedSAML2AttrValue("username");
+          if (username.length) {
+            $scope.user.username = username[0];
+          }
+        }
       } else {
         // read user from syncope core
         readUser();

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/client/enduser/src/main/resources/META-INF/resources/app/js/services/saml2IdPService.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/saml2IdPService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/saml2IdPService.js
index 0c61bf1..7db0056 100644
--- a/client/enduser/src/main/resources/META-INF/resources/app/js/services/saml2IdPService.js
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/saml2IdPService.js
@@ -30,7 +30,8 @@ angular.module('self')
                       .then(function (response) {
                         return response.data;
                       }, function (response) {
-                        console.error("Something went wrong during saml2Idp extesion retrieval, exit with status: ", response);
+                        console.error("Something went wrong during saml2Idp extension retrieval, exit with status: ",
+                                response);
                         return $q.reject(response.data || response.statusText);
                       });
             };

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/client/enduser/src/main/resources/META-INF/resources/app/js/services/saml2SPService.js
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/resources/META-INF/resources/app/js/services/saml2SPService.js b/client/enduser/src/main/resources/META-INF/resources/app/js/services/saml2SPService.js
new file mode 100644
index 0000000..85ac6a0
--- /dev/null
+++ b/client/enduser/src/main/resources/META-INF/resources/app/js/services/saml2SPService.js
@@ -0,0 +1,42 @@
+/* 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+'use strict';
+
+angular.module('self')
+        .factory('SAML2SPService', ['$q', '$http',
+          function ($q, $http) {
+
+            var saml2SPService = {};
+
+            saml2SPService.getSAML2SPUserAttrs = function () {
+              return $http.get("../api/saml2SPs/userAttrs")
+                      .then(function (response) {
+                        return response.data;
+                      }, function (response) {
+                        console.error("Something went wrong while getting saml2 user attributes, exit with status: ",
+                                response);
+                        return $q.reject(response.data || response.statusText);
+                      });
+            };
+
+            return saml2SPService;
+          }]);
+
+

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/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 c7f41a2..1cc279e 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
@@ -35,11 +35,13 @@ under the License.
             <form id="login-form" class="form form-signin" novalidate>
               <fieldset class="form-group input-group">
                 <div class="form-group">
-                  <input autofocus="autofocus" type="text" class="form-control" id="login-username" placeholder="{{'USERNAME_PLACEHOLDER'| translate}}"
+                  <input autofocus="autofocus" type="text" class="form-control" id="login-username" 
+                         placeholder="{{'USERNAME_PLACEHOLDER'| translate}}"
                          ng-required ng-model="credentials.username">
                 </div>
                 <div class="form-group">
-                  <input type="password" class="form-control" id="login-password" placeholder="{{'PASSWORD_PLACEHOLDER'| translate}}" 
+                  <input type="password" class="form-control" id="login-password" 
+                         placeholder="{{'PASSWORD_PLACEHOLDER'| translate}}" 
                          ng-required ng-model="credentials.password">
                 </div>
                 <div class="form-group" ng-controller="UserController">

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/AssertionConsumer.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/AssertionConsumer.java b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/AssertionConsumer.java
index a2fec3a..aae650b 100644
--- a/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/AssertionConsumer.java
+++ b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/AssertionConsumer.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.ext.saml2lsp.agent;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import java.io.IOException;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
@@ -27,6 +29,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.SAML2LoginResponseTO;
 import org.apache.syncope.common.rest.api.service.SAML2SPService;
 
@@ -35,6 +38,9 @@ public class AssertionConsumer extends AbstractSAML2SPServlet {
 
     private static final long serialVersionUID = 968480296813639041L;
 
+    private static final ObjectMapper MAPPER =
+            new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+
     @Override
     protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
             throws ServletException, IOException {
@@ -49,15 +55,33 @@ public class AssertionConsumer extends AbstractSAML2SPServlet {
                             request.getRemoteAddr(),
                             request.getInputStream()));
 
-            request.getSession(true).setAttribute(Constants.SAML2SPJWT, responseTO.getAccessToken());
-            request.getSession(true).setAttribute(Constants.SAML2SPJWT_EXPIRE, responseTO.getAccessTokenExpiryTime());
+            if (responseTO.isSelfReg()) {
+                responseTO.getAttrs().add(
+                        new AttrTO.Builder().schema("username").values(responseTO.getUsername()).build());
+                request.getSession(true).
+                        setAttribute(Constants.SAML2SP_USER_ATTRS, MAPPER.writeValueAsString(responseTO.getAttrs()));
 
-            String successURL = getServletContext().getInitParameter(Constants.CONTEXT_PARAM_LOGIN_SUCCESS_URL);
-            if (successURL == null) {
-                request.setAttribute("responseTO", responseTO);
-                request.getRequestDispatcher("loginSuccess.jsp").forward(request, response);
+                String selfRegRedirectURL =
+                        getServletContext().getInitParameter(Constants.CONTEXT_PARAM_REDIRECT_SELFREG_URL);
+                if (selfRegRedirectURL == null) {
+                    request.setAttribute("responseTO", responseTO);
+                    request.getRequestDispatcher("loginSuccess.jsp").forward(request, response);
+                } else {
+                    response.sendRedirect(selfRegRedirectURL);
+                }
             } else {
-                response.sendRedirect(successURL + "?sloSupported=" + responseTO.isSloSupported());
+                request.getSession(true).
+                        setAttribute(Constants.SAML2SPJWT, responseTO.getAccessToken());
+                request.getSession(true).
+                        setAttribute(Constants.SAML2SPJWT_EXPIRE, responseTO.getAccessTokenExpiryTime());
+
+                String successURL = getServletContext().getInitParameter(Constants.CONTEXT_PARAM_LOGIN_SUCCESS_URL);
+                if (successURL == null) {
+                    request.setAttribute("responseTO", responseTO);
+                    request.getRequestDispatcher("loginSuccess.jsp").forward(request, response);
+                } else {
+                    response.sendRedirect(successURL + "?sloSupported=" + responseTO.isSloSupported());
+                }
             }
         } catch (Exception e) {
             LOG.error("While processing authentication response from IdP", e);

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/Constants.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/Constants.java b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/Constants.java
index b7da815..c02c582 100644
--- a/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/Constants.java
+++ b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/Constants.java
@@ -34,10 +34,14 @@ public final class Constants {
 
     public static final String CONTEXT_PARAM_LOGOUT_ERROR_URL = "saml2sp.logout.error.url";
 
+    public static final String CONTEXT_PARAM_REDIRECT_SELFREG_URL = "saml2sp.redirect.selfreg";
+
     public static final String SAML2SPJWT = "saml2sp.jwt";
 
     public static final String SAML2SPJWT_EXPIRE = "saml2sp.jwt.expire";
 
+    public static final String SAML2SP_USER_ATTRS = "saml2sp.userattrs";
+
     private Constants() {
         // private constructor for static utility class
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/client-console/src/main/java/org/apache/syncope/client/console/pages/SAML2SPSelfReg.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/client-console/src/main/java/org/apache/syncope/client/console/pages/SAML2SPSelfReg.java b/ext/saml2sp/client-console/src/main/java/org/apache/syncope/client/console/pages/SAML2SPSelfReg.java
new file mode 100644
index 0000000..c7633e8
--- /dev/null
+++ b/ext/saml2sp/client-console/src/main/java/org/apache/syncope/client/console/pages/SAML2SPSelfReg.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.client.console.pages;
+
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+public class SAML2SPSelfReg extends WebPage {
+
+    private static final long serialVersionUID = -4330637558823990359L;
+
+    private static final String SAML_ACCESS_ERROR = 
+            "SAML 2.0 error - Admin Console does not support Self Registration";
+
+    public SAML2SPSelfReg(final PageParameters parameters) {
+        super(parameters);
+
+        PageParameters params = new PageParameters();
+        params.add("errorMessage", SAML_ACCESS_ERROR);
+        setResponsePage(Login.class, params);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/client-console/src/main/java/org/apache/syncope/client/console/wizards/SAML2IdPWizardBuilder.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/client-console/src/main/java/org/apache/syncope/client/console/wizards/SAML2IdPWizardBuilder.java b/ext/saml2sp/client-console/src/main/java/org/apache/syncope/client/console/wizards/SAML2IdPWizardBuilder.java
index 3376e64..53e342f 100644
--- a/ext/saml2sp/client-console/src/main/java/org/apache/syncope/client/console/wizards/SAML2IdPWizardBuilder.java
+++ b/ext/saml2sp/client-console/src/main/java/org/apache/syncope/client/console/wizards/SAML2IdPWizardBuilder.java
@@ -111,6 +111,10 @@ public class SAML2IdPWizardBuilder extends AjaxWizardBuilder<SAML2IdPTO> {
                     "field", "createUnmatching", new PropertyModel<Boolean>(idpTO, "createUnmatching"), false);
             fields.add(createUnmatching);
 
+            AjaxCheckBoxPanel selfRegUnmatching = new AjaxCheckBoxPanel(
+                    "field", "selfRegUnmatching", new PropertyModel<Boolean>(idpTO, "selfRegUnmatching"), false);
+            fields.add(selfRegUnmatching);
+
             AjaxCheckBoxPanel updateMatching = new AjaxCheckBoxPanel(
                     "field", "updateMatching", new PropertyModel<Boolean>(idpTO, "updateMatching"), false);
             fields.add(updateMatching);

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel.properties
----------------------------------------------------------------------
diff --git a/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel.properties b/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel.properties
index 60b2a65..c2ecfe3 100644
--- a/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel.properties
+++ b/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel.properties
@@ -26,3 +26,4 @@ createUnmatching=Create unmatching users
 updateMatching=Update matching users
 actionsClassNames=Actions
 template.title=user template
+selfRegUnmatching=SAML-initiated self-registration

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_it.properties
----------------------------------------------------------------------
diff --git a/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_it.properties b/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_it.properties
index f1afdad..bf8fa9e 100644
--- a/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_it.properties
+++ b/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_it.properties
@@ -26,3 +26,4 @@ createUnmatching=Create unmatching users
 updateMatching=Update matching users
 actionsClassNames=Azioni
 template.title=template utenti
+selfRegUnmatching=SAML-initiated self-registration

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_pt_BR.properties
----------------------------------------------------------------------
diff --git a/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_pt_BR.properties b/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_pt_BR.properties
index f7bedbe..4836116 100644
--- a/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_pt_BR.properties
+++ b/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_pt_BR.properties
@@ -26,3 +26,4 @@ createUnmatching=Create unmatching users
 updateMatching=Update matching users
 actionsClassNames=Actions
 template.title=user template
+selfRegUnmatching=SAML-initiated self-registration

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_ru.properties
----------------------------------------------------------------------
diff --git a/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_ru.properties b/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_ru.properties
index 311846b..f003174 100644
--- a/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_ru.properties
+++ b/ext/saml2sp/client-console/src/main/resources/org/apache/syncope/client/console/panels/SAML2IdPsDirectoryPanel_ru.properties
@@ -26,3 +26,4 @@ createUnmatching=Create unmatching users
 updateMatching=Update matching users
 actionsClassNames=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f
 template.title=user template
+selfRegUnmatching=SAML-initiated self-registration

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/SAML2SPSelfReg.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/SAML2SPSelfReg.java b/ext/saml2sp/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/SAML2SPSelfReg.java
new file mode 100644
index 0000000..d7d2b45
--- /dev/null
+++ b/ext/saml2sp/client-enduser/src/main/java/org/apache/syncope/client/enduser/pages/SAML2SPSelfReg.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.enduser.pages;
+
+import org.apache.syncope.ext.saml2lsp.agent.Constants;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SAML2SPSelfReg extends WebPage {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SAML2SPSelfReg.class);
+
+    private static final long serialVersionUID = -4330637558823990359L;
+
+    private static final String SAML_ACCESS_ERROR = "SAML 2.0 error - while getting user attributes";
+
+    public SAML2SPSelfReg(final PageParameters parameters) {
+        super(parameters);
+
+        PageParameters params = new PageParameters();
+        try {
+            params.add("saml2SPUserAttrs", ((ServletWebRequest) getRequest()).getContainerRequest().
+                    getSession().getAttribute(Constants.SAML2SP_USER_ATTRS));
+        } catch (Exception e) {
+            LOG.error("While extracting user attributes", e);
+
+            params.add("errorMessage", SAML_ACCESS_ERROR);
+        }
+        setResponsePage(getApplication().getHomePage(), params);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/SAML2SPUserAttrsResource.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/SAML2SPUserAttrsResource.java b/ext/saml2sp/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/SAML2SPUserAttrsResource.java
new file mode 100644
index 0000000..9d6e6af
--- /dev/null
+++ b/ext/saml2sp/client-enduser/src/main/java/org/apache/syncope/client/enduser/resources/SAML2SPUserAttrsResource.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.enduser.resources;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.client.enduser.annotations.Resource;
+import org.apache.syncope.ext.saml2lsp.agent.Constants;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.apache.wicket.request.resource.IResource;
+
+@Resource(key = "saml2SPs", path = "/api/saml2SPs/userAttrs")
+public class SAML2SPUserAttrsResource extends BaseResource {
+
+    private static final long serialVersionUID = 7273151109078469253L;
+
+    @Override
+    protected ResourceResponse newResourceResponse(final IResource.Attributes attributes) {
+        ResourceResponse response = new ResourceResponse();
+        response.setContentType(MediaType.APPLICATION_JSON);
+
+        try {
+            response.setTextEncoding(StandardCharsets.UTF_8.name());
+            response.setWriteCallback(new AbstractResource.WriteCallback() {
+
+                @Override
+                public void writeData(final Attributes attributes) throws IOException {
+                    attributes.getResponse().write(
+                            (CharSequence) ((HttpServletRequest) RequestCycle.get().getRequest().
+                                    getContainerRequest()).getSession().getAttribute(Constants.SAML2SP_USER_ATTRS));
+                }
+            });
+            response.setStatusCode(Response.Status.OK.getStatusCode());
+        } catch (Exception e) {
+            LOG.error("Error retrieving saml2 user attributes", e);
+            response.setError(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), new StringBuilder()
+                    .append("ErrorMessage{{ ")
+                    .append(e.getMessage())
+                    .append(" }}")
+                    .toString());
+        }
+
+        return response;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/common-lib/src/main/java/org/apache/syncope/common/lib/to/SAML2IdPTO.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/common-lib/src/main/java/org/apache/syncope/common/lib/to/SAML2IdPTO.java b/ext/saml2sp/common-lib/src/main/java/org/apache/syncope/common/lib/to/SAML2IdPTO.java
index 12f53ab..aa2d2af 100644
--- a/ext/saml2sp/common-lib/src/main/java/org/apache/syncope/common/lib/to/SAML2IdPTO.java
+++ b/ext/saml2sp/common-lib/src/main/java/org/apache/syncope/common/lib/to/SAML2IdPTO.java
@@ -51,6 +51,8 @@ public class SAML2IdPTO extends AbstractBaseBean implements EntityTO, ItemContai
 
     private boolean updateMatching;
 
+    private boolean selfRegUnmatching;
+
     private boolean useDeflateEncoding;
 
     private boolean supportUnsolicited;
@@ -108,6 +110,14 @@ public class SAML2IdPTO extends AbstractBaseBean implements EntityTO, ItemContai
         this.createUnmatching = createUnmatching;
     }
 
+    public boolean isSelfRegUnmatching() {
+        return selfRegUnmatching;
+    }
+
+    public void setSelfRegUnmatching(final boolean selfRegUnmatching) {
+        this.selfRegUnmatching = selfRegUnmatching;
+    }
+
     public boolean isUpdateMatching() {
         return updateMatching;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/common-lib/src/main/java/org/apache/syncope/common/lib/to/SAML2LoginResponseTO.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/common-lib/src/main/java/org/apache/syncope/common/lib/to/SAML2LoginResponseTO.java b/ext/saml2sp/common-lib/src/main/java/org/apache/syncope/common/lib/to/SAML2LoginResponseTO.java
index 2b02eb4..4c1f122 100644
--- a/ext/saml2sp/common-lib/src/main/java/org/apache/syncope/common/lib/to/SAML2LoginResponseTO.java
+++ b/ext/saml2sp/common-lib/src/main/java/org/apache/syncope/common/lib/to/SAML2LoginResponseTO.java
@@ -57,6 +57,8 @@ public class SAML2LoginResponseTO extends AbstractBaseBean {
 
     private boolean sloSupported;
 
+    private boolean selfReg;
+
     public String getNameID() {
         return nameID;
     }
@@ -161,4 +163,12 @@ public class SAML2LoginResponseTO extends AbstractBaseBean {
         this.sloSupported = sloSupported;
     }
 
+    public boolean isSelfReg() {
+        return selfReg;
+    }
+
+    public void setSelfReg(final boolean selfReg) {
+        this.selfReg = selfReg;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/SAML2SPLogic.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/SAML2SPLogic.java b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/SAML2SPLogic.java
index 8fe4e5a..3b68c48 100644
--- a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/SAML2SPLogic.java
+++ b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/SAML2SPLogic.java
@@ -45,6 +45,7 @@ import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.SAML2RequestTO;
 import org.apache.syncope.common.lib.to.SAML2LoginResponseTO;
 import org.apache.syncope.common.lib.to.SAML2ReceivedResponseTO;
+import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.SAML2BindingType;
@@ -502,6 +503,22 @@ public class SAML2SPLogic extends AbstractSAML2Logic<AbstractBaseBean> {
                         return userManager.create(idp, responseTO, nameIDValue);
                     }
                 });
+            } else if (idp.isSelfRegUnmatching()) {
+                responseTO.setNameID(nameID.getValue());
+                UserTO userTO = new UserTO();
+
+                userManager.fill(idp, responseTO, userTO);
+
+                responseTO.getAttrs().clear();
+                responseTO.getAttrs().addAll(userTO.getPlainAttrs());
+                responseTO.getAttrs().addAll(userTO.getVirAttrs());
+                if (StringUtils.isNotBlank(userTO.getUsername())) {
+                    responseTO.setUsername(userTO.getUsername());
+                }
+                
+                responseTO.setSelfReg(true);
+
+                return responseTO;
             } else {
                 throw new NotFoundException("User matching the provided value " + keyValue);
             }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2IdPEntity.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2IdPEntity.java b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2IdPEntity.java
index 7b44396..dfc3617 100644
--- a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2IdPEntity.java
+++ b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2IdPEntity.java
@@ -128,6 +128,10 @@ public class SAML2IdPEntity {
         return idpTO.isCreateUnmatching();
     }
 
+    public boolean isSelfRegUnmatching() {
+        return idpTO.isSelfRegUnmatching();
+    }
+
     public boolean isUpdateMatching() {
         return idpTO.isUpdateMatching();
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
index f4374e6..3a3cc48 100644
--- a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
+++ b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
@@ -192,7 +192,7 @@ public class SAML2UserManager {
         return actions;
     }
 
-    private void fill(final SAML2IdPEntity idp, final SAML2LoginResponseTO responseTO, final UserTO userTO) {
+    public void fill(final SAML2IdPEntity idp, final SAML2LoginResponseTO responseTO, final UserTO userTO) {
         for (ItemTO item : idp.getItems()) {
             List<String> values = Collections.emptyList();
             AttrTO samlAttr = responseTO.getAttr(item.getExtAttrName());

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java b/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
index 44c2c3a..fecf121 100644
--- a/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
+++ b/ext/saml2sp/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/SAML2IdP.java
@@ -40,6 +40,10 @@ public interface SAML2IdP extends Entity {
 
     void setCreateUnmatching(boolean createUnmatching);
 
+    boolean isSelfRegUnmatching();
+
+    void setSelfRegUnmatching(boolean selfRegUnmatching);
+
     boolean isUpdateMatching();
 
     void setUpdateMatching(boolean updateMatching);

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
index f15d9b4..1b9e4db 100644
--- a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
+++ b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java
@@ -77,6 +77,11 @@ public class JPASAML2IdP extends AbstractGeneratedKeyEntity implements SAML2IdP
     @Min(0)
     @Max(1)
     @Column(nullable = false)
+    private Integer selfRegUnmatching;
+
+    @Min(0)
+    @Max(1)
+    @Column(nullable = false)
     private Integer updateMatching;
 
     @Min(0)
@@ -143,6 +148,16 @@ public class JPASAML2IdP extends AbstractGeneratedKeyEntity implements SAML2IdP
     }
 
     @Override
+    public boolean isSelfRegUnmatching() {
+        return isBooleanAsInteger(selfRegUnmatching);
+    }
+
+    @Override
+    public void setSelfRegUnmatching(final boolean selfRegUnmatching) {
+        this.selfRegUnmatching = getBooleanAsInteger(selfRegUnmatching);
+    }
+
+    @Override
     public boolean isUpdateMatching() {
         return isBooleanAsInteger(updateMatching);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
index 225c6d1..c03d701 100644
--- a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
+++ b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SAML2IdPValidator.java
@@ -30,6 +30,16 @@ public class SAML2IdPValidator extends AbstractValidator<SAML2IdPCheck, SAML2IdP
 
     @Override
     public boolean isValid(final SAML2IdP value, final ConstraintValidatorContext context) {
+
+        if (value.isSelfRegUnmatching() && value.isCreateUnmatching()) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.Standard,
+                            "Either selfRegUnmatching or createUnmatching, not both")).
+                    addPropertyNode("selfRegUnmatching").
+                    addPropertyNode("createUnmatching").addConstraintViolation();
+            return false;
+        }
+
         long connObjectKeys = IterableUtils.countMatches(value.getItems(), new Predicate<SAML2IdPItem>() {
 
             @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
index 17842d3..011e149 100644
--- a/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
+++ b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
@@ -178,6 +178,7 @@ public class SAML2IdPDataBinderImpl implements SAML2IdPDataBinder {
         idp.setName(idpTO.getName());
         idp.setMetadata(Base64.decode(idpTO.getMetadata()));
         idp.setCreateUnmatching(idpTO.isCreateUnmatching());
+        idp.setSelfRegUnmatching(idpTO.isSelfRegUnmatching());
         idp.setUpdateMatching(idpTO.isUpdateMatching());
         idp.setUseDeflateEncoding(idpTO.isUseDeflateEncoding());
         idp.setSupportUnsolicited(idpTO.isSupportUnsolicited());
@@ -243,6 +244,7 @@ public class SAML2IdPDataBinderImpl implements SAML2IdPDataBinder {
         idpTO.setSupportUnsolicited(idp.isSupportUnsolicited());
         idpTO.setBindingType(idp.getBindingType());
         idpTO.setCreateUnmatching(idp.isCreateUnmatching());
+        idpTO.setSelfRegUnmatching(idp.isSelfRegUnmatching());
         idpTO.setUpdateMatching(idp.isUpdateMatching());
         idpTO.setMetadata(Base64.encode(idp.getMetadata()));
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/fit/console-reference/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/src/main/webapp/WEB-INF/web.xml b/fit/console-reference/src/main/webapp/WEB-INF/web.xml
index 66a800e..890e5b0 100644
--- a/fit/console-reference/src/main/webapp/WEB-INF/web.xml
+++ b/fit/console-reference/src/main/webapp/WEB-INF/web.xml
@@ -47,6 +47,11 @@ under the License.
     <param-name>saml2sp.logout.error.url</param-name>
     <param-value>../wicket/bookmarkable/org.apache.syncope.client.console.pages.Login</param-value>
   </context-param>
+
+  <context-param>
+    <param-name>saml2sp.redirect.selfreg</param-name>
+    <param-value>../wicket/bookmarkable/org.apache.syncope.client.console.pages.SAML2SPSelfReg</param-value>
+  </context-param>
   
   <!-- SESSION TIMEOUT (MINUTES)-->
   <session-config>

http://git-wip-us.apache.org/repos/asf/syncope/blob/31493e5d/fit/enduser-reference/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/fit/enduser-reference/src/main/webapp/WEB-INF/web.xml b/fit/enduser-reference/src/main/webapp/WEB-INF/web.xml
index fa4720d..7f61a36 100644
--- a/fit/enduser-reference/src/main/webapp/WEB-INF/web.xml
+++ b/fit/enduser-reference/src/main/webapp/WEB-INF/web.xml
@@ -47,6 +47,11 @@ under the License.
     <param-name>saml2sp.logout.error.url</param-name>
     <param-value>../wicket/bookmarkable/org.apache.syncope.client.enduser.pages.HomePage</param-value>
   </context-param>
+  
+  <context-param>
+    <param-name>saml2sp.redirect.selfreg</param-name>
+    <param-value>../wicket/bookmarkable/org.apache.syncope.client.enduser.pages.SAML2SPSelfReg</param-value>
+  </context-param>
 
   <!-- SESSION TIMEOUT (MINUTES)-->
   <session-config>