commit
eaaaf91963
5 changed files with 75 additions and 2 deletions
|
@ -88,10 +88,26 @@
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
You have to specify an admin URL if you want logout to work. This should be a URL that will except single logout
|
||||||
|
requests from the Keycloak server. You should also specify a default redirect url. Keycloak will redirect to this
|
||||||
|
url after single logout is complete.
|
||||||
|
</para>
|
||||||
<para>
|
<para>
|
||||||
One thing to note is that roles are not treated as a hierarchy. So, any role mappings will just be added
|
One thing to note is that roles are not treated as a hierarchy. So, any role mappings will just be added
|
||||||
to the role attributes in the SAML document using their basic name. So, if you have multiple applicaiton roles
|
to the role attributes in the SAML document using their basic name. So, if you have multiple application roles
|
||||||
you might have name collisions. You can use the Scope Mapping menu item to control which role mappings are set
|
you might have name collisions. You can use the Scope Mapping menu item to control which role mappings are set
|
||||||
in the response.
|
in the response.
|
||||||
</para>
|
</para>
|
||||||
|
<section>
|
||||||
|
<title>SAML Entity Descriptor</title>
|
||||||
|
<para>
|
||||||
|
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>
|
||||||
|
format described in SAML 2.0. You should review all the information there to make sure everything is set up correctly.
|
||||||
|
</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>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
@ -102,7 +102,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
|
||||||
}
|
}
|
||||||
deploymentContext = new AdapterDeploymentContext(kd);
|
deploymentContext = new AdapterDeploymentContext(kd);
|
||||||
context.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
context.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
||||||
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deploymentContext, getNext(), getContainer(), getObjectName());
|
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deploymentContext, getNext(), getContainer());
|
||||||
setNext(actions);
|
setNext(actions);
|
||||||
|
|
||||||
nodesRegistrationManagement = new NodesRegistrationManagement();
|
nodesRegistrationManagement = new NodesRegistrationManagement();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
29
saml/saml-protocol/src/main/resources/idp-metadata-template.xml
Executable file
29
saml/saml-protocol/src/main/resources/idp-metadata-template.xml
Executable 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>
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue