keycloak-uncached

Merge pull request #910 from patriot1burke/master saml

1/7/2015 10:31:43 PM

Changes

Details

diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java
index 045b318..9e885ea 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java
@@ -22,9 +22,11 @@ import java.net.URI;
  */
 public class SAML2LogoutRequestBuilder extends SAML2BindingBuilder<SAML2LogoutRequestBuilder> {
     protected String userPrincipal;
+    protected String userPrincipalFormat;
 
-    public SAML2LogoutRequestBuilder userPrincipal(String userPrincipal) {
-        this.userPrincipal = userPrincipal;
+    public SAML2LogoutRequestBuilder userPrincipal(String nameID, String nameIDformat) {
+        this.userPrincipal = nameID;
+        this.userPrincipalFormat = nameIDformat;
         return this;
     }
 
@@ -51,7 +53,7 @@ public class SAML2LogoutRequestBuilder extends SAML2BindingBuilder<SAML2LogoutRe
         NameIDType nameID = new NameIDType();
         nameID.setValue(userPrincipal);
         //Deal with NameID Format
-        String nameIDFormat = JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get();
+        String nameIDFormat = userPrincipalFormat;
         nameID.setFormat(URI.create(nameIDFormat));
         lort.setNameID(nameID);
 
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index e8b1504..68e5d35 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -28,6 +28,7 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 import java.security.PublicKey;
+import java.util.UUID;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -54,7 +55,10 @@ public class SamlProtocol implements LoginProtocol {
     public static final String SAML_ENCRYPT = "saml.encrypt";
     public static final String SAML_FORCE_POST_BINDING = "saml.force.post.binding";
     public static final String SAML_REQUEST_ID = "SAML_REQUEST_ID";
+    public static final String SAML_NAME_ID = "SAML_NAME_ID";
+    public static final String SAML_NAME_ID_FORMAT = "SAML_NAME_ID_FORMAT";
     public static final String SAML_DEFAULT_NAMEID_FORMAT = JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get();
+    public static final String SAML_PERSISTENT_NAME_ID_FOR = "saml.persistent.name.id.for";
 
     protected KeycloakSession session;
 
@@ -125,12 +129,25 @@ public class SamlProtocol implements LoginProtocol {
     }
 
     protected String getNameId(String nameIdFormat, ClientSessionModel clientSession, UserSessionModel userSession) {
-        if(nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
+        if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
             return userSession.getUser().getEmail();
         } else if(nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get())) {
+            // "G-" stands for "generated" Add this for the slight possibility of collisions.
+            return "G-" + UUID.randomUUID().toString();
+        } else if(nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get())) {
+            // generate a persistent user id specifically for each client.
+            UserModel user = userSession.getUser();
+            String name = SAML_PERSISTENT_NAME_ID_FOR + "." + clientSession.getClient().getClientId();
+            String samlPersistentId = user.getAttribute(name);
+            if (samlPersistentId != null) return samlPersistentId;
+            // "G-" stands for "generated"
+            samlPersistentId = "G-" + UUID.randomUUID().toString();
+            user.setAttribute(name, samlPersistentId);
+            return samlPersistentId;
+        } else if(nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get())){
+            // TODO: Support for persistent NameID (pseudo-random identifier persisted in user object)
             return userSession.getUser().getUsername();
         } else {
-            // TODO: Support for persistent NameID (pseudo-random identifier persisted in user object)
             return userSession.getUser().getUsername();
         }
     }
@@ -146,6 +163,11 @@ public class SamlProtocol implements LoginProtocol {
         String nameIdFormat = getNameIdFormat(clientSession);
         String nameId = getNameId(nameIdFormat, clientSession, userSession);
 
+        // save NAME_ID and format in clientSession as they may be persistent or transient or email and not username
+        // we'll need to send this back on a logout
+        clientSession.setNote(SAML_NAME_ID, nameId);
+        clientSession.setNote(SAML_NAME_ID_FORMAT, nameIdFormat);
+
         SALM2LoginResponseBuilder builder = new SALM2LoginResponseBuilder();
         builder.requestID(requestID)
                .relayState(relayState)
@@ -256,8 +278,9 @@ public class SamlProtocol implements LoginProtocol {
         ApplicationModel app = (ApplicationModel)client;
         if (app.getManagementUrl() == null) return;
 
+        // build userPrincipal with subject used at login
         SAML2LogoutRequestBuilder logoutBuilder = new SAML2LogoutRequestBuilder()
-                                         .userPrincipal(userSession.getUser().getUsername())
+                                         .userPrincipal(clientSession.getNote(SAML_NAME_ID), clientSession.getNote(SAML_NAME_ID_FORMAT))
                                          .destination(client.getClientId());
         if (requiresRealmSignature(client)) {
             logoutBuilder.signatureAlgorithm(getSignatureAlgorithm(client))
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
index 8d542bf..2ad6584 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -246,6 +246,7 @@ public class SamlService {
         private boolean isSupportedNameIdFormat(String nameIdFormat) {
             if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get()) ||
                     nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get()) ||
+                    nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get()) ||
                     nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get())) {
                 return true;
             }
diff --git a/saml/saml-protocol/src/main/resources/idp-metadata-template.xml b/saml/saml-protocol/src/main/resources/idp-metadata-template.xml
index 25455c0..bc667d1 100755
--- a/saml/saml-protocol/src/main/resources/idp-metadata-template.xml
+++ b/saml/saml-protocol/src/main/resources/idp-metadata-template.xml
@@ -5,7 +5,8 @@
 	<EntityDescriptor entityID="${idp.entityID}">
 		<IDPSSODescriptor WantAuthnRequestsSigned="true"
 			protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
-			<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
+            <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
+            <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
 			<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
 			<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
index 94d65ad..b796452 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
@@ -49,6 +49,9 @@ public class SamlBindingTest {
 
             initializeSamlSecuredWar("/saml/simple-post", "/sales-post",  "post.war", classLoader);
             initializeSamlSecuredWar("/saml/signed-post", "/sales-post-sig",  "post-sig.war", classLoader);
+            initializeSamlSecuredWar("/saml/signed-post-email", "/sales-post-sig-email",  "post-sig-email.war", classLoader);
+            initializeSamlSecuredWar("/saml/signed-post-transient", "/sales-post-sig-transient",  "post-sig-transient.war", classLoader);
+            initializeSamlSecuredWar("/saml/signed-post-persistent", "/sales-post-sig-persistent",  "post-sig-persistent.war", classLoader);
             initializeSamlSecuredWar("/saml/signed-metadata", "/sales-metadata",  "post-metadata.war", classLoader);
             initializeSamlSecuredWar("/saml/signed-get", "/employee-sig",  "employee-sig.war", classLoader);
             initializeSamlSecuredWar("/saml/bad-client-signed-post", "/bad-client-sales-post-sig",  "bad-client-post-sig.war", classLoader);
@@ -101,6 +104,44 @@ public class SamlBindingTest {
 
     }
     @Test
+    public void testPostSignedLoginLogoutTransientNameID() {
+        driver.navigate().to("http://localhost:8081/sales-post-sig-transient/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-transient/");
+        System.out.println(driver.getPageSource());
+        Assert.assertFalse(driver.getPageSource().contains("bburke"));
+        Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
+        driver.navigate().to("http://localhost:8081/sales-post-sig-transient?GLO=true");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+
+    }
+    @Test
+    public void testPostSignedLoginLogoutPersistentNameID() {
+        driver.navigate().to("http://localhost:8081/sales-post-sig-persistent/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-persistent/");
+        System.out.println(driver.getPageSource());
+        Assert.assertFalse(driver.getPageSource().contains("bburke"));
+        Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
+        driver.navigate().to("http://localhost:8081/sales-post-sig-persistent?GLO=true");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+
+    }
+    @Test
+    public void testPostSignedLoginLogoutEmailNameID() {
+        driver.navigate().to("http://localhost:8081/sales-post-sig-email/");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+        loginPage.login("bburke", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-email/");
+        System.out.println(driver.getPageSource());
+        Assert.assertTrue(driver.getPageSource().contains("principal=bburke@redhat.com"));
+        driver.navigate().to("http://localhost:8081/sales-post-sig-email?GLO=true");
+        Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
+
+    }
+    @Test
     public void testRedirectSignedLoginLogout() {
         driver.navigate().to("http://localhost:8081/employee-sig/");
         Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlKeycloakRule.java
index 349f739..f3b543f 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlKeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlKeycloakRule.java
@@ -36,6 +36,7 @@ public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
             resp.setContentType("text/plain");
             OutputStream stream = resp.getOutputStream();
             Principal principal = req.getUserPrincipal();
+            stream.write("principal=".getBytes());
             if (principal == null) {
                 stream.write("null".getBytes());
                 return;
@@ -48,6 +49,7 @@ public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
             resp.setContentType("text/plain");
             OutputStream stream = resp.getOutputStream();
             Principal principal = req.getUserPrincipal();
+            stream.write("principal=".getBytes());
             if (principal == null) {
                 stream.write("null".getBytes());
                 return;
diff --git a/testsuite/integration/src/test/resources/saml/encrypted-post/WEB-INF/picketlink.xml b/testsuite/integration/src/test/resources/saml/encrypted-post/WEB-INF/picketlink.xml
index 068d3ec..b028a39 100755
--- a/testsuite/integration/src/test/resources/saml/encrypted-post/WEB-INF/picketlink.xml
+++ b/testsuite/integration/src/test/resources/saml/encrypted-post/WEB-INF/picketlink.xml
@@ -19,8 +19,10 @@
 	<Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">
 		<Handler
 			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" />
-		<Handler
-			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" />
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
+            <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
+        </Handler>
 		<Handler
 			class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" />
 		<Handler
diff --git a/testsuite/integration/src/test/resources/saml/signed-get/WEB-INF/picketlink.xml b/testsuite/integration/src/test/resources/saml/signed-get/WEB-INF/picketlink.xml
index beed463..e2e7e3b 100755
--- a/testsuite/integration/src/test/resources/saml/signed-get/WEB-INF/picketlink.xml
+++ b/testsuite/integration/src/test/resources/saml/signed-get/WEB-INF/picketlink.xml
@@ -18,8 +18,10 @@
 	<Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">
 		<Handler
 			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" />
-		<Handler
-			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" />
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
+            <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
+        </Handler>
 		<Handler
 			class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" />
 		<Handler
diff --git a/testsuite/integration/src/test/resources/saml/signed-metadata/WEB-INF/picketlink.xml b/testsuite/integration/src/test/resources/saml/signed-metadata/WEB-INF/picketlink.xml
index 17d37df..481679f 100755
--- a/testsuite/integration/src/test/resources/saml/signed-metadata/WEB-INF/picketlink.xml
+++ b/testsuite/integration/src/test/resources/saml/signed-metadata/WEB-INF/picketlink.xml
@@ -19,8 +19,10 @@
 	<Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">
 		<Handler
 			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" />
-		<Handler
-			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" />
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
+            <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
+        </Handler>
 		<Handler
 			class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" />
 		<Handler
diff --git a/testsuite/integration/src/test/resources/saml/signed-post/WEB-INF/picketlink.xml b/testsuite/integration/src/test/resources/saml/signed-post/WEB-INF/picketlink.xml
index 39ea935..31011db 100755
--- a/testsuite/integration/src/test/resources/saml/signed-post/WEB-INF/picketlink.xml
+++ b/testsuite/integration/src/test/resources/saml/signed-post/WEB-INF/picketlink.xml
@@ -1,31 +1,33 @@
 <PicketLink xmlns="urn:picketlink:identity-federation:config:2.1">
-	<PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1"
-		ServerEnvironment="tomcat" BindingType="POST" SupportsSignatures="true">
-		<IdentityURL>${idp-sig.url::http://localhost:8081/auth/realms/demo/protocol/saml}
-		</IdentityURL>
-		<ServiceURL>${sales-post-sig.url::http://localhost:8081/sales-post-sig/}
-		</ServiceURL>
-		<KeyProvider
-			ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager">
-			<Auth Key="KeyStoreURL" Value="saml/signed-post/WEB-INF/keystore.jks" />
-			<Auth Key="KeyStorePass" Value="store123" />
-			<Auth Key="SigningKeyPass" Value="test123" />
-			<Auth Key="SigningKeyAlias" Value="http://localhost:8080/sales-post-sig/" />
-			<ValidatingAlias Key="localhost" Value="demo" />
-			<ValidatingAlias Key="127.0.0.1" Value="demo" />
-		</KeyProvider>
+    <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1"
+                  ServerEnvironment="tomcat" BindingType="POST" SupportsSignatures="true">
+        <IdentityURL>${idp-sig.url::http://localhost:8081/auth/realms/demo/protocol/saml}
+        </IdentityURL>
+        <ServiceURL>${sales-post-sig.url::http://localhost:8081/sales-post-sig/}
+        </ServiceURL>
+        <KeyProvider
+                ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager">
+            <Auth Key="KeyStoreURL" Value="saml/signed-post/WEB-INF/keystore.jks"/>
+            <Auth Key="KeyStorePass" Value="store123"/>
+            <Auth Key="SigningKeyPass" Value="test123"/>
+            <Auth Key="SigningKeyAlias" Value="http://localhost:8080/sales-post-sig/"/>
+            <ValidatingAlias Key="localhost" Value="demo"/>
+            <ValidatingAlias Key="127.0.0.1" Value="demo"/>
+        </KeyProvider>
 
-	</PicketLinkSP>
-	<Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">
-		<Handler
-			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" />
-		<Handler
-			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" />
-		<Handler
-			class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" />
-		<Handler
-			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureGenerationHandler" />
-		<Handler
-			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler" />
-	</Handlers>
+    </PicketLinkSP>
+    <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
+            <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
+        </Handler>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureGenerationHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler"/>
+    </Handlers>
 </PicketLink>
diff --git a/testsuite/integration/src/test/resources/saml/signed-post-email/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/saml/signed-post-email/WEB-INF/keystore.jks
new file mode 100755
index 0000000..144830b
Binary files /dev/null and b/testsuite/integration/src/test/resources/saml/signed-post-email/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/saml/signed-post-email/WEB-INF/picketlink.xml b/testsuite/integration/src/test/resources/saml/signed-post-email/WEB-INF/picketlink.xml
new file mode 100755
index 0000000..d036b07
--- /dev/null
+++ b/testsuite/integration/src/test/resources/saml/signed-post-email/WEB-INF/picketlink.xml
@@ -0,0 +1,33 @@
+<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1">
+    <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1"
+                  ServerEnvironment="tomcat" BindingType="POST" SupportsSignatures="true">
+        <IdentityURL>${idp-sig.url::http://localhost:8081/auth/realms/demo/protocol/saml}
+        </IdentityURL>
+        <ServiceURL>${sales-post-sig.url::http://localhost:8081/sales-post-sig-email/}
+        </ServiceURL>
+        <KeyProvider
+                ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager">
+            <Auth Key="KeyStoreURL" Value="saml/signed-post/WEB-INF/keystore.jks"/>
+            <Auth Key="KeyStorePass" Value="store123"/>
+            <Auth Key="SigningKeyPass" Value="test123"/>
+            <Auth Key="SigningKeyAlias" Value="http://localhost:8080/sales-post-sig/"/>
+            <ValidatingAlias Key="localhost" Value="demo"/>
+            <ValidatingAlias Key="127.0.0.1" Value="demo"/>
+        </KeyProvider>
+
+    </PicketLinkSP>
+    <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
+            <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"/>
+        </Handler>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureGenerationHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler"/>
+    </Handlers>
+</PicketLink>
diff --git a/testsuite/integration/src/test/resources/saml/signed-post-persistent/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/saml/signed-post-persistent/WEB-INF/keystore.jks
new file mode 100755
index 0000000..144830b
Binary files /dev/null and b/testsuite/integration/src/test/resources/saml/signed-post-persistent/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/saml/signed-post-persistent/WEB-INF/picketlink.xml b/testsuite/integration/src/test/resources/saml/signed-post-persistent/WEB-INF/picketlink.xml
new file mode 100755
index 0000000..2a57b17
--- /dev/null
+++ b/testsuite/integration/src/test/resources/saml/signed-post-persistent/WEB-INF/picketlink.xml
@@ -0,0 +1,33 @@
+<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1">
+    <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1"
+                  ServerEnvironment="tomcat" BindingType="POST" SupportsSignatures="true">
+        <IdentityURL>${idp-sig.url::http://localhost:8081/auth/realms/demo/protocol/saml}
+        </IdentityURL>
+        <ServiceURL>${sales-post-sig.url::http://localhost:8081/sales-post-sig-persistent/}
+        </ServiceURL>
+        <KeyProvider
+                ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager">
+            <Auth Key="KeyStoreURL" Value="saml/signed-post/WEB-INF/keystore.jks"/>
+            <Auth Key="KeyStorePass" Value="store123"/>
+            <Auth Key="SigningKeyPass" Value="test123"/>
+            <Auth Key="SigningKeyAlias" Value="http://localhost:8080/sales-post-sig/"/>
+            <ValidatingAlias Key="localhost" Value="demo"/>
+            <ValidatingAlias Key="127.0.0.1" Value="demo"/>
+        </KeyProvider>
+
+    </PicketLinkSP>
+    <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
+            <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
+        </Handler>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureGenerationHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler"/>
+    </Handlers>
+</PicketLink>
diff --git a/testsuite/integration/src/test/resources/saml/signed-post-transient/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/saml/signed-post-transient/WEB-INF/keystore.jks
new file mode 100755
index 0000000..144830b
Binary files /dev/null and b/testsuite/integration/src/test/resources/saml/signed-post-transient/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/saml/signed-post-transient/WEB-INF/picketlink.xml b/testsuite/integration/src/test/resources/saml/signed-post-transient/WEB-INF/picketlink.xml
new file mode 100755
index 0000000..70d81fc
--- /dev/null
+++ b/testsuite/integration/src/test/resources/saml/signed-post-transient/WEB-INF/picketlink.xml
@@ -0,0 +1,33 @@
+<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1">
+    <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:2.1"
+                  ServerEnvironment="tomcat" BindingType="POST" SupportsSignatures="true">
+        <IdentityURL>${idp-sig.url::http://localhost:8081/auth/realms/demo/protocol/saml}
+        </IdentityURL>
+        <ServiceURL>${sales-post-sig.url::http://localhost:8081/sales-post-sig-transient/}
+        </ServiceURL>
+        <KeyProvider
+                ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager">
+            <Auth Key="KeyStoreURL" Value="saml/signed-post/WEB-INF/keystore.jks"/>
+            <Auth Key="KeyStorePass" Value="store123"/>
+            <Auth Key="SigningKeyPass" Value="test123"/>
+            <Auth Key="SigningKeyAlias" Value="http://localhost:8080/sales-post-sig/"/>
+            <ValidatingAlias Key="localhost" Value="demo"/>
+            <ValidatingAlias Key="127.0.0.1" Value="demo"/>
+        </KeyProvider>
+
+    </PicketLinkSP>
+    <Handlers xmlns="urn:picketlink:identity-federation:handler:config:2.1">
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
+            <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
+        </Handler>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureGenerationHandler"/>
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler"/>
+    </Handlers>
+</PicketLink>
diff --git a/testsuite/integration/src/test/resources/saml/simple-get/WEB-INF/picketlink.xml b/testsuite/integration/src/test/resources/saml/simple-get/WEB-INF/picketlink.xml
index 2fb11ca..1d170ee 100755
--- a/testsuite/integration/src/test/resources/saml/simple-get/WEB-INF/picketlink.xml
+++ b/testsuite/integration/src/test/resources/saml/simple-get/WEB-INF/picketlink.xml
@@ -10,7 +10,8 @@
 			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" />
 		<Handler
 			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
-			
+
+            <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
 			<Option Key="ASSERTION_SESSION_ATTRIBUTE_NAME" Value="org.picketlink.sp.assertion"/>
 			
 		</Handler>
diff --git a/testsuite/integration/src/test/resources/saml/simple-post/WEB-INF/picketlink.xml b/testsuite/integration/src/test/resources/saml/simple-post/WEB-INF/picketlink.xml
index 4e20d7e..73dab62 100755
--- a/testsuite/integration/src/test/resources/saml/simple-post/WEB-INF/picketlink.xml
+++ b/testsuite/integration/src/test/resources/saml/simple-post/WEB-INF/picketlink.xml
@@ -12,8 +12,10 @@
             class="org.picketlink.identity.federation.web.handlers.saml2.SAML2IssuerTrustHandler" />
 		<Handler
 			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2LogOutHandler" />
-		<Handler
-			class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler" />
+        <Handler
+                class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
+            <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/>
+        </Handler>
 		<Handler
 			class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler" />
 	</Handlers>
diff --git a/testsuite/integration/src/test/resources/saml/testsaml.json b/testsuite/integration/src/test/resources/saml/testsaml.json
index 8098d5b..4453c34 100755
--- a/testsuite/integration/src/test/resources/saml/testsaml.json
+++ b/testsuite/integration/src/test/resources/saml/testsaml.json
@@ -62,6 +62,63 @@
             }
         },
         {
+            "name": "http://localhost:8081/sales-post-sig-transient/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/sales-post-sig-transient",
+            "adminUrl": "http://localhost:8081/sales-post-sig-transient",
+            "redirectUris": [
+                "http://localhost:8081/sales-post-sig-transient/*"
+            ],
+            "attributes": {
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "name": "http://localhost:8081/sales-post-sig-persistent/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/sales-post-sig-persistent",
+            "adminUrl": "http://localhost:8081/sales-post-sig-persistent",
+            "redirectUris": [
+                "http://localhost:8081/sales-post-sig-persistent/*"
+            ],
+            "attributes": {
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "name": "http://localhost:8081/sales-post-sig-email/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8081/sales-post-sig-email",
+            "adminUrl": "http://localhost:8081/sales-post-sig-email",
+            "redirectUris": [
+                "http://localhost:8081/sales-post-sig-email/*"
+            ],
+            "attributes": {
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
             "name": "http://localhost:8081/bad-realm-sales-post-sig/",
             "enabled": true,
             "protocol": "saml",