keycloak-aplcache

more complete

9/23/2015 6:54:16 PM

Changes

Details

diff --git a/integration/adapter-spi/src/main/java/org/keycloak/adapters/InMemorySessionIdMapper.java b/integration/adapter-spi/src/main/java/org/keycloak/adapters/InMemorySessionIdMapper.java
index 8225ae2..4470c15 100755
--- a/integration/adapter-spi/src/main/java/org/keycloak/adapters/InMemorySessionIdMapper.java
+++ b/integration/adapter-spi/src/main/java/org/keycloak/adapters/InMemorySessionIdMapper.java
@@ -11,7 +11,7 @@ import java.util.concurrent.ConcurrentHashMap;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class InMemorySessionIdMapper implements SessionIdMaper {
+public class InMemorySessionIdMapper implements SessionIdMapper {
     ConcurrentHashMap<String, String> ssoToSession = new ConcurrentHashMap<>();
     ConcurrentHashMap<String, String> sessionToSso = new ConcurrentHashMap<>();
     ConcurrentHashMap<String, Set<String>> principalToSession = new ConcurrentHashMap<>();
@@ -33,8 +33,10 @@ public class InMemorySessionIdMapper implements SessionIdMaper {
 
     @Override
     public void map(String sso, String principal, String session) {
-        ssoToSession.put(sso, session);
-        sessionToSso.put(session, sso);
+        if (sso != null) {
+            ssoToSession.put(sso, session);
+            sessionToSso.put(session, sso);
+        }
         Set<String> userSessions = principalToSession.get(principal);
         if (userSessions == null) {
             final Set<String> tmp = Collections.synchronizedSet(new HashSet<String>());
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/IDP.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/IDP.java
index 813f52e..84764e3 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/IDP.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/IDP.java
@@ -13,7 +13,6 @@ public class IDP implements Serializable {
     public static class SingleSignOnService implements Serializable {
         private boolean signRequest;
         private boolean validateResponseSignature;
-        private String signatureCanonicalizationMethod;
         private String requestBinding;
         private String responseBinding;
         private String bindingUrl;
@@ -34,14 +33,6 @@ public class IDP implements Serializable {
             this.validateResponseSignature = validateResponseSignature;
         }
 
-        public String getSignatureCanonicalizationMethod() {
-            return signatureCanonicalizationMethod;
-        }
-
-        public void setSignatureCanonicalizationMethod(String signatureCanonicalizationMethod) {
-            this.signatureCanonicalizationMethod = signatureCanonicalizationMethod;
-        }
-
         public String getRequestBinding() {
             return requestBinding;
         }
@@ -72,7 +63,6 @@ public class IDP implements Serializable {
         private boolean signResponse;
         private boolean validateRequestSignature;
         private boolean validateResponseSignature;
-        private String signatureCanonicalizationMethod;
         private String requestBinding;
         private String responseBinding;
         private String postBindingUrl;
@@ -110,14 +100,6 @@ public class IDP implements Serializable {
             this.validateResponseSignature = validateResponseSignature;
         }
 
-        public String getSignatureCanonicalizationMethod() {
-            return signatureCanonicalizationMethod;
-        }
-
-        public void setSignatureCanonicalizationMethod(String signatureCanonicalizationMethod) {
-            this.signatureCanonicalizationMethod = signatureCanonicalizationMethod;
-        }
-
         public String getRequestBinding() {
             return requestBinding;
         }
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/ConfigXmlConstants.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/ConfigXmlConstants.java
index a714b0a..0e0542c 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/ConfigXmlConstants.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/ConfigXmlConstants.java
@@ -11,6 +11,8 @@ public class ConfigXmlConstants {
     public static final String SSL_POLICY_ATTR = "sslPolicy";
     public static final String NAME_ID_POLICY_FORMAT_ATTR = "nameIDPolicyFormat";
     public static final String FORCE_AUTHENTICATION_ATTR = "forceAuthentication";
+    public static final String SIGNATURE_ALGORITHM_ATTR = "signatureAlgorithm";
+    public static final String SIGNATURE_CANONICALIZATION_METHOD_ATTR = "signatureCanonicalizationMethod";
     public static final String LOGOUT_PAGE_ATTR = "logoutPage";
 
 
@@ -45,7 +47,6 @@ public class ConfigXmlConstants {
     public static final String SINGLE_LOGOUT_SERVICE_ELEMENT = "SingleLogoutService";
     public static final String SIGN_REQUEST_ATTR = "signRequest";
     public static final String SIGN_RESPONSE_ATTR = "signResponse";
-    public static final String SIGNATURE_CANONICALIZATION_METHOD_ATTR = "signatureCanonicalizationMethod";
     public static final String REQUEST_BINDING_ATTR = "requestBinding";
     public static final String RESPONSE_BINDING_ATTR = "responseBinding";
     public static final String BINDING_URL_ATTR = "bindingUrl";
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java
index 24f9101..46e5b8f 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/DeploymentBuilder.java
@@ -6,6 +6,7 @@ import org.keycloak.adapters.saml.config.Key;
 import org.keycloak.adapters.saml.config.KeycloakSamlAdapter;
 import org.keycloak.adapters.saml.config.SP;
 import org.keycloak.enums.SslRequired;
+import org.keycloak.saml.SignatureAlgorithm;
 import org.keycloak.saml.common.exceptions.ParsingException;
 import org.keycloak.util.PemUtils;
 
@@ -40,6 +41,11 @@ public class DeploymentBuilder {
         deployment.setForceAuthentication(sp.isForceAuthentication());
         deployment.setNameIDPolicyFormat(sp.getNameIDPolicyFormat());
         deployment.setLogoutPage(sp.getLogoutPage());
+        deployment.setSignatureCanonicalizationMethod(sp.getSignatureCanonicalizationMethod());
+        deployment.setSignatureAlgorithm(SignatureAlgorithm.RSA_SHA256);
+        if (sp.getSignatureAlgorithm() != null) {
+            deployment.setSignatureAlgorithm(SignatureAlgorithm.valueOf(sp.getSignatureAlgorithm()));
+        }
         if (sp.getPrincipalNameMapping() != null) {
             SamlDeployment.PrincipalNamePolicy policy = SamlDeployment.PrincipalNamePolicy.valueOf(sp.getPrincipalNameMapping().getPolicy());
             deployment.setPrincipalNamePolicy(policy);
@@ -51,45 +57,47 @@ public class DeploymentBuilder {
             SslRequired ssl = SslRequired.valueOf(sp.getSslPolicy());
             deployment.setSslRequired(ssl);
         }
-        for (Key key : sp.getKeys()) {
-            if (key.isSigning()) {
-                PrivateKey privateKey = null;
-                PublicKey publicKey = null;
-                if (key.getKeystore() != null) {
-                    KeyStore keyStore = loadKeystore(resourceLoader, key);
-                    Certificate cert  = null;
-                    try {
-                        cert = keyStore.getCertificate(key.getKeystore().getCertificateAlias());
-                        privateKey = (PrivateKey)keyStore.getKey(key.getKeystore().getPrivateKeyAlias(), key.getKeystore().getPrivateKeyPassword().toCharArray());
-                    } catch (Exception e) {
-                        throw new RuntimeException(e);
-                    }
-                    publicKey = cert.getPublicKey();
-                } else {
-                    if (key.getPrivateKeyPem() == null) {
-                        throw new RuntimeException("SP signing key must have a PrivateKey defined");
+        if (sp.getKeys() != null) {
+            for (Key key : sp.getKeys()) {
+                if (key.isSigning()) {
+                    PrivateKey privateKey = null;
+                    PublicKey publicKey = null;
+                    if (key.getKeystore() != null) {
+                        KeyStore keyStore = loadKeystore(resourceLoader, key);
+                        Certificate cert = null;
+                        try {
+                            cert = keyStore.getCertificate(key.getKeystore().getCertificateAlias());
+                            privateKey = (PrivateKey) keyStore.getKey(key.getKeystore().getPrivateKeyAlias(), key.getKeystore().getPrivateKeyPassword().toCharArray());
+                        } catch (Exception e) {
+                            throw new RuntimeException(e);
+                        }
+                        publicKey = cert.getPublicKey();
+                    } else {
+                        if (key.getPrivateKeyPem() == null) {
+                            throw new RuntimeException("SP signing key must have a PrivateKey defined");
+                        }
+                        try {
+                            privateKey = PemUtils.decodePrivateKey(key.getPrivateKeyPem().trim());
+                            if (key.getPublicKeyPem() == null && key.getCertificatePem() == null) {
+                                throw new RuntimeException("Sp signing key must have a PublicKey or Certificate defined");
+                            }
+                            publicKey = getPublicKeyFromPem(key);
+                        } catch (Exception e) {
+                            throw new RuntimeException(e);
+                        }
                     }
+                    KeyPair keyPair = new KeyPair(publicKey, privateKey);
+                    deployment.setSigningKeyPair(keyPair);
+
+                } else if (key.isEncryption()) {
+                    KeyStore keyStore = loadKeystore(resourceLoader, key);
                     try {
-                        privateKey = PemUtils.decodePrivateKey(key.getPrivateKeyPem().trim());
-                        if (key.getPublicKeyPem() == null &&key.getCertificatePem() == null) {
-                            throw new RuntimeException("Sp signing key must have a PublicKey or Certificate defined");
-                        }
-                        publicKey = getPublicKeyFromPem(key);
+                        PrivateKey privateKey = (PrivateKey) keyStore.getKey(key.getKeystore().getPrivateKeyAlias(), key.getKeystore().getPrivateKeyPassword().toCharArray());
+                        deployment.setDecryptionKey(privateKey);
                     } catch (Exception e) {
                         throw new RuntimeException(e);
                     }
                 }
-                KeyPair keyPair = new KeyPair(publicKey, privateKey);
-                deployment.setSigningKeyPair(keyPair);
-
-            } else if (key.isEncryption()) {
-                KeyStore keyStore = loadKeystore(resourceLoader, key);
-                try {
-                    PrivateKey privateKey = (PrivateKey)keyStore.getKey(key.getKeystore().getPrivateKeyAlias(), key.getKeystore().getPrivateKeyPassword().toCharArray());
-                    deployment.setDecryptionKey(privateKey);
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
             }
         }
 
@@ -97,8 +105,9 @@ public class DeploymentBuilder {
         idp.setEntityID(sp.getIdp().getEntityID());
         sso.setRequestBinding(SamlDeployment.Binding.parseBinding(sp.getIdp().getSingleSignOnService().getRequestBinding()));
         sso.setRequestBindingUrl(sp.getIdp().getSingleSignOnService().getBindingUrl());
-        sso.setResponseBinding(SamlDeployment.Binding.parseBinding(sp.getIdp().getSingleSignOnService().getResponseBinding()));
-        sso.setSignatureCanonicalizationMethod(sp.getIdp().getSingleSignOnService().getSignatureCanonicalizationMethod());
+        if (sp.getIdp().getSingleSignOnService().getResponseBinding() != null) {
+            sso.setResponseBinding(SamlDeployment.Binding.parseBinding(sp.getIdp().getSingleSignOnService().getResponseBinding()));
+        }
         sso.setSignRequest(sp.getIdp().getSingleSignOnService().isSignRequest());
         sso.setValidateResponseSignature(sp.getIdp().getSingleSignOnService().isValidateResponseSignature());
 
@@ -106,7 +115,6 @@ public class DeploymentBuilder {
         slo.setSignResponse(sp.getIdp().getSingleLogoutService().isSignResponse());
         slo.setValidateResponseSignature(sp.getIdp().getSingleLogoutService().isValidateResponseSignature());
         slo.setValidateRequestSignature(sp.getIdp().getSingleLogoutService().isValidateRequestSignature());
-        slo.setSignatureCanonicalizationMethod(sp.getIdp().getSingleLogoutService().getSignatureCanonicalizationMethod());
         slo.setRequestBinding(SamlDeployment.Binding.parseBinding(sp.getIdp().getSingleLogoutService().getRequestBinding()));
         slo.setResponseBinding(SamlDeployment.Binding.parseBinding(sp.getIdp().getSingleLogoutService().getResponseBinding()));
         if (slo.getRequestBinding() == SamlDeployment.Binding.POST) {
@@ -119,26 +127,28 @@ public class DeploymentBuilder {
         } else {
             slo.setResponseBindingUrl(sp.getIdp().getSingleLogoutService().getRedirectBindingUrl());
         }
-        for (Key key : sp.getIdp().getKeys()) {
-            if (key.isSigning()) {
-                if (key.getKeystore() != null) {
-                    KeyStore keyStore = loadKeystore(resourceLoader, key);
-                    Certificate cert  = null;
-                    try {
-                        cert = keyStore.getCertificate(key.getKeystore().getCertificateAlias());
-                    } catch (KeyStoreException e) {
-                        throw new RuntimeException(e);
-                    }
-                    idp.setSignatureValidationKey(cert.getPublicKey());
-                } else {
-                    if (key.getPublicKeyPem() == null && key.getCertificatePem() == null) {
-                        throw new RuntimeException("IDP signing key must have a PublicKey or Certificate defined");
-                    }
-                    try {
-                        PublicKey publicKey = getPublicKeyFromPem(key);
-                        idp.setSignatureValidationKey(publicKey);
-                    } catch (Exception e) {
-                        throw new RuntimeException(e);
+        if (sp.getIdp().getKeys() != null) {
+            for (Key key : sp.getIdp().getKeys()) {
+                if (key.isSigning()) {
+                    if (key.getKeystore() != null) {
+                        KeyStore keyStore = loadKeystore(resourceLoader, key);
+                        Certificate cert = null;
+                        try {
+                            cert = keyStore.getCertificate(key.getKeystore().getCertificateAlias());
+                        } catch (KeyStoreException e) {
+                            throw new RuntimeException(e);
+                        }
+                        idp.setSignatureValidationKey(cert.getPublicKey());
+                    } else {
+                        if (key.getPublicKeyPem() == null && key.getCertificatePem() == null) {
+                            throw new RuntimeException("IDP signing key must have a PublicKey or Certificate defined");
+                        }
+                        try {
+                            PublicKey publicKey = getPublicKeyFromPem(key);
+                            idp.setSignatureValidationKey(publicKey);
+                        } catch (Exception e) {
+                            throw new RuntimeException(e);
+                        }
                     }
                 }
             }
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/IDPXmlParser.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/IDPXmlParser.java
index c4e9a6e..96485d5 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/IDPXmlParser.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/IDPXmlParser.java
@@ -72,7 +72,6 @@ public class IDPXmlParser extends AbstractParser {
         slo.setSignRequest(StaxParserUtil.getBooleanAttributeValue(element, ConfigXmlConstants.SIGN_REQUEST_ATTR));
         slo.setValidateResponseSignature(StaxParserUtil.getBooleanAttributeValue(element, ConfigXmlConstants.VALIDATE_RESPONSE_SIGNATURE_ATTR));
         slo.setValidateRequestSignature(StaxParserUtil.getBooleanAttributeValue(element, ConfigXmlConstants.VALIDATE_REQUEST_SIGNATURE_ATTR));
-        slo.setSignatureCanonicalizationMethod(StaxParserUtil.getAttributeValue(element, ConfigXmlConstants.SIGNATURE_CANONICALIZATION_METHOD_ATTR));
         slo.setRequestBinding(StaxParserUtil.getAttributeValue(element, ConfigXmlConstants.REQUEST_BINDING_ATTR));
         slo.setResponseBinding(StaxParserUtil.getAttributeValue(element, ConfigXmlConstants.RESPONSE_BINDING_ATTR));
         slo.setSignResponse(StaxParserUtil.getBooleanAttributeValue(element, ConfigXmlConstants.SIGN_RESPONSE_ATTR));
@@ -86,7 +85,6 @@ public class IDPXmlParser extends AbstractParser {
         StartElement element = StaxParserUtil.getNextStartElement(xmlEventReader);
         sso.setSignRequest(StaxParserUtil.getBooleanAttributeValue(element, ConfigXmlConstants.SIGN_REQUEST_ATTR));
         sso.setValidateResponseSignature(StaxParserUtil.getBooleanAttributeValue(element, ConfigXmlConstants.VALIDATE_RESPONSE_SIGNATURE_ATTR));
-        sso.setSignatureCanonicalizationMethod(StaxParserUtil.getAttributeValue(element, ConfigXmlConstants.SIGNATURE_CANONICALIZATION_METHOD_ATTR));
         sso.setRequestBinding(StaxParserUtil.getAttributeValue(element, ConfigXmlConstants.REQUEST_BINDING_ATTR));
         sso.setResponseBinding(StaxParserUtil.getAttributeValue(element, ConfigXmlConstants.RESPONSE_BINDING_ATTR));
         sso.setBindingUrl(StaxParserUtil.getAttributeValue(element, ConfigXmlConstants.BINDING_URL_ATTR));
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/SPXmlParser.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/SPXmlParser.java
index 8df8500..089dc78 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/SPXmlParser.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/parsers/SPXmlParser.java
@@ -37,6 +37,8 @@ public class SPXmlParser extends AbstractParser {
         sp.setSslPolicy(StaxParserUtil.getAttributeValue(startElement, ConfigXmlConstants.SSL_POLICY_ATTR));
         sp.setLogoutPage(StaxParserUtil.getAttributeValue(startElement, ConfigXmlConstants.LOGOUT_PAGE_ATTR));
         sp.setNameIDPolicyFormat(StaxParserUtil.getAttributeValue(startElement, ConfigXmlConstants.NAME_ID_POLICY_FORMAT_ATTR));
+        sp.setSignatureCanonicalizationMethod(StaxParserUtil.getAttributeValue(startElement, ConfigXmlConstants.SIGNATURE_CANONICALIZATION_METHOD_ATTR));
+        sp.setSignatureAlgorithm(StaxParserUtil.getAttributeValue(startElement, ConfigXmlConstants.SIGNATURE_ALGORITHM_ATTR));
         sp.setForceAuthentication(StaxParserUtil.getBooleanAttributeValue(startElement, ConfigXmlConstants.FORCE_AUTHENTICATION_ATTR));
         while (xmlEventReader.hasNext()) {
             XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/SP.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/SP.java
index addafdb..bd48ba1 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/SP.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/config/SP.java
@@ -42,6 +42,8 @@ public class SP implements Serializable {
     private PrincipalNameMapping principalNameMapping;
     private Set<String> roleAttributes;
     private Set<String> roleFriendlyAttributes;
+    private String signatureAlgorithm;
+    private String signatureCanonicalizationMethod;
     private IDP idp;
 
     public String getEntityID() {
@@ -123,4 +125,20 @@ public class SP implements Serializable {
     public void setLogoutPage(String logoutPage) {
         this.logoutPage = logoutPage;
     }
+
+    public String getSignatureAlgorithm() {
+        return signatureAlgorithm;
+    }
+
+    public void setSignatureAlgorithm(String signatureAlgorithm) {
+        this.signatureAlgorithm = signatureAlgorithm;
+    }
+
+    public String getSignatureCanonicalizationMethod() {
+        return signatureCanonicalizationMethod;
+    }
+
+    public void setSignatureCanonicalizationMethod(String signatureCanonicalizationMethod) {
+        this.signatureCanonicalizationMethod = signatureCanonicalizationMethod;
+    }
 }
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/DefaultSamlDeployment.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/DefaultSamlDeployment.java
index 65612b3..28a4ead 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/DefaultSamlDeployment.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/DefaultSamlDeployment.java
@@ -3,6 +3,7 @@ package org.keycloak.adapters.saml;
 import org.keycloak.adapters.saml.SamlDeployment;
 import org.keycloak.adapters.saml.config.IDP;
 import org.keycloak.enums.SslRequired;
+import org.keycloak.saml.SignatureAlgorithm;
 
 import java.security.KeyPair;
 import java.security.PrivateKey;
@@ -18,7 +19,6 @@ public class DefaultSamlDeployment implements SamlDeployment {
     public static class DefaultSingleSignOnService implements IDP.SingleSignOnService {
         private boolean signRequest;
         private boolean validateResponseSignature;
-        private String signatureCanonicalizationMethod;
         private Binding requestBinding;
         private Binding responseBinding;
         private String requestBindingUrl;
@@ -33,12 +33,7 @@ public class DefaultSamlDeployment implements SamlDeployment {
             return validateResponseSignature;
         }
 
-        @Override
-        public String getSignatureCanonicalizationMethod() {
-            return signatureCanonicalizationMethod;
-        }
-
-        @Override
+         @Override
         public Binding getRequestBinding() {
             return requestBinding;
         }
@@ -61,10 +56,6 @@ public class DefaultSamlDeployment implements SamlDeployment {
             this.validateResponseSignature = validateResponseSignature;
         }
 
-        public void setSignatureCanonicalizationMethod(String signatureCanonicalizationMethod) {
-            this.signatureCanonicalizationMethod = signatureCanonicalizationMethod;
-        }
-
         public void setRequestBinding(Binding requestBinding) {
             this.requestBinding = requestBinding;
         }
@@ -83,7 +74,6 @@ public class DefaultSamlDeployment implements SamlDeployment {
         private boolean validateResponseSignature;
         private boolean signRequest;
         private boolean signResponse;
-        private String signatureCanonicalizationMethod;
         private Binding requestBinding;
         private Binding responseBinding;
         private String requestBindingUrl;
@@ -109,12 +99,7 @@ public class DefaultSamlDeployment implements SamlDeployment {
             return signResponse;
         }
 
-        @Override
-        public String getSignatureCanonicalizationMethod() {
-            return signatureCanonicalizationMethod;
-        }
-
-        @Override
+         @Override
         public Binding getRequestBinding() {
             return requestBinding;
         }
@@ -150,10 +135,6 @@ public class DefaultSamlDeployment implements SamlDeployment {
             this.signResponse = signResponse;
         }
 
-        public void setSignatureCanonicalizationMethod(String signatureCanonicalizationMethod) {
-            this.signatureCanonicalizationMethod = signatureCanonicalizationMethod;
-        }
-
         public void setRequestBinding(Binding requestBinding) {
             this.requestBinding = requestBinding;
         }
@@ -233,6 +214,8 @@ public class DefaultSamlDeployment implements SamlDeployment {
     private PrincipalNamePolicy principalNamePolicy = PrincipalNamePolicy.FROM_NAME_ID;
     private String principalAttributeName;
     private String logoutPage;
+    private SignatureAlgorithm signatureAlgorithm;
+    private String signatureCanonicalizationMethod;
 
 
     @Override
@@ -360,4 +343,22 @@ public class DefaultSamlDeployment implements SamlDeployment {
     public void setLogoutPage(String logoutPage) {
         this.logoutPage = logoutPage;
     }
+
+     @Override
+    public String getSignatureCanonicalizationMethod() {
+        return signatureCanonicalizationMethod;
+    }
+
+    public void setSignatureCanonicalizationMethod(String signatureCanonicalizationMethod) {
+        this.signatureCanonicalizationMethod = signatureCanonicalizationMethod;
+    }
+
+    @Override
+    public SignatureAlgorithm getSignatureAlgorithm() {
+        return signatureAlgorithm;
+    }
+
+    public void setSignatureAlgorithm(SignatureAlgorithm signatureAlgorithm) {
+        this.signatureAlgorithm = signatureAlgorithm;
+    }
 }
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/InitiateLogin.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/InitiateLogin.java
index 690a99c..1cef2b1 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/InitiateLogin.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/InitiateLogin.java
@@ -43,18 +43,21 @@ public class InitiateLogin implements AuthChallenge {
                 nameIDPolicyFormat =  JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get();
             }
 
-            String protocolBinding = JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get();
 
-            if (deployment.getIDP().getSingleSignOnService().getResponseBinding() == SamlDeployment.Binding.POST) {
-                protocolBinding = JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get();
-            }
 
             SAML2AuthnRequestBuilder authnRequestBuilder = new SAML2AuthnRequestBuilder()
                     .destination(destinationUrl)
                     .issuer(issuerURL)
                     .forceAuthn(deployment.isForceAuthentication())
-                    .protocolBinding(protocolBinding)
                     .nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat));
+            if (deployment.getIDP().getSingleSignOnService().getResponseBinding() != null) {
+                String protocolBinding = JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get();
+                if (deployment.getIDP().getSingleSignOnService().getResponseBinding() == SamlDeployment.Binding.POST) {
+                    protocolBinding = JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get();
+                }
+                authnRequestBuilder.protocolBinding(protocolBinding);
+
+            }
             if (deployment.getAssertionConsumerServiceUrl() != null) {
                 authnRequestBuilder.assertionConsumerUrl(deployment.getAssertionConsumerServiceUrl());
             }
@@ -67,8 +70,8 @@ public class InitiateLogin implements AuthChallenge {
                 if (keypair == null) {
                     throw new RuntimeException("Signing keys not configured");
                 }
-                if (deployment.getIDP().getSingleSignOnService().getSignatureCanonicalizationMethod() != null) {
-                    binding.canonicalizationMethod(deployment.getIDP().getSingleSignOnService().getSignatureCanonicalizationMethod());
+                if (deployment.getSignatureCanonicalizationMethod() != null) {
+                    binding.canonicalizationMethod(deployment.getSignatureCanonicalizationMethod());
                 }
 
                 binding.signWith(keypair);
@@ -78,7 +81,7 @@ public class InitiateLogin implements AuthChallenge {
 
             Document document = authnRequestBuilder.toDocument();
             SamlDeployment.Binding samlBinding = deployment.getIDP().getSingleSignOnService().getRequestBinding();
-            SamlUtil.sendSaml(httpFacade, actionUrl, binding, document, samlBinding);
+            SamlUtil.sendSaml(true, httpFacade, actionUrl, binding, document, samlBinding);
         } catch (Exception e) {
             throw new RuntimeException("Could not create authentication request.", e);
         }
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlAuthenticator.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlAuthenticator.java
index ca2da00..99c8c13 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlAuthenticator.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlAuthenticator.java
@@ -25,11 +25,11 @@ import org.keycloak.saml.common.constants.GeneralConstants;
 import org.keycloak.saml.common.exceptions.ConfigurationException;
 import org.keycloak.saml.common.exceptions.ParsingException;
 import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.Base64;
 import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
 import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
 import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
 import org.keycloak.saml.processing.web.util.PostBindingUtil;
-import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
 import org.keycloak.util.KeycloakUriBuilder;
 import org.keycloak.util.MultivaluedHashMap;
 import org.w3c.dom.Document;
@@ -103,7 +103,7 @@ public abstract class SamlAuthenticator {
         binding.relayState("logout");
 
         try {
-            SamlUtil.sendSaml(facade, deployment.getIDP().getSingleLogoutService().getRequestBindingUrl(), binding, logoutBuilder.buildDocument(), deployment.getIDP().getSingleLogoutService().getRequestBinding());
+            SamlUtil.sendSaml(true, facade, deployment.getIDP().getSingleLogoutService().getRequestBindingUrl(), binding, logoutBuilder.buildDocument(), deployment.getIDP().getSingleLogoutService().getRequestBinding());
         } catch (ProcessingException e) {
             throw new RuntimeException(e);
         } catch (ConfigurationException e) {
@@ -119,15 +119,22 @@ public abstract class SamlAuthenticator {
     protected AuthOutcome handleSamlRequest(String samlRequest, String relayState) {
         SAMLDocumentHolder holder = null;
         boolean postBinding = false;
+        String requestUri = facade.getRequest().getURI();
         if (facade.getRequest().getMethod().equalsIgnoreCase("GET")) {
+            // strip out query params
+            int index = requestUri.indexOf('?');
+            if (index > -1) {
+                requestUri = requestUri.substring(0, index);
+            }
             holder = SAMLRequestParser.parseRequestRedirectBinding(samlRequest);
         } else {
             postBinding = true;
             holder = SAMLRequestParser.parseRequestPostBinding(samlRequest);
         }
         RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
-        if (!facade.getRequest().getURI().toString().equals(requestAbstractType.getDestination())) {
-            throw new RuntimeException("destination not equal to request");
+        if (!requestUri.equals(requestAbstractType.getDestination().toString())) {
+            log.error("expected destination '" + requestUri + "' got '" + requestAbstractType.getDestination() + "'");
+            throw new RuntimeException("destination not equal to request.");
         }
 
         if (requestAbstractType instanceof LogoutRequestType) {
@@ -156,14 +163,15 @@ public abstract class SamlAuthenticator {
         builder.issuer(issuerURL);
         BaseSAML2BindingBuilder binding = new BaseSAML2BindingBuilder().relayState(relayState);
         if (deployment.getIDP().getSingleLogoutService().signResponse()) {
-            binding.signWith(deployment.getSigningKeyPair())
+            binding.signatureAlgorithm(deployment.getSignatureAlgorithm())
+                    .signWith(deployment.getSigningKeyPair())
                     .signDocument();
-            binding.canonicalizationMethod(deployment.getIDP().getSingleLogoutService().getSignatureCanonicalizationMethod());
+            if (deployment.getSignatureCanonicalizationMethod() != null) binding.canonicalizationMethod(deployment.getSignatureCanonicalizationMethod());
         }
 
 
         try {
-            SamlUtil.sendSaml(facade, deployment.getIDP().getSingleLogoutService().getResponseBindingUrl(), binding, builder.buildDocument(),
+            SamlUtil.sendSaml(false, facade, deployment.getIDP().getSingleLogoutService().getResponseBindingUrl(), binding, builder.buildDocument(),
                     deployment.getIDP().getSingleLogoutService().getResponseBinding());
         } catch (ConfigurationException e) {
             throw new RuntimeException(e);
@@ -180,7 +188,12 @@ public abstract class SamlAuthenticator {
     protected AuthOutcome handleSamlResponse(String samlResponse, String relayState) {
         SAMLDocumentHolder holder = null;
         boolean postBinding = false;
+        String requestUri = facade.getRequest().getURI();
         if (facade.getRequest().getMethod().equalsIgnoreCase("GET")) {
+            int index = requestUri.indexOf('?');
+            if (index > -1) {
+                requestUri = requestUri.substring(0, index);
+            }
             holder = extractRedirectBindingResponse(samlResponse);
         } else {
             postBinding = true;
@@ -188,18 +201,18 @@ public abstract class SamlAuthenticator {
         }
         StatusResponseType statusResponse = (StatusResponseType)holder.getSamlObject();
         // validate destination
-        if (!facade.getRequest().getURI().toString().equals(statusResponse.getDestination())) {
+        if (!requestUri.equals(statusResponse.getDestination())) {
             throw new RuntimeException("destination not equal to request");
         }
         if (statusResponse instanceof ResponseType) {
             if (deployment.getIDP().getSingleSignOnService().validateResponseSignature()) {
-                validateSamlSignature(holder, postBinding, GeneralConstants.SAML_REQUEST_KEY);
+                validateSamlSignature(holder, postBinding, GeneralConstants.SAML_RESPONSE_KEY);
             }
             return handleLoginResponse((ResponseType)statusResponse);
 
         } else {
             if (deployment.getIDP().getSingleLogoutService().validateResponseSignature()) {
-                validateSamlSignature(holder, postBinding, GeneralConstants.SAML_REQUEST_KEY);
+                validateSamlSignature(holder, postBinding, GeneralConstants.SAML_RESPONSE_KEY);
             }
             // todo need to check that it is actually a LogoutResponse
             return handleLogoutResponse(holder, statusResponse, relayState);
@@ -320,10 +333,16 @@ public abstract class SamlAuthenticator {
         sessionStore.saveAccount(account);
         completeAuthentication(account);
 
+
         // redirect to original request, it will be restored
-        facade.getResponse().setHeader("Location", sessionStore.getRedirectUri());
-        facade.getResponse().setStatus(302);
-        facade.getResponse().end();
+        String redirectUri = sessionStore.getRedirectUri();
+        if (redirectUri != null) {
+            facade.getResponse().setHeader("Location", redirectUri);
+            facade.getResponse().setStatus(302);
+            facade.getResponse().end();
+        } else {
+            log.debug("IDP initiated invocation");
+        }
 
 
         return AuthOutcome.AUTHENTICATED;
@@ -400,7 +419,9 @@ public abstract class SamlAuthenticator {
         String signature = facade.getRequest().getQueryParamValue(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
         String decodedAlgorithm = facade.getRequest().getQueryParamValue(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
 
-        if (request == null) throw new VerificationException("SAM was null");
+        if (request == null) {
+            throw new VerificationException("SAML Request was null");
+        }
         if (algorithm == null) throw new VerificationException("SigAlg was null");
         if (signature == null) throw new VerificationException("Signature was null");
 
@@ -417,7 +438,8 @@ public abstract class SamlAuthenticator {
         String rawQuery = builder.build().getRawQuery();
 
         try {
-            byte[] decodedSignature = RedirectBindingUtil.urlBase64Decode(signature);
+            //byte[] decodedSignature = RedirectBindingUtil.urlBase64Decode(signature);
+            byte[] decodedSignature = Base64.decode(signature);
 
             SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getFromXmlMethod(decodedAlgorithm);
             Signature validator = signatureAlgorithm.createSignature(); // todo plugin signature alg
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlDeployment.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlDeployment.java
index 9363624..4540b25 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlDeployment.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlDeployment.java
@@ -1,6 +1,7 @@
 package org.keycloak.adapters.saml;
 
 import org.keycloak.enums.SslRequired;
+import org.keycloak.saml.SignatureAlgorithm;
 
 import java.security.KeyPair;
 import java.security.PrivateKey;
@@ -32,7 +33,6 @@ public interface SamlDeployment {
         public interface SingleSignOnService {
             boolean signRequest();
             boolean validateResponseSignature();
-            String getSignatureCanonicalizationMethod();
             Binding getRequestBinding();
             Binding getResponseBinding();
             String getRequestBindingUrl();
@@ -42,7 +42,6 @@ public interface SamlDeployment {
             boolean validateResponseSignature();
             boolean signRequest();
             boolean signResponse();
-            String getSignatureCanonicalizationMethod();
             Binding getRequestBinding();
             Binding getResponseBinding();
             String getRequestBindingUrl();
@@ -59,6 +58,8 @@ public interface SamlDeployment {
     boolean isForceAuthentication();
     PrivateKey getDecryptionKey();
     KeyPair getSigningKeyPair();
+    String getSignatureCanonicalizationMethod();
+    SignatureAlgorithm getSignatureAlgorithm();
     String getAssertionConsumerServiceUrl();
     String getLogoutPage();
 
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlUtil.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlUtil.java
index b0981db..e0ea5ec 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlUtil.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/SamlUtil.java
@@ -13,9 +13,11 @@ import java.io.IOException;
  * @version $Revision: 1 $
  */
 public class SamlUtil {
-    public static void sendSaml(HttpFacade httpFacade, String actionUrl, BaseSAML2BindingBuilder binding, Document document, SamlDeployment.Binding samlBinding) throws ProcessingException, ConfigurationException, IOException {
+    public static void sendSaml(boolean asRequest, HttpFacade httpFacade, String actionUrl,
+                            BaseSAML2BindingBuilder binding, Document document,
+                            SamlDeployment.Binding samlBinding) throws ProcessingException, ConfigurationException, IOException {
         if (samlBinding == SamlDeployment.Binding.POST) {
-            String html = binding.postBinding(document).getHtmlRequest(actionUrl);
+            String html = asRequest ? binding.postBinding(document).getHtmlRequest(actionUrl) : binding.postBinding(document).getHtmlResponse(actionUrl) ;
             httpFacade.getResponse().setStatus(200);
             httpFacade.getResponse().setHeader("Content-Type", "text/html");
             httpFacade.getResponse().setHeader("Pragma", "no-cache");
@@ -23,9 +25,11 @@ public class SamlUtil {
             httpFacade.getResponse().getOutputStream().write(html.getBytes());
             httpFacade.getResponse().end();
         } else {
-            String uri = binding.redirectBinding(document).requestURI(actionUrl).toString();
+            String uri = asRequest ? binding.redirectBinding(document).requestURI(actionUrl).toString() : binding.redirectBinding(document).responseURI(actionUrl).toString();
             httpFacade.getResponse().setStatus(302);
             httpFacade.getResponse().setHeader("Location", uri);
+            httpFacade.getResponse().end();
         }
     }
+
 }
diff --git a/saml/client-adapter/core/src/test/java/org/keycloak/test/adapters/saml/XmlParserTest.java b/saml/client-adapter/core/src/test/java/org/keycloak/test/adapters/saml/XmlParserTest.java
index 84f03ea..c49cdf1 100755
--- a/saml/client-adapter/core/src/test/java/org/keycloak/test/adapters/saml/XmlParserTest.java
+++ b/saml/client-adapter/core/src/test/java/org/keycloak/test/adapters/saml/XmlParserTest.java
@@ -55,7 +55,6 @@ public class XmlParserTest {
         Assert.assertEquals("idp", idp.getEntityID());
         Assert.assertTrue(idp.getSingleSignOnService().isSignRequest());
         Assert.assertTrue(idp.getSingleSignOnService().isValidateResponseSignature());
-        Assert.assertEquals("canon", idp.getSingleSignOnService().getSignatureCanonicalizationMethod());
         Assert.assertEquals("post", idp.getSingleSignOnService().getRequestBinding());
         Assert.assertEquals("url", idp.getSingleSignOnService().getBindingUrl());
 
@@ -63,7 +62,6 @@ public class XmlParserTest {
         Assert.assertTrue(idp.getSingleLogoutService().isSignResponse());
         Assert.assertTrue(idp.getSingleLogoutService().isValidateRequestSignature());
         Assert.assertTrue(idp.getSingleLogoutService().isValidateResponseSignature());
-        Assert.assertEquals("canon", idp.getSingleLogoutService().getSignatureCanonicalizationMethod());
         Assert.assertEquals("redirect", idp.getSingleLogoutService().getRequestBinding());
         Assert.assertEquals("post", idp.getSingleLogoutService().getResponseBinding());
         Assert.assertEquals("posturl", idp.getSingleLogoutService().getPostBindingUrl());
diff --git a/saml/client-adapter/core/src/test/resources/keycloak-saml.xml b/saml/client-adapter/core/src/test/resources/keycloak-saml.xml
index 5755fd7..c161fa2 100755
--- a/saml/client-adapter/core/src/test/resources/keycloak-saml.xml
+++ b/saml/client-adapter/core/src/test/resources/keycloak-saml.xml
@@ -2,6 +2,8 @@
     <SP entityID="sp"
         sslPolicy="ssl"
         nameIDPolicyFormat="format"
+        signatureAlgorithm=""
+        sgnatureCanonicalizationMethod=""
         forceAuthentication="true">
         <Keys>
             <Key signing="true" >
@@ -27,7 +29,6 @@
         <IDP entityID="idp">
             <SingleSignOnService signRequest="true"
                                  validateResponseSignature="true"
-                                 signatureCanonicalizationMethod="canon"
                                  requestBinding="post"
                                  bindingUrl="url"
                     />
@@ -37,7 +38,6 @@
                     validateResponseSignature="true"
                     signRequest="true"
                     signResponse="true"
-                    signatureCanonicalizationMethod="canon"
                     requestBinding="redirect"
                     responseBinding="post"
                     postBindingUrl="posturl"
@@ -51,11 +51,5 @@
                 </Key>
             </Keys>
         </IDP>
-        <Keys>
-            <KeyStore>
-
-            </KeyStore>
-        </Keys>
-
     </SP>
 </keycloak-saml-adapter>
\ No newline at end of file
diff --git a/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/ServletSamlAuthMech.java b/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/ServletSamlAuthMech.java
index cd52536..a5a0bd4 100755
--- a/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/ServletSamlAuthMech.java
+++ b/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/ServletSamlAuthMech.java
@@ -5,6 +5,8 @@ import io.undertow.server.HttpServerExchange;
 import io.undertow.servlet.handlers.ServletRequestContext;
 import io.undertow.util.Headers;
 import org.keycloak.adapters.HttpFacade;
+import org.keycloak.adapters.InMemorySessionIdMapper;
+import org.keycloak.adapters.SessionIdMapper;
 import org.keycloak.adapters.saml.SamlDeployment;
 import org.keycloak.adapters.saml.SamlDeploymentContext;
 import org.keycloak.adapters.saml.SamlSessionStore;
@@ -23,13 +25,14 @@ import java.io.IOException;
  * @version $Revision: 1 $
  */
 public class ServletSamlAuthMech extends AbstractSamlAuthMech {
+    private SessionIdMapper idMapper = new InMemorySessionIdMapper();
     public ServletSamlAuthMech(SamlDeploymentContext deploymentContext, UndertowUserSessionManagement sessionManagement, String errorPage) {
         super(deploymentContext, sessionManagement, errorPage);
     }
 
     @Override
     protected SamlSessionStore getTokenStore(HttpServerExchange exchange, HttpFacade facade, SamlDeployment deployment, SecurityContext securityContext) {
-        return new ServletSamlSessionStore(exchange, sessionManagement, securityContext);
+        return new ServletSamlSessionStore(exchange, sessionManagement, securityContext, idMapper);
     }
 
     @Override
diff --git a/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/ServletSamlSessionStore.java b/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/ServletSamlSessionStore.java
index 696a29c..1f32666 100755
--- a/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/ServletSamlSessionStore.java
+++ b/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/ServletSamlSessionStore.java
@@ -4,11 +4,13 @@ import io.undertow.security.api.SecurityContext;
 import io.undertow.security.idm.Account;
 import io.undertow.server.HttpServerExchange;
 import io.undertow.server.session.Session;
+import io.undertow.server.session.SessionManager;
 import io.undertow.servlet.handlers.ServletRequestContext;
 import io.undertow.servlet.spec.HttpSessionImpl;
 import io.undertow.servlet.util.SavedRequest;
 import io.undertow.util.Sessions;
 import org.jboss.logging.Logger;
+import org.keycloak.adapters.SessionIdMapper;
 import org.keycloak.adapters.saml.SamlSession;
 import org.keycloak.adapters.saml.SamlSessionStore;
 import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
@@ -17,6 +19,8 @@ import org.keycloak.util.KeycloakUriBuilder;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 import java.security.Principal;
+import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
@@ -31,31 +35,66 @@ public class ServletSamlSessionStore implements SamlSessionStore {
     private final HttpServerExchange exchange;
     private final UndertowUserSessionManagement sessionManagement;
     private final SecurityContext securityContext;
+    private final SessionIdMapper idMapper;
 
     public ServletSamlSessionStore(HttpServerExchange exchange, UndertowUserSessionManagement sessionManagement,
-                                   SecurityContext securityContext) {
+                                   SecurityContext securityContext,
+                                   SessionIdMapper idMapper) {
         this.exchange = exchange;
         this.sessionManagement = sessionManagement;
         this.securityContext = securityContext;
+        this.idMapper = idMapper;
     }
 
     @Override
     public void logoutAccount() {
         HttpSession session = getSession(false);
         if (session != null) {
-            session.removeAttribute(SamlSession.class.getName());
+            SamlSession samlSession = (SamlSession)session.getAttribute(SamlSession.class.getName());
+            if (samlSession != null) {
+                if (samlSession.getSessionIndex() != null) {
+                    idMapper.removeSession(session.getId());
+                }
+                session.removeAttribute(SamlSession.class.getName());
+            }
             session.removeAttribute(SAML_REDIRECT_URI);
         }
     }
 
     @Override
     public void logoutByPrincipal(String principal) {
+        Set<String> sessions = idMapper.getUserSessions(principal);
+        if (sessions != null) {
+            List<String> ids = new LinkedList<>();
+            ids.addAll(sessions);
+            logoutSessionIds(ids);
+            for (String id : ids) {
+                idMapper.removeSession(id);
+            }
+        }
 
     }
 
     @Override
     public void logoutBySsoId(List<String> ssoIds) {
+        if (ssoIds == null) return;
+        List<String> sessionIds = new LinkedList<>();
+        for (String id : ssoIds) {
+             String sessionId = idMapper.getSessionFromSSO(id);
+             if (sessionId != null) {
+                 sessionIds.add(sessionId);
+                 idMapper.removeSession(sessionId);
+             }
 
+        }
+        logoutSessionIds(sessionIds);
+    }
+
+    protected void logoutSessionIds(List<String> sessionIds) {
+        if (sessionIds == null || sessionIds.isEmpty()) return;
+        final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
+        SessionManager sessionManager = servletRequestContext.getDeployment().getSessionManager();
+        sessionManagement.logoutHttpSessions(sessionManager, sessionIds);
     }
 
     @Override
@@ -93,6 +132,7 @@ public class ServletSamlSessionStore implements SamlSessionStore {
         HttpSession session = getSession(true);
         session.setAttribute(SamlSession.class.getName(), account);
         sessionManagement.login(servletRequestContext.getDeployment().getSessionManager());
+        idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), session.getId());
 
     }
 
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 383e1c5..d6b745b 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
@@ -625,6 +625,7 @@ public class SamlProtocol implements LoginProtocol {
         SAML2LogoutRequestBuilder logoutBuilder = new SAML2LogoutRequestBuilder()
                                          .assertionExpiration(realm.getAccessCodeLifespan())
                                          .issuer(getResponseIssuer(realm))
+                                         .sessionIndex(clientSession.getId())
                                          .userPrincipal(clientSession.getNote(SAML_NAME_ID), clientSession.getNote(SAML_NAME_ID_FORMAT))
                                          .destination(logoutUrl);
         return logoutBuilder;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlBindingTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlBindingTest.java
index 9639aab..429fe81 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlBindingTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/keycloaksaml/SamlBindingTest.java
@@ -68,20 +68,20 @@ public class SamlBindingTest {
         public void initWars() {
              ClassLoader classLoader = SamlBindingTest.class.getClassLoader();
 
-            //initializeSamlSecuredWar("/keycloak-saml/simple-post", "/sales-post",  "post.war", classLoader);
+            initializeSamlSecuredWar("/keycloak-saml/simple-post", "/sales-post",  "post.war", classLoader);
             initializeSamlSecuredWar("/keycloak-saml/signed-post", "/sales-post-sig",  "post-sig.war", classLoader);
-            //initializeSamlSecuredWar("/keycloak-saml/signed-post-email", "/sales-post-sig-email",  "post-sig-email.war", classLoader);
-            //initializeSamlSecuredWar("/keycloak-saml/signed-post-transient", "/sales-post-sig-transient",  "post-sig-transient.war", classLoader);
-            //initializeSamlSecuredWar("/keycloak-saml/signed-post-persistent", "/sales-post-sig-persistent",  "post-sig-persistent.war", classLoader);
+            initializeSamlSecuredWar("/keycloak-saml/signed-post-email", "/sales-post-sig-email",  "post-sig-email.war", classLoader);
+            initializeSamlSecuredWar("/keycloak-saml/signed-post-transient", "/sales-post-sig-transient",  "post-sig-transient.war", classLoader);
+            initializeSamlSecuredWar("/keycloak-saml/signed-post-persistent", "/sales-post-sig-persistent",  "post-sig-persistent.war", classLoader);
             //initializeSamlSecuredWar("/keycloak-saml/signed-metadata", "/sales-metadata",  "post-metadata.war", classLoader);
-            //initializeSamlSecuredWar("/keycloak-saml/signed-get", "/employee-sig",  "employee-sig.war", classLoader);
+            initializeSamlSecuredWar("/keycloak-saml/signed-get", "/employee-sig",  "employee-sig.war", classLoader);
             //initializeSamlSecuredWar("/saml/simple-get", "/employee",  "employee.war", classLoader);
-            //initializeSamlSecuredWar("/keycloak-saml/signed-front-get", "/employee-sig-front",  "employee-sig-front.war", classLoader);
+            initializeSamlSecuredWar("/keycloak-saml/signed-front-get", "/employee-sig-front",  "employee-sig-front.war", classLoader);
             //initializeSamlSecuredWar("/keycloak-saml/bad-client-signed-post", "/bad-client-sales-post-sig",  "bad-client-post-sig.war", classLoader);
             //initializeSamlSecuredWar("/keycloak-saml/bad-realm-signed-post", "/bad-realm-sales-post-sig",  "bad-realm-post-sig.war", classLoader);
             //initializeSamlSecuredWar("/keycloak-saml/encrypted-post", "/sales-post-enc",  "post-enc.war", classLoader);
             //uploadSP();
-            //server.getServer().deploy(createDeploymentInfo("employee.war", "/employee", SamlSPFacade.class));
+            server.getServer().deploy(createDeploymentInfo("employee.war", "/employee", SamlSPFacade.class));
 
 
 
@@ -411,7 +411,8 @@ public class SamlBindingTest {
         driver.navigate().to("http://localhost:8081/employee-sig?GLO=true");
         checkLoggedOut("http://localhost:8081/employee-sig/");
         driver.navigate().to("http://localhost:8081/employee-sig-front/");
-        Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
+        String currentUrl = driver.getCurrentUrl();
+        Assert.assertTrue(currentUrl.startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
         driver.navigate().to("http://localhost:8081/sales-post-sig/");
         Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
 
@@ -505,6 +506,4 @@ public class SamlBindingTest {
         response.close();
         client.close();
     }
-
-
 }
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-front-get/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/signed-front-get/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..51c8e0c
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/signed-front-get/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,44 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/employee-sig-front/"
+        sslPolicy="EXTERNAL"
+        logoutPage="/logout.jsp"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8080/employee-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8080/employee-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="REDIRECT"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    validateRequestSignature="true"
+                    validateResponseSignature="true"
+                    signRequest="true"
+                    signResponse="true"
+                    requestBinding="REDIRECT"
+                    responseBinding="REDIRECT"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-front-get/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/keycloak-saml/signed-front-get/WEB-INF/keystore.jks
new file mode 100755
index 0000000..4daad21
Binary files /dev/null and b/testsuite/integration/src/test/resources/keycloak-saml/signed-front-get/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-get/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/signed-get/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..909216d
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/signed-get/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,44 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/employee-sig/"
+        sslPolicy="EXTERNAL"
+        logoutPage="/logout.jsp"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8080/employee-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8080/employee-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="REDIRECT"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    validateRequestSignature="true"
+                    validateResponseSignature="true"
+                    signRequest="true"
+                    signResponse="true"
+                    requestBinding="REDIRECT"
+                    responseBinding="REDIRECT"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-get/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/keycloak-saml/signed-get/WEB-INF/keystore.jks
new file mode 100755
index 0000000..4daad21
Binary files /dev/null and b/testsuite/integration/src/test/resources/keycloak-saml/signed-get/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-post-email/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/signed-post-email/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..ef9856a
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/signed-post-email/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,44 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/sales-post-sig-email/"
+        sslPolicy="EXTERNAL"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8080/sales-post-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    validateRequestSignature="true"
+                    validateResponseSignature="true"
+                    signRequest="true"
+                    signResponse="true"
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-post-email/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/keycloak-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/keycloak-saml/signed-post-email/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-post-persistent/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/signed-post-persistent/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..7bc05f6
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/signed-post-persistent/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,45 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/sales-post-sig-persistent/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8080/sales-post-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    validateRequestSignature="true"
+                    validateResponseSignature="true"
+                    signRequest="true"
+                    signResponse="true"
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-post-persistent/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/keycloak-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/keycloak-saml/signed-post-persistent/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-post-transient/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/signed-post-transient/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..5d614fa
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/signed-post-transient/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,45 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/sales-post-sig-transient/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8080/sales-post-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    validateRequestSignature="true"
+                    validateResponseSignature="true"
+                    signRequest="true"
+                    signResponse="true"
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/signed-post-transient/WEB-INF/keystore.jks b/testsuite/integration/src/test/resources/keycloak-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/keycloak-saml/signed-post-transient/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/simple-post/WEB-INF/keycloak-saml.xml b/testsuite/integration/src/test/resources/keycloak-saml/simple-post/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..501e8f5
--- /dev/null
+++ b/testsuite/integration/src/test/resources/keycloak-saml/simple-post/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,24 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/sales-post/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleMapping>
+            <Attribute name="Role"/>
+        </RoleMapping>
+        <IDP entityID="idp">
+            <SingleSignOnService requestBinding="POST"
+                                 bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
+                    />
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration/src/test/resources/keycloak-saml/testsaml.json b/testsuite/integration/src/test/resources/keycloak-saml/testsaml.json
index e929c24..c6b682d 100755
--- a/testsuite/integration/src/test/resources/keycloak-saml/testsaml.json
+++ b/testsuite/integration/src/test/resources/keycloak-saml/testsaml.json
@@ -209,7 +209,7 @@
             "attributes": {
                 "saml.server.signature": "true",
                 "saml.client.signature": "true",
-                "saml.signature.algorithm": "RSA_SHA1",
+                "saml.signature.algorithm": "RSA_SHA256",
                 "saml.authnstatement": "true",
                 "saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
             }