idp descriptor

This commit is contained in:
Bill Burke 2014-10-28 12:49:31 -04:00
parent e5934e9d54
commit 12e2a4698d
4 changed files with 61 additions and 1 deletions

View file

@ -100,11 +100,14 @@
in the response. in the response.
</para> </para>
<section> <section>
<title>SAML Entity Descriptor Import</title> <title>SAML Entity Descriptor</title>
<para> <para>
If you go into the admin console in the application list menu page you will see an <literal>Import</literal> If you go into the admin console in the application list menu page you will see an <literal>Import</literal>
button. If you click on that you can import SAML Service Provider definitions using the <ulink url="http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf">Entity Descriptor</ulink> button. If you click on that you can import SAML Service Provider definitions using the <ulink url="http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf">Entity Descriptor</ulink>
format described in SAML 2.0. You should review all the information there to make sure everything is set up correctly. format described in SAML 2.0. You should review all the information there to make sure everything is set up correctly.
</para> </para>
<para>
Each realm has a URL where you can view the XML entity descriptor for the IDP. <literal>root/realms/{realm}/protocol/saml/descriptor</literal>
</para>
</section> </section>
</chapter> </chapter>

View file

@ -19,7 +19,9 @@ import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.oidc.OpenIDConnectService; import org.keycloak.protocol.oidc.OpenIDConnectService;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.ClientSessionCode; import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.services.resources.flows.Flows; import org.keycloak.services.resources.flows.Flows;
import org.keycloak.util.StreamUtil;
import org.picketlink.common.constants.GeneralConstants; import org.picketlink.common.constants.GeneralConstants;
import org.picketlink.identity.federation.core.saml.v2.common.SAMLDocumentHolder; import org.picketlink.identity.federation.core.saml.v2.common.SAMLDocumentHolder;
import org.picketlink.identity.federation.saml.v2.SAML2Object; import org.picketlink.identity.federation.saml.v2.SAML2Object;
@ -32,6 +34,8 @@ import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam; import javax.ws.rs.FormParam;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
@ -42,6 +46,7 @@ import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Providers; import javax.ws.rs.ext.Providers;
import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.Signature; import java.security.Signature;
@ -379,4 +384,19 @@ public class SamlService {
return new PostBindingProtocol().execute(samlRequest, samlResponse, relayState); return new PostBindingProtocol().execute(samlRequest, samlResponse, relayState);
} }
@GET
@Path("descriptor")
@Produces(MediaType.APPLICATION_XML)
public String getDescriptor() throws Exception {
InputStream is = getClass().getResourceAsStream("/idp-metadata-template.xml");
String template = StreamUtil.readString(is);
template = template.replace("${idp.entityID}", RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString());
template = template.replace("${idp.sso.HTTP-POST}", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
template = template.replace("${idp.sso.HTTP-Redirect}", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
template = template.replace("${idp.sls.HTTP-POST}", RealmsResource.protocolUrl(uriInfo).build(realm.getName(), SamlProtocol.LOGIN_PROTOCOL).toString());
template = template.replace("${idp.signing.certificate}", realm.getCertificatePem());
return template;
}
} }

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<EntitiesDescriptor Name="urn:keycloak"
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EntityDescriptor entityID="${idp.entityID}">
<IDPSSODescriptor WantAuthnRequestsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient
</NameIDFormat>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="${idp.sso.HTTP-POST}" />
<SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="${idp.sso.HTTP-Redirect}" />
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="${idp.sls.HTTP-POST}" />
<KeyDescriptor use="signing">
<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<dsig:X509Data>
<dsig:X509Certificate>
${idp.signing.certificate}
</dsig:X509Certificate>
</dsig:X509Data>
</dsig:KeyInfo>
</KeyDescriptor>
</IDPSSODescriptor>
</EntityDescriptor>
</EntitiesDescriptor>

View file

@ -77,6 +77,14 @@ public class RealmsResource {
return base.path(RealmsResource.class).path(RealmsResource.class, "getAccountService"); return base.path(RealmsResource.class).path(RealmsResource.class, "getAccountService");
} }
public static UriBuilder protocolUrl(UriBuilder base) {
return base.path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
}
public static UriBuilder protocolUrl(UriInfo uriInfo) {
return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
}
@Path("{realm}/login-status-iframe.html") @Path("{realm}/login-status-iframe.html")
@GET @GET
@Produces(MediaType.TEXT_HTML) @Produces(MediaType.TEXT_HTML)