keycloak-aplcache

KEYCLOAK-1881 Client installers

11/3/2016 1:26:44 PM

Details

diff --git a/services/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlClientInstallation.java b/services/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlClientInstallation.java
index 2175b32..14166ce 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlClientInstallation.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlClientInstallation.java
@@ -18,7 +18,6 @@
 package org.keycloak.protocol.saml.installation;
 
 import org.keycloak.Config;
-import org.keycloak.common.util.PemUtils;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
@@ -42,14 +41,14 @@ public class KeycloakSamlClientInstallation implements ClientInstallationProvide
     @Override
     public Response generateInstallation(KeycloakSession session, RealmModel realm, ClientModel client, URI baseUri) {
         SamlClient samlClient = new SamlClient(client);
-        StringBuffer buffer = new StringBuffer();
+        StringBuilder buffer = new StringBuilder();
         buffer.append("<keycloak-saml-adapter>\n");
         baseXml(session, realm, client, baseUri, samlClient, buffer);
         buffer.append("</keycloak-saml-adapter>\n");
         return Response.ok(buffer.toString(), MediaType.TEXT_PLAIN_TYPE).build();
     }
 
-    public static void baseXml(KeycloakSession session, RealmModel realm, ClientModel client, URI baseUri, SamlClient samlClient, StringBuffer buffer) {
+    public static void baseXml(KeycloakSession session, RealmModel realm, ClientModel client, URI baseUri, SamlClient samlClient, StringBuilder buffer) {
         buffer.append("    <SP entityID=\"").append(client.getClientId()).append("\"\n");
         buffer.append("        sslPolicy=\"").append(realm.getSslRequired().name()).append("\"\n");
         buffer.append("        logoutPage=\"SPECIFY YOUR LOGOUT PAGE!\">\n");
@@ -113,15 +112,6 @@ public class KeycloakSamlClientInstallation implements ClientInstallationProvide
         buffer.append("                                 postBindingUrl=\"").append(bindingUrl).append("\"\n");
         buffer.append("                                 redirectBindingUrl=\"").append(bindingUrl).append("\"");
         buffer.append("/>\n");
-        if (samlClient.requiresRealmSignature()) {
-            buffer.append("            <Keys>\n");
-            buffer.append("                <Key signing=\"true\">\n");
-            buffer.append("                    <CertificatePem>\n");
-            buffer.append("                       ").append(PemUtils.encodeCertificate(session.keys().getActiveKey(realm).getCertificate())).append("\n");
-            buffer.append("                    </CertificatePem>\n");
-            buffer.append("                </Key>\n");
-            buffer.append("            </Keys>\n");
-        }
         buffer.append("        </IDP>\n");
         buffer.append("    </SP>\n");
     }
@@ -138,7 +128,7 @@ public class KeycloakSamlClientInstallation implements ClientInstallationProvide
 
     @Override
     public String getHelpText() {
-        return "Keycloak SAML adapter configuration file.  Put this in WEB-INF directory if your WAR.";
+        return "Keycloak SAML adapter configuration file.  Put this in WEB-INF directory of your WAR.";
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlSubsystemInstallation.java b/services/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlSubsystemInstallation.java
index ea77d47..bde0ccd 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlSubsystemInstallation.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/installation/KeycloakSamlSubsystemInstallation.java
@@ -39,7 +39,7 @@ public class KeycloakSamlSubsystemInstallation implements ClientInstallationProv
     @Override
     public Response generateInstallation(KeycloakSession session, RealmModel realm, ClientModel client, URI baseUri) {
         SamlClient samlClient = new SamlClient(client);
-        StringBuffer buffer = new StringBuffer();
+        StringBuilder buffer = new StringBuilder();
         buffer.append("<secure-deployment name=\"YOUR-WAR.war\">\n");
         KeycloakSamlClientInstallation.baseXml(session, realm, client, baseUri, samlClient, buffer);
         buffer.append("</secure-deployment>\n");
diff --git a/services/src/main/java/org/keycloak/protocol/saml/installation/SamlIDPDescriptorClientInstallation.java b/services/src/main/java/org/keycloak/protocol/saml/installation/SamlIDPDescriptorClientInstallation.java
index 4b84363..3c451b3 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/installation/SamlIDPDescriptorClientInstallation.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/installation/SamlIDPDescriptorClientInstallation.java
@@ -32,6 +32,11 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
 import java.net.URI;
+import java.util.Set;
+import java.util.TreeSet;
+import org.keycloak.dom.saml.v2.metadata.KeyTypes;
+import org.keycloak.keys.KeyMetadata;
+import org.keycloak.saml.SPMetadataDescriptor;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -41,49 +46,61 @@ public class SamlIDPDescriptorClientInstallation implements ClientInstallationPr
     public static String getIDPDescriptorForClient(KeycloakSession session, RealmModel realm, ClientModel client, URI serverBaseUri) {
         SamlClient samlClient = new SamlClient(client);
         String idpEntityId = RealmsResource.realmBaseUrl(UriBuilder.fromUri(serverBaseUri)).build(realm.getName()).toString();
-        String idp = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
-                 "<EntityDescriptor entityID=\"" + idpEntityId + "\"\n" +
-                "                   xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\"\n" +
-                "                   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
-                "   <IDPSSODescriptor WantAuthnRequestsSigned=\"" + Boolean.toString(samlClient.requiresClientSignature()) + "\"\n" +
-                "      protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\">\n";
+        StringBuilder sb = new StringBuilder();
+        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+          + "<EntityDescriptor entityID=\"").append(idpEntityId).append("\"\n"
+          + "                   xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\"\n"
+          + "                   xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\"\n"
+          + "                   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
+          + "   <IDPSSODescriptor WantAuthnRequestsSigned=\"")
+          .append(samlClient.requiresClientSignature())
+          .append("\"\n"
+            + "      protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\">\n");
         if (samlClient.forceNameIDFormat() && samlClient.getNameIDFormat() != null) {
-            idp +=  "   <NameIDFormat>" + samlClient.getNameIDFormat() + "</NameIDFormat>\n";
+            sb.append("   <NameIDFormat>").append(samlClient.getNameIDFormat()).append("</NameIDFormat>\n");
         } else {
-            idp +=  "   <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>\n" +
-                    "   <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>\n" +
-                    "   <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>\n" +
-                    "   <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>\n";
+            sb.append("   <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>\n"
+              + "   <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>\n"
+              + "   <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>\n"
+              + "   <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>\n");
         }
         String bindUrl = RealmsResource.protocolUrl(UriBuilder.fromUri(serverBaseUri)).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString();
-        idp +=  "\n" +
-                "      <SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\"\n" +
-                "         Location=\"" + bindUrl + "\" />\n";
-        if (!samlClient.forcePostBinding()) {
-           idp +=   "      <SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n" +
-                    "         Location=\"" + bindUrl + "\" />\n";
+        sb.append("\n"
+          + "      <SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\"\n"
+          + "         Location=\"").append(bindUrl).append("\" />\n");
+        if (! samlClient.forcePostBinding()) {
+           sb.append("      <SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n"
+             + "         Location=\"").append(bindUrl).append("\" />\n");
 
         }
-        idp +=  "      <SingleLogoutService\n" +
-                "         Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\"\n" +
-                "         Location=\"" + bindUrl + "\" />\n";
-        if (!samlClient.forcePostBinding()) {
-            idp +=  "      <SingleLogoutService\n" +
-                    "         Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n" +
-                    "         Location=\"" + bindUrl + "\" />\n";
+        sb.append("      <SingleLogoutService\n"
+          + "         Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\"\n"
+          + "         Location=\"").append(bindUrl).append("\" />\n");
+        if (! samlClient.forcePostBinding()) {
+            sb.append("      <SingleLogoutService\n"
+              + "         Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\"\n"
+              + "         Location=\"").append(bindUrl).append("\" />\n");
         }
-        idp +=  "      <KeyDescriptor use=\"signing\">\n" +
-                "          <dsig:KeyInfo xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\">\n" +
-                "              <dsig:X509Data>\n" +
-                "                  <dsig:X509Certificate>\n" +
-                "                      " + PemUtils.encodeCertificate(session.keys().getActiveKey(realm).getCertificate()) + "\n" +
-                "                  </dsig:X509Certificate>\n" +
-                "              </dsig:X509Data>\n" +
-                "          </dsig:KeyInfo>\n" +
-                "      </KeyDescriptor>\n" +
-                "   </IDPSSODescriptor>\n" +
-                "</EntityDescriptor>\n";
-        return idp;
+
+        Set<KeyMetadata> keys = new TreeSet<>((o1, o2) -> o1.getStatus() == o2.getStatus() // Status can be only PASSIVE OR ACTIVE, push PASSIVE to end of list
+          ? (int) (o2.getProviderPriority() - o1.getProviderPriority())
+          : (o1.getStatus() == KeyMetadata.Status.PASSIVE ? 1 : -1));
+        keys.addAll(session.keys().getKeys(realm, false));
+        for (KeyMetadata key : keys) {
+            addKeyInfo(sb, key, KeyTypes.SIGNING.value());
+        }
+
+        sb.append("   </IDPSSODescriptor>\n"
+          + "</EntityDescriptor>\n");
+        return sb.toString();
+    }
+
+    private static void addKeyInfo(StringBuilder target, KeyMetadata key, String purpose) {
+        if (key == null) {
+            return;
+        }
+
+        target.append(SPMetadataDescriptor.xmlKeyInfo("      ", key.getKid(), PemUtils.encodeCertificate(key.getCertificate()), purpose, false));
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/protocol/saml/installation/SamlSPDescriptorClientInstallation.java b/services/src/main/java/org/keycloak/protocol/saml/installation/SamlSPDescriptorClientInstallation.java
index ced0d7a..6349953 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/installation/SamlSPDescriptorClientInstallation.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/installation/SamlSPDescriptorClientInstallation.java
@@ -46,7 +46,7 @@ public class SamlSPDescriptorClientInstallation implements ClientInstallationPro
         if (logoutUrl == null) logoutUrl = client.getManagementUrl();
         String nameIdFormat = samlClient.getNameIDFormat();
         if (nameIdFormat == null) nameIdFormat = SamlProtocol.SAML_DEFAULT_NAMEID_FORMAT;
-        String spCertificate = SPMetadataDescriptor.xmlKeyInfo(null, samlClient.getClientSigningCertificate(), KeyTypes.SIGNING.value(), true);
+        String spCertificate = SPMetadataDescriptor.xmlKeyInfo("        ", null, samlClient.getClientSigningCertificate(), KeyTypes.SIGNING.value(), true);
         return SPMetadataDescriptor.getSPDescriptor(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get(), assertionUrl, logoutUrl, samlClient.requiresClientSignature(), client.getClientId(), nameIdFormat, spCertificate);
     }