keycloak-aplcache

Details

diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java b/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java
old mode 100644
new mode 100755
index f38d840..bc007ae
--- a/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java
+++ b/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java
@@ -18,6 +18,10 @@
 package org.keycloak.broker.provider;
 
 import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.RealmModel;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
 
 /**
  * @author Pedro Igor
@@ -35,6 +39,11 @@ public abstract class AbstractIdentityProvider<C extends IdentityProviderModel> 
     }
 
     @Override
+    public Response export(UriInfo uriInfo, RealmModel realm, String format) {
+        return Response.noContent().build();
+    }
+
+    @Override
     public void close() {
         // no-op
     }
diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProvider.java b/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProvider.java
old mode 100644
new mode 100755
index ac1e3dc..f754eeb
--- a/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProvider.java
+++ b/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProvider.java
@@ -19,9 +19,11 @@ package org.keycloak.broker.provider;
 
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.RealmModel;
 import org.keycloak.provider.Provider;
 
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
 
 /**
  * @author Pedro Igor
@@ -76,4 +78,12 @@ public interface IdentityProvider<C extends IdentityProviderModel> extends Provi
      * @return
      */
     Response retrieveToken(FederatedIdentityModel identity);
+
+    /**
+     * Export a representation of the IdentityProvider in a specific format.  For example, a SAML EntityDescriptor
+     *
+     * @return
+     */
+    Response export(UriInfo uriInfo, RealmModel realm, String format);
+
 }
diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
old mode 100644
new mode 100755
index 1ad696c..c136c1d
--- a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
+++ b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java
@@ -24,6 +24,8 @@ import org.keycloak.broker.provider.AuthenticationResponse;
 import org.keycloak.broker.provider.FederatedIdentity;
 import org.keycloak.broker.provider.IdentityBrokerException;
 import org.keycloak.models.FederatedIdentityModel;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.saml.SAML2AuthnRequestBuilder;
 import org.keycloak.protocol.saml.SAML2NameIDPolicyBuilder;
 import org.picketlink.common.constants.JBossSAMLConstants;
@@ -55,6 +57,7 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriBuilder;
@@ -85,7 +88,8 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
     public AuthenticationResponse handleRequest(AuthenticationRequest request) {
         try {
             UriInfo uriInfo = request.getUriInfo();
-            String issuerURL = UriBuilder.fromUri(uriInfo.getBaseUri()).build().toString();
+            RealmModel realm = request.getRealm();
+            String issuerURL = getEntityId(uriInfo, realm);
             String destinationUrl = getConfig().getSingleSignOnServiceUrl();
             String nameIDPolicyFormat = getConfig().getNameIDPolicyFormat();
 
@@ -109,15 +113,15 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
                     .relayState(request.getState());
 
             if (getConfig().isWantAuthnRequestsSigned()) {
-                PrivateKey privateKey = request.getRealm().getPrivateKey();
-                PublicKey publicKey = request.getRealm().getPublicKey();
+                PrivateKey privateKey = realm.getPrivateKey();
+                PublicKey publicKey = realm.getPublicKey();
 
                 if (privateKey == null) {
-                    throw new IdentityBrokerException("Identity Provider [" + getConfig().getName() + "] wants a signed authentication request. But the Realm [" + request.getRealm().getName() + "] does not have a private key.");
+                    throw new IdentityBrokerException("Identity Provider [" + getConfig().getName() + "] wants a signed authentication request. But the Realm [" + realm.getName() + "] does not have a private key.");
                 }
 
                 if (publicKey == null) {
-                    throw new IdentityBrokerException("Identity Provider [" + getConfig().getName() + "] wants a signed authentication request. But the Realm [" + request.getRealm().getName() + "] does not have a public key.");
+                    throw new IdentityBrokerException("Identity Provider [" + getConfig().getName() + "] wants a signed authentication request. But the Realm [" + realm.getName() + "] does not have a public key.");
                 }
 
                 KeyPair keypair = new KeyPair(publicKey, privateKey);
@@ -136,6 +140,10 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
         }
     }
 
+    private String getEntityId(UriInfo uriInfo, RealmModel realm) {
+        return UriBuilder.fromUri(uriInfo.getBaseUri()).path("realms").path(realm.getName()).build().toString();
+    }
+
     @Override
     public String getRelayState(AuthenticationRequest request) {
         return getRequestParameter(request, RELAY_STATE_PARAMETER);
@@ -283,4 +291,45 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
 
         return requestParameters.getFirst(parameterName);
     }
+
+    @Override
+    public Response export(UriInfo uriInfo, RealmModel realm, String format) {
+
+        String authnBinding = JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get();
+
+        if (getConfig().isPostBindingAuthnRequest()) {
+            authnBinding = JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get();
+        }
+
+        String assertionConsumerService = uriInfo.getBaseUriBuilder().path("realms").path(realm.getName()).path("broker").path(getConfig().getProviderId()).build().toString();
+
+
+
+        String descriptor =
+                "<EntityDescriptor entityID=\"" + getEntityId(uriInfo, realm) + "\n" +
+                "    <SPSSODescriptor AuthnRequestsSigned=\"" + getConfig().isWantAuthnRequestsSigned() + "\n" +
+                "            protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol http://schemas.xmlsoap.org/ws/2003/07/secext\">\n" +
+                "        <NameIDFormat>" + getConfig().getNameIDPolicyFormat() + "\n" +
+                "        </NameIDFormat>\n" +
+// todo single logout service description
+//                "        <SingleLogoutService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" Location=\"http://localhost:8081/sales-metadata/\"/>\n" +
+                "        <AssertionConsumerService\n" +
+                "                Binding=\"" + authnBinding + "\" Location=\"" + assertionConsumerService + "\n" +
+                "                index=\"1\" isDefault=\"true\" />\n";
+        if (getConfig().isWantAuthnRequestsSigned()) {
+            descriptor +=
+                "        <KeyDescriptor use=\"signing\">\n" +
+                "            <dsig:KeyInfo xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\">\n" +
+                "                <dsig:X509Data>\n" +
+                "                    <dsig:X509Certificate>\n" + realm.getCertificatePem() + "\n" +
+                "                    </dsig:X509Certificate>\n" +
+                "                </dsig:X509Data>\n" +
+                "            </dsig:KeyInfo>\n" +
+                "        </KeyDescriptor>\n";
+        }
+        descriptor +=
+                "    </SPSSODescriptor>\n" +
+                "</EntityDescriptor>\n";
+        return Response.ok(descriptor, MediaType.APPLICATION_XML_TYPE).build();
+    }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index c95b618..0bf652b 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -167,6 +167,17 @@ public class IdentityBrokerService {
         return getToken(providerId, false);
     }
 
+    @GET
+    @Path("{provider_id}/export")
+    public Response export(@PathParam("provider_id") String providerId, @QueryParam("format") String format) {
+        try {
+            IdentityProvider identityProvider = getIdentityProvider(providerId);
+            return identityProvider.export(uriInfo, realmModel, format);
+        } catch (Exception e) {
+            return redirectToErrorPage("Could not export public broker configuration for identity provider [" + providerId + "].", e);
+        }
+    }
+
     private Response getToken(String providerId, boolean forceRetrieval) {
         this.event.event(EventType.IDENTITY_PROVIDER_RETRIEVE_TOKEN);
 
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 0198644..812696f 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -601,9 +601,6 @@ public class LoginActionsService {
         return authManager.redirectAfterSuccessfulFlow(session, realm, userSession, clientSession, request, uriInfo, clientConnection);
     }
 
-
-
-
     @Path("profile")
     @POST
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
diff --git a/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml.json b/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml.json
index 60c0396..5757b28 100755
--- a/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml.json
+++ b/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml.json
@@ -8,7 +8,7 @@
     "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
     "applications": [
         {
-            "name": "http://localhost:8081/auth/",
+            "name": "http://localhost:8081/auth/realms/realm-with-broker",
             "enabled": true,
             "redirectUris": [
                 "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic"
diff --git a/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml-with-signature.json b/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml-with-signature.json
index 4b3c505..db027d8 100755
--- a/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml-with-signature.json
+++ b/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-saml-with-signature.json
@@ -8,7 +8,7 @@
     "publicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgj8r0029eL0jJKXv6XbNj+QqsZO25HhZ0IjTEtb8mfh0tju/X8c6dXgILh5wU7OF00U+0mSYSE/+rrYKmY5g4oCleTe1+abavATP1tamtXGAUYqdutaXPrVn9yMsCWEPchSPZlEGq5iBJdA+xh9ejUmZJYXmln26HUVWq71/jC9GpjbRmFQ37f0X7WJoGyiqyttfKkKfUeBmRbX/0P0Zm6DVze8HjCDVPBllZE0a3HCgSF0rp0+s1xn7o91qdWKVattAVsGNjjDPz/sgwHOyyhDtSyajwXU+K/QUZ9pV4moGtwC9uIEymTylP7bu7qnxXIhfouEa+fEjAzTs0HJ5JQIDAQAB",
     "applications": [
         {
-            "name": "http://localhost:8081/auth/",
+            "name": "http://localhost:8081/auth/realms/realm-with-broker",
             "enabled": true,
             "redirectUris": [
                 "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-signed-idp"