KEYCLOAK-3268
This commit is contained in:
parent
c925033944
commit
46b4bb0909
4 changed files with 135 additions and 31 deletions
|
@ -26,13 +26,7 @@ public class SPMetadataDescriptor {
|
|||
String descriptor =
|
||||
"<EntityDescriptor xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"" + entityId + "\">\n" +
|
||||
" <SPSSODescriptor AuthnRequestsSigned=\"" + wantAuthnRequestsSigned + "\"\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" +
|
||||
" <SingleLogoutService Binding=\"" + binding + "\" Location=\"" + logoutEndpoint + "\"/>\n" +
|
||||
" <NameIDFormat>" + nameIDPolicyFormat + "\n" +
|
||||
" </NameIDFormat>\n" +
|
||||
" <AssertionConsumerService\n" +
|
||||
" Binding=\"" + binding + "\" Location=\"" + assertionEndpoint + "\"\n" +
|
||||
" index=\"1\" isDefault=\"true\" />\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";
|
||||
if (wantAuthnRequestsSigned) {
|
||||
descriptor +=
|
||||
" <KeyDescriptor use=\"signing\">\n" +
|
||||
|
@ -44,6 +38,13 @@ public class SPMetadataDescriptor {
|
|||
" </dsig:KeyInfo>\n" +
|
||||
" </KeyDescriptor>\n";
|
||||
}
|
||||
descriptor +=
|
||||
" <SingleLogoutService Binding=\"" + binding + "\" Location=\"" + logoutEndpoint + "\"/>\n" +
|
||||
" <NameIDFormat>" + nameIDPolicyFormat + "\n" +
|
||||
" </NameIDFormat>\n" +
|
||||
" <AssertionConsumerService\n" +
|
||||
" Binding=\"" + binding + "\" Location=\"" + assertionEndpoint + "\"\n" +
|
||||
" index=\"1\" isDefault=\"true\" />\n";
|
||||
descriptor +=
|
||||
" </SPSSODescriptor>\n" +
|
||||
"</EntityDescriptor>\n";
|
||||
|
|
|
@ -18,15 +18,30 @@
|
|||
|
||||
<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">
|
||||
xmlns:dsig="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">
|
||||
|
||||
<KeyDescriptor use="signing">
|
||||
<dsig:KeyInfo>
|
||||
<dsig:X509Data>
|
||||
<dsig:X509Certificate>
|
||||
${idp.signing.certificate}
|
||||
</dsig:X509Certificate>
|
||||
</dsig:X509Data>
|
||||
</dsig:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
<SingleLogoutService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||
Location="${idp.sls.HTTP-POST}" />
|
||||
<SingleLogoutService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
|
||||
Location="${idp.sso.HTTP-Redirect}" />
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
|
||||
|
||||
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||
Location="${idp.sso.HTTP-POST}" />
|
||||
<SingleSignOnService
|
||||
|
@ -35,21 +50,6 @@
|
|||
<SingleSignOnService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
|
||||
Location="${idp.sso.HTTP-POST}" />
|
||||
<SingleLogoutService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||
Location="${idp.sls.HTTP-POST}" />
|
||||
<SingleLogoutService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
|
||||
Location="${idp.sso.HTTP-Redirect}" />
|
||||
<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>
|
|
@ -244,6 +244,11 @@
|
|||
<artifactId>picketlink-wildfly-common</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-federation</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.wildfly</groupId>
|
||||
<artifactId>wildfly-undertow</artifactId>
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.testsuite.saml;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.common.util.StreamUtil;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.protocol.saml.SamlProtocol;
|
||||
import org.keycloak.protocol.saml.SamlService;
|
||||
import org.keycloak.saml.SPMetadataDescriptor;
|
||||
import org.keycloak.services.resources.RealmsResource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
import javax.xml.validation.Validator;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ValidationTest {
|
||||
|
||||
public static String getIDPMetadataDescriptor() throws IOException {
|
||||
InputStream is = SamlService.class.getResourceAsStream("/idp-metadata-template.xml");
|
||||
String template = StreamUtil.readString(is);
|
||||
template = template.replace("${idp.entityID}", "http://keycloak.org/auth/realms/test");
|
||||
template = template.replace("${idp.sso.HTTP-POST}", "http://keycloak.org/auth/realms/test/saml");
|
||||
template = template.replace("${idp.sso.HTTP-Redirect}", "http://keycloak.org/auth/realms/test/saml");
|
||||
template = template.replace("${idp.sls.HTTP-POST}", "http://keycloak.org/auth/realms/test/saml");
|
||||
template = template.replace("${idp.signing.certificate}", KeycloakModelUtils.generateKeyPairCertificate("test").getCertificate());
|
||||
return template;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore // ignore because it goes out to web
|
||||
public void testIDPDescriptor() throws Exception {
|
||||
URL schemaFile = getClass().getResource("/schema/saml/v2/saml-schema-metadata-2.0.xsd");
|
||||
Source xmlFile = new StreamSource(new ByteArrayInputStream(getIDPMetadataDescriptor().getBytes()), "IDPSSODescriptor");
|
||||
SchemaFactory schemaFactory = SchemaFactory
|
||||
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||
Schema schema = schemaFactory.newSchema(schemaFile);
|
||||
Validator validator = schema.newValidator();
|
||||
try {
|
||||
validator.validate(xmlFile);
|
||||
System.out.println(xmlFile.getSystemId() + " is valid");
|
||||
} catch (SAXException e) {
|
||||
System.out.println(xmlFile.getSystemId() + " is NOT valid");
|
||||
System.out.println("Reason: " + e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
@Test
|
||||
@Ignore // ignore because it goes out to web
|
||||
public void testBrokerExportDescriptor() throws Exception {
|
||||
URL schemaFile = getClass().getResource("/schema/saml/v2/saml-schema-metadata-2.0.xsd");
|
||||
Source xmlFile = new StreamSource(new ByteArrayInputStream(SPMetadataDescriptor.getSPDescriptor(
|
||||
"POST", "http://realm/assertion", "http://realm/logout", true, "test", SamlProtocol.SAML_DEFAULT_NAMEID_FORMAT, KeycloakModelUtils.generateKeyPairCertificate("test").getCertificate()
|
||||
).getBytes()), "SP Descriptor");
|
||||
SchemaFactory schemaFactory = SchemaFactory
|
||||
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||
Schema schema = schemaFactory.newSchema(schemaFile);
|
||||
Validator validator = schema.newValidator();
|
||||
try {
|
||||
validator.validate(xmlFile);
|
||||
System.out.println(xmlFile.getSystemId() + " is valid");
|
||||
} catch (SAXException e) {
|
||||
System.out.println(xmlFile.getSystemId() + " is NOT valid");
|
||||
System.out.println("Reason: " + e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue