KEYCLOAK-6471 Refactor SAML metadata parsers
This commit is contained in:
parent
1d88d061e6
commit
2a4663c940
54 changed files with 2525 additions and 794 deletions
|
@ -18,6 +18,10 @@ package org.keycloak.dom.saml.v2.metadata;
|
|||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Java class for ExtensionsType complex type.
|
||||
|
@ -39,13 +43,49 @@ import org.w3c.dom.Element;
|
|||
*/
|
||||
public class ExtensionsType {
|
||||
|
||||
protected Element element = null;
|
||||
protected List<Object> any = new ArrayList<Object>();
|
||||
|
||||
/**
|
||||
* Function is obsoleted with getAny
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public Element getElement() {
|
||||
return element;
|
||||
return (any.isEmpty()) ? null : (Element) any.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function is obsoleted with addExtension
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public void setElement(Element element) {
|
||||
this.element = element;
|
||||
any.clear();
|
||||
any.add(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an extension
|
||||
*
|
||||
* @param extension
|
||||
*/
|
||||
public void addExtension(Object extension) {
|
||||
any.add(extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an extension
|
||||
*
|
||||
* @param extension
|
||||
*/
|
||||
public void removeExtension(Object extension) {
|
||||
any.remove(extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the any property.
|
||||
*/
|
||||
public List<Object> getAny() {
|
||||
return Collections.unmodifiableList(this.any);
|
||||
}
|
||||
}
|
|
@ -56,6 +56,11 @@ public class EncryptionMethodType {
|
|||
OAEPparams = oAEPparams;
|
||||
}
|
||||
|
||||
public EncryptionMethod() {
|
||||
this.keySize = null;
|
||||
this.OAEPparams = null;
|
||||
}
|
||||
|
||||
public BigInteger getKeySize() {
|
||||
return keySize;
|
||||
}
|
||||
|
@ -63,6 +68,14 @@ public class EncryptionMethodType {
|
|||
public byte[] getOAEPparams() {
|
||||
return OAEPparams;
|
||||
}
|
||||
|
||||
public void setKeySize(BigInteger keySize) {
|
||||
this.keySize = keySize;
|
||||
}
|
||||
|
||||
public void setOAEPparams(byte[] OAEPparams) {
|
||||
this.OAEPparams = OAEPparams;
|
||||
}
|
||||
}
|
||||
|
||||
public EncryptionMethodType(String algo) {
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.w3c.dom.Document;
|
|||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.datatype.Duration;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.Location;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
|
@ -52,7 +53,10 @@ import javax.xml.validation.SchemaFactory;
|
|||
import javax.xml.validation.Validator;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.xml.datatype.XMLGregorianCalendar;
|
||||
|
||||
|
@ -288,6 +292,20 @@ public class StaxParserUtil {
|
|||
return value == null ? null : XMLTimeUtil.parse(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Attribute value
|
||||
*
|
||||
* @param startElement
|
||||
* @param tag localpart of the qname of the attribute
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Duration getXmlDurationAttributeValue(StartElement startElement, HasQName attrName) throws ParsingException {
|
||||
Attribute attr = startElement.getAttributeByName(attrName.getQName());
|
||||
String value = getAttributeValue(attr);
|
||||
return value == null ? null : XMLTimeUtil.parseAsDuration(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Attribute value
|
||||
*
|
||||
|
@ -391,6 +409,29 @@ public class StaxParserUtil {
|
|||
return StaxParserUtil.getAttributeValueRP(attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a space delimited list of strings
|
||||
*
|
||||
* @param startElement
|
||||
* @param attrName
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static List<String> getRequiredStringListAttributeValue(StartElement startElement, HasQName attrName) throws ParsingException{
|
||||
List<String> protocolEnum = new ArrayList<>();
|
||||
|
||||
String val = StaxParserUtil.getRequiredAttributeValue(startElement, attrName);
|
||||
if (StringUtil.isNotNull(val)) {
|
||||
StringTokenizer st = new StringTokenizer(val);
|
||||
while (st.hasMoreTokens()) {
|
||||
protocolEnum.add(st.nextToken());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return protocolEnum;
|
||||
}
|
||||
|
||||
private static final String JDK_TRANSFORMER_PROPERTY = "picketlink.jdk.transformer";
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.keycloak.saml.processing.core.parsers.saml;
|
||||
|
||||
import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLAttributeQueryParser;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLSloRequestParser;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLSloResponseParser;
|
||||
|
@ -53,8 +54,6 @@ import java.io.InputStream;
|
|||
*/
|
||||
public class SAMLParser extends AbstractParser {
|
||||
|
||||
private static final SAMLEntityDescriptorParser SAML_ENTITY_DESCRIPTOR_PARSER = new SAMLEntityDescriptorParser();
|
||||
private static final SAMLEntitiesDescriptorParser SAML_ENTITIES_DESCRIPTOR_PARSER = new SAMLEntitiesDescriptorParser();
|
||||
private static final SAML11ResponseParser SAML_11_RESPONSE_PARSER = new SAML11ResponseParser();
|
||||
private static final SAML11RequestParser SAML_11_REQUEST_PARSER = new SAML11RequestParser();
|
||||
|
||||
|
@ -88,9 +87,8 @@ public class SAMLParser extends AbstractParser {
|
|||
|
||||
PARSERS.put(SAMLAssertionQNames.AUTHN_STATEMENT.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLAuthnStatementParser.getInstance(); }});
|
||||
|
||||
// TODO: Change to SamlMetadataElements
|
||||
PARSERS.put(JBossSAMLConstants.ENTITY_DESCRIPTOR.getAsQName(), new ParserFactory() { @Override public StaxParser create() { return SAML_ENTITY_DESCRIPTOR_PARSER; }});
|
||||
PARSERS.put(JBossSAMLConstants.ENTITIES_DESCRIPTOR.getAsQName(),new ParserFactory() { @Override public StaxParser create() { return SAML_ENTITIES_DESCRIPTOR_PARSER; }});
|
||||
PARSERS.put(SAMLMetadataQNames.ENTITY_DESCRIPTOR.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLEntityDescriptorParser.getInstance(); }});
|
||||
PARSERS.put(SAMLMetadataQNames.ENTITIES_DESCRIPTOR.getQName(),new ParserFactory() { @Override public StaxParser create() { return SAMLEntitiesDescriptorParser.getInstance(); }});
|
||||
|
||||
PARSERS.put(SAMLProtocolQNames.ATTRIBUTE_QUERY.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLAttributeQueryParser.getInstance(); }});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.saml.common.parsers.AbstractStaxParser;
|
||||
import org.keycloak.saml.processing.core.parsers.util.QNameEnumLookup;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
abstract public class AbstractStaxSamlMetadataParser<T> extends AbstractStaxParser<T, SAMLMetadataQNames> {
|
||||
|
||||
protected static final QNameEnumLookup<SAMLMetadataQNames> LOOKUP = new QNameEnumLookup(SAMLMetadataQNames.values());
|
||||
|
||||
|
||||
public AbstractStaxSamlMetadataParser(SAMLMetadataQNames expectedStartElement) {
|
||||
super(expectedStartElement.getQName(), SAMLMetadataQNames.UNKNOWN_ELEMENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SAMLMetadataQNames getElementFromName(QName name) {
|
||||
return LOOKUP.from(name);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 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.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.saml.common.constants.JBossSAMLConstants;
|
||||
import javax.xml.namespace.QName;
|
||||
import org.keycloak.saml.common.parsers.AbstractStaxParser;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public abstract class AbstractStaxSamlParser<T> extends AbstractStaxParser<T, JBossSAMLConstants> {
|
||||
|
||||
public AbstractStaxSamlParser(JBossSAMLConstants expectedStartElement) {
|
||||
super(expectedStartElement.getAsQName(), JBossSAMLConstants.UNKNOWN_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isUnknownElement(JBossSAMLConstants token) {
|
||||
return token == JBossSAMLConstants.UNKNOWN_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JBossSAMLConstants getElementFromName(QName name) {
|
||||
JBossSAMLConstants res = JBossSAMLConstants.from(name);
|
||||
|
||||
if ((res == null || res == JBossSAMLConstants.UNKNOWN_VALUE) && name != null) {
|
||||
// Relax and search regardless of namespace
|
||||
res = JBossSAMLConstants.from(name.getLocalPart());
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLArtifactResolutionServiceParser extends SAMLIndexedEndpointTypeParser {
|
||||
|
||||
private static final SAMLArtifactResolutionServiceParser INSTANCE = new SAMLArtifactResolutionServiceParser();
|
||||
|
||||
public SAMLArtifactResolutionServiceParser() {
|
||||
super(SAMLMetadataQNames.ARTIFACT_RESOLUTION_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLArtifactResolutionServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLAssertinIDRequestServiceParser extends SAMLEndpointTypeParser {
|
||||
|
||||
private static final SAMLAssertinIDRequestServiceParser INSTANCE = new SAMLAssertinIDRequestServiceParser();
|
||||
|
||||
public SAMLAssertinIDRequestServiceParser() {
|
||||
super(SAMLMetadataQNames.ASSERTION_ID_REQUEST_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLAssertinIDRequestServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLAssertionConsumerServiceParser extends SAMLIndexedEndpointTypeParser {
|
||||
|
||||
private static final SAMLAssertionConsumerServiceParser INSTANCE = new SAMLAssertionConsumerServiceParser();
|
||||
|
||||
public SAMLAssertionConsumerServiceParser() {
|
||||
super(SAMLMetadataQNames.ASSERTION_CONSUMER_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLAssertionConsumerServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.AttributeAuthorityDescriptorType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLAttributeAuthorityDescriptorParser extends SAMLRoleDecriptorTypeParser<AttributeAuthorityDescriptorType> {
|
||||
|
||||
private static final SAMLAttributeAuthorityDescriptorParser INSTANCE = new SAMLAttributeAuthorityDescriptorParser();
|
||||
|
||||
public SAMLAttributeAuthorityDescriptorParser() {
|
||||
super(SAMLMetadataQNames.ATTRIBUTE_AUTHORITY_DESCRIPTOR);
|
||||
}
|
||||
|
||||
public static SAMLAttributeAuthorityDescriptorParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AttributeAuthorityDescriptorType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
List<String> protocolEnum = StaxParserUtil.getRequiredStringListAttributeValue(element, SAMLMetadataQNames.ATTR_PROTOCOL_SUPPORT_ENUMERATION);
|
||||
AttributeAuthorityDescriptorType descriptor = new AttributeAuthorityDescriptorType(protocolEnum);
|
||||
|
||||
parseOptionalArguments(element, descriptor);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, AttributeAuthorityDescriptorType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case ATTRIBUTE_SERVICE:
|
||||
target.addAttributeService(SAMLAttributeServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ASSERTION_ID_REQUEST_SERVICE:
|
||||
target.addAssertionIDRequestService(SAMLAssertinIDRequestServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case NAMEID_FORMAT:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ATTRIBUTE_PROFILE:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.addAttributeProfile(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ATTRIBUTE:
|
||||
target.addAttribute(SAMLAttributeParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
super.processSubElement(xmlEventReader, target, element, elementDetail);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.AttributeConsumingServiceType;
|
||||
import org.keycloak.dom.saml.v2.metadata.LocalizedNameType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
|
||||
import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.ATTR_LANG;
|
||||
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLAttributeConsumingServiceParser extends AbstractStaxSamlMetadataParser<AttributeConsumingServiceType> {
|
||||
|
||||
private static final SAMLAttributeConsumingServiceParser INSTANCE = new SAMLAttributeConsumingServiceParser();
|
||||
|
||||
public SAMLAttributeConsumingServiceParser() {
|
||||
super(SAMLMetadataQNames.ATTRIBUTE_CONSUMING_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLAttributeConsumingServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AttributeConsumingServiceType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
int index = Integer.parseInt(StaxParserUtil.getRequiredAttributeValue(element, SAMLMetadataQNames.ATTR_INDEX));
|
||||
|
||||
AttributeConsumingServiceType service = new AttributeConsumingServiceType(index);
|
||||
service.setIsDefault(StaxParserUtil.getBooleanAttributeValue(element, SAMLMetadataQNames.ATTR_IS_DEFAULT));
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, AttributeConsumingServiceType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case SERVICE_NAME:
|
||||
LocalizedNameType serviceName = new LocalizedNameType(StaxParserUtil.getAttributeValue(elementDetail, ATTR_LANG));
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
serviceName.setValue(StaxParserUtil.getElementText(xmlEventReader));
|
||||
target.addServiceName(serviceName);
|
||||
break;
|
||||
|
||||
case SERVICE_DESCRIPTION:
|
||||
target.addServiceDescription(new LocalizedNameType(StaxParserUtil.getAttributeValue(elementDetail, ATTR_LANG)));
|
||||
break;
|
||||
|
||||
case REQUESTED_ATTRIBUTE:
|
||||
target.addRequestedAttribute(SAMLRequestedAttributeParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.assertion.AttributeType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAttributeValueParser;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
|
||||
/**
|
||||
* Parse the <conditions> in the saml assertion
|
||||
*
|
||||
* @since Oct 14, 2010
|
||||
*/
|
||||
public class SAMLAttributeParser extends AbstractStaxSamlMetadataParser<AttributeType> {
|
||||
|
||||
private static final SAMLAttributeParser INSTANCE = new SAMLAttributeParser();
|
||||
|
||||
private SAMLAttributeParser() {
|
||||
super(SAMLMetadataQNames.ATTRIBUTE);
|
||||
}
|
||||
|
||||
public static SAMLAttributeParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AttributeType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
String name = StaxParserUtil.getRequiredAttributeValue(element, SAMLMetadataQNames.ATTR_NAME);
|
||||
final AttributeType attribute = new AttributeType(name);
|
||||
|
||||
attribute.setFriendlyName(StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_FRIENDLY_NAME));
|
||||
attribute.setNameFormat(StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_NAME_FORMAT));
|
||||
|
||||
final String x500Encoding = StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_X500_ENCODING);
|
||||
if (x500Encoding != null) {
|
||||
attribute.getOtherAttributes().put(SAMLMetadataQNames.ATTR_X500_ENCODING.getQName(), x500Encoding);
|
||||
}
|
||||
|
||||
return attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, AttributeType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case ATTRIBUTE_VALUE:
|
||||
target.addAttributeValue(SAMLAttributeValueParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLAttributeServiceParser extends SAMLEndpointTypeParser {
|
||||
|
||||
private static final SAMLAttributeServiceParser INSTANCE = new SAMLAttributeServiceParser();
|
||||
|
||||
public SAMLAttributeServiceParser() {
|
||||
super(SAMLMetadataQNames.ATTRIBUTE_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLAttributeServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.AuthnAuthorityDescriptorType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLAuthnAuthorityDescriptorParser extends SAMLRoleDecriptorTypeParser<AuthnAuthorityDescriptorType> {
|
||||
|
||||
private static final SAMLAuthnAuthorityDescriptorParser INSTANCE = new SAMLAuthnAuthorityDescriptorParser();
|
||||
|
||||
public SAMLAuthnAuthorityDescriptorParser() {
|
||||
super(SAMLMetadataQNames.AUTHN_AUTHORITY_DESCRIPTOR);
|
||||
}
|
||||
|
||||
public static SAMLAuthnAuthorityDescriptorParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthnAuthorityDescriptorType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
List<String> protocolEnum = StaxParserUtil.getRequiredStringListAttributeValue(element, SAMLMetadataQNames.ATTR_PROTOCOL_SUPPORT_ENUMERATION);
|
||||
AuthnAuthorityDescriptorType descriptor = new AuthnAuthorityDescriptorType(protocolEnum);
|
||||
|
||||
parseOptionalArguments(element, descriptor);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, AuthnAuthorityDescriptorType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case AUTHN_QUERY_SERVICE:
|
||||
target.addAuthnQueryService(SAMLAuthnQueryServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ASSERTION_ID_REQUEST_SERVICE:
|
||||
target.addAssertionIDRequestService(SAMLAssertinIDRequestServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case NAMEID_FORMAT:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
super.processSubElement(xmlEventReader, target, element, elementDetail);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLAuthnQueryServiceParser extends SAMLEndpointTypeParser {
|
||||
|
||||
private static final SAMLAuthnQueryServiceParser INSTANCE = new SAMLAuthnQueryServiceParser();
|
||||
|
||||
public SAMLAuthnQueryServiceParser() {
|
||||
super(SAMLMetadataQNames.AUTHN_QUERY_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLAuthnQueryServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLAuthzServiceParser extends SAMLEndpointTypeParser {
|
||||
|
||||
private static final SAMLAuthzServiceParser INSTANCE = new SAMLAuthzServiceParser();
|
||||
|
||||
public SAMLAuthzServiceParser() {
|
||||
super(SAMLMetadataQNames.AUTHZ_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLAuthzServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.ContactType;
|
||||
import org.keycloak.dom.saml.v2.metadata.ContactTypeType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
|
||||
import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.ATTR_CONTACT_TYPE;
|
||||
import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.CONTACT_PERSON;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLContactPersonParser extends AbstractStaxSamlMetadataParser<ContactType> {
|
||||
|
||||
private static final SAMLContactPersonParser INSTANCE = new SAMLContactPersonParser();
|
||||
|
||||
public SAMLContactPersonParser() {
|
||||
super(CONTACT_PERSON);
|
||||
}
|
||||
|
||||
public static SAMLContactPersonParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContactType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
return new ContactType(ContactTypeType.fromValue(StaxParserUtil.getRequiredAttributeValue(element, ATTR_CONTACT_TYPE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, ContactType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case COMPANY:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.setCompany(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
case GIVEN_NAME:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.setGivenName(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
case SURNAME:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.setSurName(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
case EMAIL_ADDRESS:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.addEmailAddress(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
case TELEPHONE_NUMBER:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.addTelephone(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
case EXTENSIONS:
|
||||
target.setExtensions(SAMLExtensionsParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.xmlsec.w3.xmlenc.EncryptionMethodType;
|
||||
import org.keycloak.saml.common.constants.GeneralConstants;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.ENCRYPTION_METHOD;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLEncryptionMethodParser extends AbstractStaxSamlMetadataParser<EncryptionMethodType> {
|
||||
|
||||
private static final SAMLEncryptionMethodParser INSTANCE = new SAMLEncryptionMethodParser();
|
||||
|
||||
public SAMLEncryptionMethodParser() {
|
||||
super(ENCRYPTION_METHOD);
|
||||
}
|
||||
|
||||
public static SAMLEncryptionMethodParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EncryptionMethodType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
return new EncryptionMethodType(StaxParserUtil.getRequiredAttributeValue(element, SAMLMetadataQNames.ATTR_ALGORITHM));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, EncryptionMethodType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch(element) {
|
||||
case KEY_SIZE:
|
||||
{
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
BigInteger keySize = BigInteger.valueOf(Long.valueOf(StaxParserUtil.getElementText(xmlEventReader)));
|
||||
|
||||
EncryptionMethodType.EncryptionMethod encMethod = target.getEncryptionMethod();
|
||||
if (encMethod == null) {
|
||||
encMethod = new EncryptionMethodType.EncryptionMethod();
|
||||
target.setEncryptionMethod(encMethod);
|
||||
}
|
||||
|
||||
encMethod.setKeySize(keySize);
|
||||
}
|
||||
break;
|
||||
|
||||
case OAEP_PARAMS:
|
||||
{
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
byte[] OAEPparams = StaxParserUtil.getElementText(xmlEventReader).getBytes(GeneralConstants.SAML_CHARSET);
|
||||
EncryptionMethodType.EncryptionMethod encMethod = target.getEncryptionMethod();
|
||||
if (encMethod == null){
|
||||
encMethod = new EncryptionMethodType.EncryptionMethod();
|
||||
target.setEncryptionMethod(encMethod);
|
||||
}
|
||||
|
||||
encMethod.setOAEPparams(OAEPparams);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.EndpointType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public abstract class SAMLEndpointTypeParser extends AbstractStaxSamlMetadataParser<EndpointType> {
|
||||
|
||||
public SAMLEndpointTypeParser(SAMLMetadataQNames expectedStartElement) {
|
||||
super(expectedStartElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EndpointType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
String binding = StaxParserUtil.getRequiredAttributeValue(element, SAMLMetadataQNames.ATTR_BINDING);
|
||||
String location = StaxParserUtil.getRequiredAttributeValue(element, SAMLMetadataQNames.ATTR_LOCATION);
|
||||
|
||||
EndpointType endpoint = new EndpointType(URI.create(binding), URI.create(location));
|
||||
|
||||
String responseLocation = StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_RESPONSE_LOCATION);
|
||||
|
||||
if (responseLocation != null) {
|
||||
endpoint.setResponseLocation(URI.create(responseLocation));
|
||||
}
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, EndpointType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
}
|
||||
}
|
|
@ -17,24 +17,12 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.ExtensionsType;
|
||||
import org.keycloak.saml.common.PicketLinkLogger;
|
||||
import org.keycloak.saml.common.PicketLinkLoggerFactory;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLConstants;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.parsers.AbstractParser;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.Attribute;
|
||||
import javax.xml.stream.events.EndElement;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import org.keycloak.saml.common.parsers.StaxParser;
|
||||
|
||||
/**
|
||||
* Parse the SAML Entities Descriptor
|
||||
|
@ -42,74 +30,53 @@ import org.keycloak.saml.common.parsers.StaxParser;
|
|||
* @author Anil.Saldhana@redhat.com
|
||||
* @since Jan 31, 2011
|
||||
*/
|
||||
public class SAMLEntitiesDescriptorParser extends AbstractParser {
|
||||
public class SAMLEntitiesDescriptorParser extends AbstractStaxSamlMetadataParser<EntitiesDescriptorType> {
|
||||
|
||||
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
|
||||
private static final SAMLEntitiesDescriptorParser INSTANCE = new SAMLEntitiesDescriptorParser();
|
||||
|
||||
private static final String EDT = JBossSAMLConstants.ENTITIES_DESCRIPTOR.get();
|
||||
public SAMLEntitiesDescriptorParser() {
|
||||
super(SAMLMetadataQNames.ENTITIES_DESCRIPTOR);
|
||||
}
|
||||
|
||||
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
public static SAMLEntitiesDescriptorParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
StaxParserUtil.validate(startElement, EDT);
|
||||
|
||||
EntitiesDescriptorType entitiesDescriptorType = new EntitiesDescriptorType();
|
||||
@Override
|
||||
protected EntitiesDescriptorType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
EntitiesDescriptorType descriptor = new EntitiesDescriptorType();
|
||||
|
||||
// Parse the attributes
|
||||
Attribute validUntil = startElement.getAttributeByName(new QName(JBossSAMLConstants.VALID_UNTIL.get()));
|
||||
if (validUntil != null) {
|
||||
String validUntilValue = StaxParserUtil.getAttributeValue(validUntil);
|
||||
entitiesDescriptorType.setValidUntil(XMLTimeUtil.parse(validUntilValue));
|
||||
descriptor.setID(StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_ID));
|
||||
descriptor.setValidUntil(StaxParserUtil.getXmlTimeAttributeValue(element, SAMLMetadataQNames.ATTR_VALID_UNTIL));
|
||||
descriptor.setCacheDuration(StaxParserUtil.getXmlDurationAttributeValue(element, SAMLMetadataQNames.ATTR_CACHE_DURATION));
|
||||
descriptor.setName(StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_NAME));
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
Attribute id = startElement.getAttributeByName(new QName(JBossSAMLConstants.ID.get()));
|
||||
if (id != null) {
|
||||
entitiesDescriptorType.setID(StaxParserUtil.getAttributeValue(id));
|
||||
}
|
||||
|
||||
Attribute name = startElement.getAttributeByName(new QName(JBossSAMLConstants.NAME.get()));
|
||||
if (name != null) {
|
||||
entitiesDescriptorType.setName(StaxParserUtil.getAttributeValue(name));
|
||||
}
|
||||
|
||||
Attribute cacheDuration = startElement.getAttributeByName(new QName(JBossSAMLConstants.CACHE_DURATION.get()));
|
||||
if (cacheDuration != null) {
|
||||
entitiesDescriptorType
|
||||
.setCacheDuration(XMLTimeUtil.parseAsDuration(StaxParserUtil.getAttributeValue(cacheDuration)));
|
||||
}
|
||||
|
||||
// Get the Child Elements
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
StaxParserUtil.validate((EndElement) xmlEvent, EDT);
|
||||
StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, EntitiesDescriptorType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case SIGNATURE:
|
||||
Element sig = StaxParserUtil.getDOMElement(xmlEventReader);
|
||||
target.setSignature(sig);
|
||||
break;
|
||||
}
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if (JBossSAMLConstants.ENTITY_DESCRIPTOR.get().equals(localPart)) {
|
||||
SAMLEntityDescriptorParser entityParser = new SAMLEntityDescriptorParser();
|
||||
entitiesDescriptorType.addEntityDescriptor(entityParser.parse(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.EXTENSIONS__METADATA.get().equalsIgnoreCase(localPart)) {
|
||||
entitiesDescriptorType.setExtensions(parseExtensions(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.ENTITIES_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
|
||||
SAMLEntitiesDescriptorParser parser = new SAMLEntitiesDescriptorParser();
|
||||
entitiesDescriptorType.addEntityDescriptor(parser.parse(xmlEventReader));
|
||||
} else if (localPart.equals(JBossSAMLConstants.SIGNATURE.get())) {
|
||||
entitiesDescriptorType.setSignature(StaxParserUtil.getDOMElement(xmlEventReader));
|
||||
} else
|
||||
throw logger.parserUnknownTag(localPart, startElement.getLocation());
|
||||
}
|
||||
return entitiesDescriptorType;
|
||||
}
|
||||
case EXTENSIONS:
|
||||
target.setExtensions(SAMLExtensionsParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ENTITY_DESCRIPTOR:
|
||||
target.addEntityDescriptor(SAMLEntityDescriptorParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
private ExtensionsType parseExtensions(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
ExtensionsType extensions = new ExtensionsType();
|
||||
Element extElement = StaxParserUtil.getDOMElement(xmlEventReader);
|
||||
extensions.setElement(extElement);
|
||||
return extensions;
|
||||
case ENTITIES_DESCRIPTOR:
|
||||
target.addEntityDescriptor(parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,50 +16,20 @@
|
|||
*/
|
||||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.assertion.AttributeType;
|
||||
import org.keycloak.dom.saml.v2.metadata.AttributeAuthorityDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.AttributeConsumingServiceType;
|
||||
import org.keycloak.dom.saml.v2.metadata.ContactType;
|
||||
import org.keycloak.dom.saml.v2.metadata.ContactTypeType;
|
||||
import org.keycloak.dom.saml.v2.metadata.EndpointType;
|
||||
import org.keycloak.dom.saml.v2.metadata.AuthnAuthorityDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.ExtensionsType;
|
||||
import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.IndexedEndpointType;
|
||||
import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.KeyTypes;
|
||||
import org.keycloak.dom.saml.v2.metadata.LocalizedNameType;
|
||||
import org.keycloak.dom.saml.v2.metadata.LocalizedURIType;
|
||||
import org.keycloak.dom.saml.v2.metadata.OrganizationType;
|
||||
import org.keycloak.dom.saml.v2.metadata.PDPDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.RoleDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
|
||||
import org.keycloak.dom.xmlsec.w3.xmlenc.EncryptionMethodType;
|
||||
import org.keycloak.saml.common.PicketLinkLogger;
|
||||
import org.keycloak.saml.common.PicketLinkLoggerFactory;
|
||||
import org.keycloak.saml.common.constants.GeneralConstants;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLConstants;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.parsers.AbstractParser;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
import org.keycloak.saml.common.util.StringUtil;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAttributeParser;
|
||||
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.Attribute;
|
||||
import javax.xml.stream.events.EndElement;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import org.keycloak.saml.common.parsers.StaxParser;
|
||||
|
||||
import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.ENTITY_DESCRIPTOR;
|
||||
|
||||
/**
|
||||
* Parse the SAML Metadata element "EntityDescriptor"
|
||||
|
@ -67,621 +37,107 @@ import org.keycloak.saml.common.parsers.StaxParser;
|
|||
* @author Anil.Saldhana@redhat.com
|
||||
* @since Dec 14, 2010
|
||||
*/
|
||||
public class SAMLEntityDescriptorParser extends AbstractParser {
|
||||
public class SAMLEntityDescriptorParser extends AbstractStaxSamlMetadataParser<EntityDescriptorType> {
|
||||
|
||||
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
|
||||
private static final SAMLEntityDescriptorParser INSTANCE = new SAMLEntityDescriptorParser();
|
||||
|
||||
private static final String EDT = JBossSAMLConstants.ENTITY_DESCRIPTOR.get();
|
||||
|
||||
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
|
||||
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
StaxParserUtil.validate(startElement, EDT);
|
||||
|
||||
Attribute entityID = startElement.getAttributeByName(new QName(JBossSAMLConstants.ENTITY_ID.get()));
|
||||
String entityIDValue = StaxParserUtil.getAttributeValue(entityID);
|
||||
EntityDescriptorType entityDescriptorType = new EntityDescriptorType(entityIDValue);
|
||||
|
||||
Attribute validUntil = startElement.getAttributeByName(new QName(JBossSAMLConstants.VALID_UNTIL.get()));
|
||||
if (validUntil != null) {
|
||||
String validUntilValue = StaxParserUtil.getAttributeValue(validUntil);
|
||||
entityDescriptorType.setValidUntil(XMLTimeUtil.parse(validUntilValue));
|
||||
private SAMLEntityDescriptorParser() {
|
||||
super(ENTITY_DESCRIPTOR);
|
||||
}
|
||||
|
||||
Attribute id = startElement.getAttributeByName(new QName(JBossSAMLConstants.ID.get()));
|
||||
if (id != null) {
|
||||
entityDescriptorType.setID(StaxParserUtil.getAttributeValue(id));
|
||||
public static SAMLEntityDescriptorParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
Attribute cacheDuration = startElement.getAttributeByName(new QName(JBossSAMLConstants.CACHE_DURATION.get()));
|
||||
if (cacheDuration != null) {
|
||||
entityDescriptorType.setCacheDuration(XMLTimeUtil.parseAsDuration(StaxParserUtil.getAttributeValue(cacheDuration)));
|
||||
@Override
|
||||
protected EntityDescriptorType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
String entityID = StaxParserUtil.getRequiredAttributeValue(element, SAMLMetadataQNames.ATTR_ENTITY_ID);
|
||||
EntityDescriptorType descriptor = new EntityDescriptorType(entityID);
|
||||
|
||||
descriptor.setValidUntil(StaxParserUtil.getXmlTimeAttributeValue(element, SAMLMetadataQNames.ATTR_VALID_UNTIL));
|
||||
descriptor.setCacheDuration(StaxParserUtil.getXmlDurationAttributeValue(element, SAMLMetadataQNames.ATTR_CACHE_DURATION));
|
||||
descriptor.setID(StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_ID));
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// Get the Child Elements
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
StaxParserUtil.validate((EndElement) xmlEvent, EDT);
|
||||
StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, EntityDescriptorType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case SIGNATURE:
|
||||
target.setSignature(StaxParserUtil.getDOMElement(xmlEventReader));
|
||||
break;
|
||||
}
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if (JBossSAMLConstants.IDP_SSO_DESCRIPTOR.get().equals(localPart)) {
|
||||
IDPSSODescriptorType idpSSO = parseIDPSSODescriptor(xmlEventReader);
|
||||
case EXTENSIONS:
|
||||
target.setExtensions(SAMLExtensionsParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case IDP_SSO_DESCRIPTOR:
|
||||
{
|
||||
IDPSSODescriptorType idpSSO = SAMLIDPSSODescriptorParser.getInstance().parse(xmlEventReader);
|
||||
|
||||
EntityDescriptorType.EDTDescriptorChoiceType edtDescChoice = new EntityDescriptorType.EDTDescriptorChoiceType(idpSSO);
|
||||
EntityDescriptorType.EDTChoiceType edtChoice = EntityDescriptorType.EDTChoiceType.oneValue(edtDescChoice);
|
||||
entityDescriptorType.addChoiceType(edtChoice);
|
||||
} else if (JBossSAMLConstants.SP_SSO_DESCRIPTOR.get().equals(localPart)) {
|
||||
SPSSODescriptorType spSSO = parseSPSSODescriptor(xmlEventReader);
|
||||
target.addChoiceType(edtChoice);
|
||||
}
|
||||
break;
|
||||
|
||||
case SP_SSO_DESCRIPTOR:
|
||||
{
|
||||
SPSSODescriptorType spSSO = SAMLSPSSODescriptorParser.getInstance().parse(xmlEventReader);
|
||||
|
||||
EntityDescriptorType.EDTDescriptorChoiceType edtDescChoice = new EntityDescriptorType.EDTDescriptorChoiceType(spSSO);
|
||||
EntityDescriptorType.EDTChoiceType edtChoice = EntityDescriptorType.EDTChoiceType.oneValue(edtDescChoice);
|
||||
entityDescriptorType.addChoiceType(edtChoice);
|
||||
} else if (JBossSAMLConstants.ATTRIBUTE_AUTHORITY_DESCRIPTOR.get().equals(localPart)) {
|
||||
AttributeAuthorityDescriptorType attrAuthority = parseAttributeAuthorityDescriptor(xmlEventReader);
|
||||
target.addChoiceType(edtChoice);
|
||||
}
|
||||
break;
|
||||
|
||||
case ATTRIBUTE_AUTHORITY_DESCRIPTOR:
|
||||
{
|
||||
AttributeAuthorityDescriptorType attrAuthority = SAMLAttributeAuthorityDescriptorParser.getInstance().parse(xmlEventReader);
|
||||
|
||||
EntityDescriptorType.EDTDescriptorChoiceType edtDescChoice = new EntityDescriptorType.EDTDescriptorChoiceType(attrAuthority);
|
||||
EntityDescriptorType.EDTChoiceType edtChoice = EntityDescriptorType.EDTChoiceType.oneValue(edtDescChoice);
|
||||
entityDescriptorType.addChoiceType(edtChoice);
|
||||
} else if (JBossSAMLConstants.AUTHN_AUTHORITY_DESCRIPTOR.get().equals(localPart)) {
|
||||
throw logger.unsupportedType("AuthnAuthorityDescriptor");
|
||||
} else if (JBossSAMLConstants.AFFILIATION_DESCRIPTOR.get().equals(localPart)) {
|
||||
throw logger.unsupportedType(" AffiliationDescriptor");
|
||||
} else if (JBossSAMLConstants.PDP_DESCRIPTOR.get().equals(localPart)) {
|
||||
throw logger.unsupportedType(" PDPDescriptor");
|
||||
} else if (localPart.equals(JBossSAMLConstants.SIGNATURE.get())) {
|
||||
entityDescriptorType.setSignature(StaxParserUtil.getDOMElement(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.ORGANIZATION.get().equals(localPart)) {
|
||||
OrganizationType organization = parseOrganization(xmlEventReader);
|
||||
target.addChoiceType(edtChoice);
|
||||
}
|
||||
break;
|
||||
|
||||
entityDescriptorType.setOrganization(organization);
|
||||
} else if (JBossSAMLConstants.CONTACT_PERSON.get().equals(localPart)) {
|
||||
entityDescriptorType.addContactPerson(parseContactPerson(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.ADDITIONAL_METADATA_LOCATION.get().equals(localPart)) {
|
||||
throw logger.unsupportedType("AdditionalMetadataLocation");
|
||||
} else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
|
||||
entityDescriptorType.setExtensions(SAMLExtensionsParser.getInstance().parse(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.ROLE_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
|
||||
RoleDescriptorType roleDescriptor = parseRoleDescriptor(xmlEventReader);
|
||||
case AUTHN_AUTHORITY_DESCRIPTOR:
|
||||
{
|
||||
AuthnAuthorityDescriptorType authAuthority = SAMLAuthnAuthorityDescriptorParser.getInstance().parse(xmlEventReader);
|
||||
|
||||
EntityDescriptorType.EDTDescriptorChoiceType edtDescChoice = new EntityDescriptorType.EDTDescriptorChoiceType(roleDescriptor);
|
||||
EntityDescriptorType.EDTDescriptorChoiceType edtDescChoice = new EntityDescriptorType.EDTDescriptorChoiceType(authAuthority);
|
||||
EntityDescriptorType.EDTChoiceType edtChoice = EntityDescriptorType.EDTChoiceType.oneValue(edtDescChoice);
|
||||
|
||||
entityDescriptorType.addChoiceType(edtChoice);
|
||||
} else
|
||||
throw logger.parserUnknownStartElement(localPart, startElement.getLocation());
|
||||
target.addChoiceType(edtChoice);
|
||||
}
|
||||
return entityDescriptorType;
|
||||
}
|
||||
|
||||
|
||||
private SPSSODescriptorType parseSPSSODescriptor(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
StaxParserUtil.validate(startElement, JBossSAMLConstants.SP_SSO_DESCRIPTOR.get());
|
||||
|
||||
List<String> protocolEnum = parseProtocolEnumeration(startElement);
|
||||
SPSSODescriptorType spSSODescriptor = new SPSSODescriptorType(protocolEnum);
|
||||
|
||||
Attribute wantAssertionsSigned = startElement.getAttributeByName(new QName(JBossSAMLConstants.WANT_ASSERTIONS_SIGNED
|
||||
.get()));
|
||||
if (wantAssertionsSigned != null) {
|
||||
spSSODescriptor
|
||||
.setWantAssertionsSigned(Boolean.parseBoolean(StaxParserUtil.getAttributeValue(wantAssertionsSigned)));
|
||||
}
|
||||
Attribute wantAuthnSigned = startElement.getAttributeByName(new QName(JBossSAMLConstants.AUTHN_REQUESTS_SIGNED.get()));
|
||||
if (wantAuthnSigned != null) {
|
||||
spSSODescriptor.setAuthnRequestsSigned(Boolean.parseBoolean(StaxParserUtil.getAttributeValue(wantAuthnSigned)));
|
||||
}
|
||||
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(end, JBossSAMLConstants.SP_SSO_DESCRIPTOR.get());
|
||||
break;
|
||||
|
||||
case PDP_DESCRIPTOR:
|
||||
{
|
||||
PDPDescriptorType pdpDescriptor = SAMLPDPDescriptorParser.getInstance().parse(xmlEventReader);
|
||||
|
||||
EntityDescriptorType.EDTDescriptorChoiceType edtDescChoice = new EntityDescriptorType.EDTDescriptorChoiceType(pdpDescriptor);
|
||||
EntityDescriptorType.EDTChoiceType edtChoice = EntityDescriptorType.EDTChoiceType.oneValue(edtDescChoice);
|
||||
target.addChoiceType(edtChoice);
|
||||
}
|
||||
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if (JBossSAMLConstants.ARTIFACT_RESOLUTION_SERVICE.get().equals(localPart)) {
|
||||
IndexedEndpointType endpoint = parseArtifactResolutionService(xmlEventReader, startElement);
|
||||
spSSODescriptor.addArtifactResolutionService(endpoint);
|
||||
} else if (JBossSAMLConstants.ASSERTION_CONSUMER_SERVICE.get().equals(localPart)) {
|
||||
IndexedEndpointType endpoint = parseAssertionConsumerService(xmlEventReader, startElement);
|
||||
spSSODescriptor.addAssertionConsumerService(endpoint);
|
||||
} else if (JBossSAMLConstants.ATTRIBUTE_CONSUMING_SERVICE.get().equals(localPart)) {
|
||||
AttributeConsumingServiceType attributeConsumer = parseAttributeConsumingService(xmlEventReader, startElement);
|
||||
spSSODescriptor.addAttributeConsumerService(attributeConsumer);
|
||||
} else if (JBossSAMLConstants.SINGLE_LOGOUT_SERVICE.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
EndpointType endpoint = getEndpointType(startElement);
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.SINGLE_LOGOUT_SERVICE.get());
|
||||
|
||||
spSSODescriptor.addSingleLogoutService(endpoint);
|
||||
} else if (JBossSAMLConstants.MANAGE_NAMEID_SERVICE.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
EndpointType endpoint = getEndpointType(startElement);
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.MANAGE_NAMEID_SERVICE.get());
|
||||
|
||||
spSSODescriptor.addManageNameIDService(endpoint);
|
||||
} else if (JBossSAMLConstants.NAMEID_FORMAT.get().equalsIgnoreCase(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
spSSODescriptor.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.KEY_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
|
||||
spSSODescriptor.addKeyDescriptor(parseKeyDescriptor(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
|
||||
spSSODescriptor.setExtensions(parseExtensions(xmlEventReader));
|
||||
} else
|
||||
throw logger.parserUnknownTag(localPart, startElement.getLocation());
|
||||
}
|
||||
return spSSODescriptor;
|
||||
}
|
||||
|
||||
private IDPSSODescriptorType parseIDPSSODescriptor(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
StaxParserUtil.validate(startElement, JBossSAMLConstants.IDP_SSO_DESCRIPTOR.get());
|
||||
|
||||
List<String> protocolEnum = parseProtocolEnumeration(startElement);
|
||||
IDPSSODescriptorType idpSSODescriptor = new IDPSSODescriptorType(protocolEnum);
|
||||
|
||||
Attribute wantAuthnSigned = startElement.getAttributeByName(new QName(JBossSAMLConstants.WANT_AUTHN_REQUESTS_SIGNED
|
||||
.get()));
|
||||
if (wantAuthnSigned != null) {
|
||||
idpSSODescriptor
|
||||
.setWantAuthnRequestsSigned(Boolean.parseBoolean(StaxParserUtil.getAttributeValue(wantAuthnSigned)));
|
||||
}
|
||||
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(end, JBossSAMLConstants.IDP_SSO_DESCRIPTOR.get());
|
||||
break;
|
||||
}
|
||||
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if (JBossSAMLConstants.ARTIFACT_RESOLUTION_SERVICE.get().equals(localPart)) {
|
||||
IndexedEndpointType endpoint = parseArtifactResolutionService(xmlEventReader, startElement);
|
||||
idpSSODescriptor.addArtifactResolutionService(endpoint);
|
||||
} else if (JBossSAMLConstants.ASSERTION_ID_REQUEST_SERVICE.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
EndpointType endpoint = getEndpointType(startElement);
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.ASSERTION_ID_REQUEST_SERVICE.get());
|
||||
|
||||
idpSSODescriptor.addAssertionIDRequestService(endpoint);
|
||||
} else if (JBossSAMLConstants.SINGLE_LOGOUT_SERVICE.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
EndpointType endpoint = getEndpointType(startElement);
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.SINGLE_LOGOUT_SERVICE.get());
|
||||
|
||||
idpSSODescriptor.addSingleLogoutService(endpoint);
|
||||
} else if (JBossSAMLConstants.SINGLE_SIGNON_SERVICE.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
EndpointType endpoint = getEndpointType(startElement);
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.SINGLE_SIGNON_SERVICE.get());
|
||||
|
||||
idpSSODescriptor.addSingleSignOnService(endpoint);
|
||||
} else if (JBossSAMLConstants.MANAGE_NAMEID_SERVICE.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
EndpointType endpoint = getEndpointType(startElement);
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.MANAGE_NAMEID_SERVICE.get());
|
||||
|
||||
idpSSODescriptor.addManageNameIDService(endpoint);
|
||||
} else if (JBossSAMLConstants.NAMEID_MAPPING_SERVICE.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
EndpointType endpoint = getEndpointType(startElement);
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.NAMEID_MAPPING_SERVICE.get());
|
||||
|
||||
idpSSODescriptor.addNameIDMappingService(endpoint);
|
||||
} else if (JBossSAMLConstants.NAMEID_FORMAT.get().equalsIgnoreCase(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
idpSSODescriptor.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.ATTRIBUTE.get().equalsIgnoreCase(localPart)) {
|
||||
AttributeType attribute = SAMLAttributeParser.getInstance().parse(xmlEventReader);
|
||||
idpSSODescriptor.addAttribute(attribute);
|
||||
} else if (JBossSAMLConstants.KEY_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
|
||||
idpSSODescriptor.addKeyDescriptor(parseKeyDescriptor(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
|
||||
idpSSODescriptor.setExtensions(parseExtensions(xmlEventReader));
|
||||
} else
|
||||
throw logger.parserUnknownTag(localPart, startElement.getLocation());
|
||||
}
|
||||
return idpSSODescriptor;
|
||||
}
|
||||
|
||||
private EndpointType getEndpointType(StartElement startElement) {
|
||||
Attribute bindingAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.BINDING.get()));
|
||||
String binding = StaxParserUtil.getAttributeValue(bindingAttr);
|
||||
|
||||
Attribute locationAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.LOCATION.get()));
|
||||
String location = StaxParserUtil.getAttributeValue(locationAttr);
|
||||
|
||||
EndpointType endpoint = new IndexedEndpointType(URI.create(binding), URI.create(location));
|
||||
Attribute responseLocation = startElement.getAttributeByName(new QName(JBossSAMLConstants.RESPONSE_LOCATION.get()));
|
||||
if (responseLocation != null) {
|
||||
endpoint.setResponseLocation(URI.create(StaxParserUtil.getAttributeValue(responseLocation)));
|
||||
}
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
private AttributeAuthorityDescriptorType parseAttributeAuthorityDescriptor(XMLEventReader xmlEventReader)
|
||||
throws ParsingException {
|
||||
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
StaxParserUtil.validate(startElement, JBossSAMLConstants.ATTRIBUTE_AUTHORITY_DESCRIPTOR.get());
|
||||
List<String> protocolEnum = parseProtocolEnumeration(startElement);
|
||||
AttributeAuthorityDescriptorType attributeAuthority = new AttributeAuthorityDescriptorType(protocolEnum);
|
||||
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(end, JBossSAMLConstants.ATTRIBUTE_AUTHORITY_DESCRIPTOR.get());
|
||||
case ROLE_DESCRIPTOR:
|
||||
case AFFILIATION_DESCRIPTOR:
|
||||
case ADDITIONAL_METADATA_LOCATION:
|
||||
StaxParserUtil.bypassElementBlock(xmlEventReader);
|
||||
break;
|
||||
}
|
||||
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if (JBossSAMLConstants.ATTRIBUTE_SERVICE.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
Attribute bindingAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.BINDING.get()));
|
||||
String binding = StaxParserUtil.getAttributeValue(bindingAttr);
|
||||
|
||||
Attribute locationAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.LOCATION.get()));
|
||||
String location = StaxParserUtil.getAttributeValue(locationAttr);
|
||||
|
||||
IndexedEndpointType endpoint = new IndexedEndpointType(URI.create(binding), URI.create(location));
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.ATTRIBUTE_SERVICE.get());
|
||||
|
||||
attributeAuthority.addAttributeService(endpoint);
|
||||
} else if (JBossSAMLConstants.ASSERTION_ID_REQUEST_SERVICE.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
EndpointType endpoint = getEndpointType(startElement);
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.ASSERTION_ID_REQUEST_SERVICE.get());
|
||||
|
||||
attributeAuthority.addAssertionIDRequestService(endpoint);
|
||||
} else if (JBossSAMLConstants.ATTRIBUTE_PROFILE.get().equalsIgnoreCase(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
attributeAuthority.addAttributeProfile(StaxParserUtil.getElementText(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.ATTRIBUTE.get().equalsIgnoreCase(localPart)) {
|
||||
attributeAuthority.addAttribute(SAMLAttributeParser.getInstance().parse(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.KEY_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
|
||||
attributeAuthority.addKeyDescriptor(parseKeyDescriptor(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.NAMEID_FORMAT.get().equalsIgnoreCase(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
attributeAuthority.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
|
||||
attributeAuthority.setExtensions(parseExtensions(xmlEventReader));
|
||||
} else
|
||||
throw logger.parserUnknownTag(localPart, startElement.getLocation());
|
||||
|
||||
}
|
||||
return attributeAuthority;
|
||||
}
|
||||
|
||||
private OrganizationType parseOrganization(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
StaxParserUtil.validate(startElement, JBossSAMLConstants.ORGANIZATION.get());
|
||||
|
||||
OrganizationType org = new OrganizationType();
|
||||
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(end, JBossSAMLConstants.ORGANIZATION.get());
|
||||
case ORGANIZATION:
|
||||
target.setOrganization(SAMLOrganizationParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
}
|
||||
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if (JBossSAMLConstants.ORGANIZATION_NAME.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
LocalizedNameType localName = getLocalizedName(xmlEventReader, startElement);
|
||||
org.addOrganizationName(localName);
|
||||
} else if (JBossSAMLConstants.ORGANIZATION_DISPLAY_NAME.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
LocalizedNameType localName = getLocalizedName(xmlEventReader, startElement);
|
||||
org.addOrganizationDisplayName(localName);
|
||||
} else if (JBossSAMLConstants.ORGANIZATION_URL.get().equals(localPart) ||
|
||||
(JBossSAMLConstants.ORGANIZATION_URL_ALT.get().equals(localPart))) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
Attribute lang = startElement.getAttributeByName(new QName(JBossSAMLURIConstants.XML.get(), "lang"));
|
||||
String langVal = StaxParserUtil.getAttributeValue(lang);
|
||||
LocalizedURIType localName = new LocalizedURIType(langVal);
|
||||
localName.setValue(URI.create(StaxParserUtil.getElementText(xmlEventReader)));
|
||||
org.addOrganizationURL(localName);
|
||||
} else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
|
||||
org.setExtensions(parseExtensions(xmlEventReader));
|
||||
} else
|
||||
throw logger.parserUnknownTag(localPart, startElement.getLocation());
|
||||
}
|
||||
return org;
|
||||
}
|
||||
|
||||
private KeyDescriptorType parseKeyDescriptor(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
StaxParserUtil.validate(startElement, JBossSAMLConstants.KEY_DESCRIPTOR.get());
|
||||
|
||||
KeyDescriptorType keyDescriptor = new KeyDescriptorType();
|
||||
|
||||
String use = StaxParserUtil.getAttributeValue(startElement, "use");
|
||||
|
||||
if (use != null && !use.isEmpty()) {
|
||||
keyDescriptor.setUse(KeyTypes.fromValue(use));
|
||||
}
|
||||
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(end, JBossSAMLConstants.KEY_DESCRIPTOR.get());
|
||||
case CONTACT_PERSON:
|
||||
target.addContactPerson(SAMLContactPersonParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
}
|
||||
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if (JBossSAMLConstants.KEY_INFO.get().equals(localPart)) {
|
||||
Element key = StaxParserUtil.getDOMElement(xmlEventReader);
|
||||
keyDescriptor.setKeyInfo(key);
|
||||
} else if (JBossSAMLConstants.ENCRYPTION_METHOD.get().equals(localPart)) {
|
||||
keyDescriptor.addEncryptionMethod(parseEncryptionMethod(xmlEventReader));
|
||||
} else
|
||||
throw logger.parserUnknownTag(localPart, startElement.getLocation());
|
||||
}
|
||||
|
||||
return keyDescriptor;
|
||||
}
|
||||
|
||||
private EncryptionMethodType parseEncryptionMethod(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
StaxParserUtil.validate(startElement, JBossSAMLConstants.ENCRYPTION_METHOD.get());
|
||||
Attribute algorithm = startElement.getAttributeByName(new QName("Algorithm"));
|
||||
EncryptionMethodType encryptionMethodType = new EncryptionMethodType(algorithm.getValue());
|
||||
|
||||
BigInteger keySize = null;
|
||||
byte[] OAEPparams = null;
|
||||
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(end, JBossSAMLConstants.ENCRYPTION_METHOD.get());
|
||||
break;
|
||||
}
|
||||
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if ("KeySize".equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
keySize = BigInteger.valueOf(Long.valueOf(StaxParserUtil.getElementText(xmlEventReader)));
|
||||
} else if ("OAEPparams".equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
OAEPparams = StaxParserUtil.getElementText(xmlEventReader).getBytes(GeneralConstants.SAML_CHARSET);
|
||||
} else {
|
||||
throw logger.parserUnknownTag(localPart, startElement.getLocation());
|
||||
}
|
||||
}
|
||||
|
||||
EncryptionMethodType.EncryptionMethod encryptionMethod = new EncryptionMethodType.EncryptionMethod(keySize, OAEPparams);
|
||||
|
||||
encryptionMethodType.setEncryptionMethod(encryptionMethod);
|
||||
|
||||
return encryptionMethodType;
|
||||
}
|
||||
|
||||
private ContactType parseContactPerson(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
StaxParserUtil.validate(startElement, JBossSAMLConstants.CONTACT_PERSON.get());
|
||||
|
||||
Attribute attr = startElement.getAttributeByName(new QName(JBossSAMLConstants.CONTACT_TYPE.get()));
|
||||
if (attr == null)
|
||||
throw logger.parserRequiredAttribute("contactType");
|
||||
ContactType contactType = new ContactType(ContactTypeType.fromValue(StaxParserUtil.getAttributeValue(attr)));
|
||||
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(end, JBossSAMLConstants.CONTACT_PERSON.get());
|
||||
break;
|
||||
}
|
||||
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if (JBossSAMLConstants.COMPANY.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
contactType.setCompany(StaxParserUtil.getElementText(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.GIVEN_NAME.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
contactType.setGivenName(StaxParserUtil.getElementText(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.SURNAME.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
contactType.setSurName(StaxParserUtil.getElementText(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.EMAIL_ADDRESS.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
contactType.addEmailAddress(StaxParserUtil.getElementText(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.TELEPHONE_NUMBER.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
contactType.addTelephone(StaxParserUtil.getElementText(xmlEventReader));
|
||||
} else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
|
||||
contactType.setExtensions(parseExtensions(xmlEventReader));
|
||||
} else
|
||||
throw logger.parserUnknownTag(localPart, startElement.getLocation());
|
||||
}
|
||||
return contactType;
|
||||
}
|
||||
|
||||
private LocalizedNameType getLocalizedName(XMLEventReader xmlEventReader, StartElement startElement)
|
||||
throws ParsingException {
|
||||
Attribute lang = startElement.getAttributeByName(new QName(JBossSAMLURIConstants.XML.get(), "lang"));
|
||||
String langVal = StaxParserUtil.getAttributeValue(lang);
|
||||
LocalizedNameType localName = new LocalizedNameType(langVal);
|
||||
localName.setValue(StaxParserUtil.getElementText(xmlEventReader));
|
||||
return localName;
|
||||
}
|
||||
|
||||
private IndexedEndpointType parseAssertionConsumerService(XMLEventReader xmlEventReader, StartElement startElement)
|
||||
throws ParsingException {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
IndexedEndpointType endpoint = parseIndexedEndpoint(xmlEventReader, startElement);
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.ASSERTION_CONSUMER_SERVICE.get());
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
private IndexedEndpointType parseArtifactResolutionService(XMLEventReader xmlEventReader, StartElement startElement)
|
||||
throws ParsingException {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
IndexedEndpointType endpoint = parseIndexedEndpoint(xmlEventReader, startElement);
|
||||
|
||||
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(endElement, JBossSAMLConstants.ARTIFACT_RESOLUTION_SERVICE.get());
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
private IndexedEndpointType parseIndexedEndpoint(XMLEventReader xmlEventReader, StartElement startElement) {
|
||||
Attribute bindingAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.BINDING.get()));
|
||||
String binding = StaxParserUtil.getAttributeValue(bindingAttr);
|
||||
|
||||
Attribute locationAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.LOCATION.get()));
|
||||
String location = StaxParserUtil.getAttributeValue(locationAttr);
|
||||
|
||||
IndexedEndpointType endpoint = new IndexedEndpointType(URI.create(binding), URI.create(location));
|
||||
Attribute isDefault = startElement.getAttributeByName(new QName(JBossSAMLConstants.ISDEFAULT.get()));
|
||||
if (isDefault != null) {
|
||||
endpoint.setIsDefault(Boolean.parseBoolean(StaxParserUtil.getAttributeValue(isDefault)));
|
||||
}
|
||||
Attribute index = startElement.getAttributeByName(new QName(JBossSAMLConstants.INDEX.get()));
|
||||
if (index != null) {
|
||||
endpoint.setIndex(Integer.parseInt(StaxParserUtil.getAttributeValue(index)));
|
||||
}
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
private AttributeConsumingServiceType parseAttributeConsumingService(XMLEventReader xmlEventReader,
|
||||
StartElement startElement) throws ParsingException {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
|
||||
Attribute indexAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.INDEX.get()));
|
||||
if (indexAttr == null)
|
||||
throw logger.parserRequiredAttribute("index");
|
||||
|
||||
AttributeConsumingServiceType attributeConsumer = new AttributeConsumingServiceType(Integer.parseInt(StaxParserUtil
|
||||
.getAttributeValue(indexAttr)));
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(end, JBossSAMLConstants.ATTRIBUTE_CONSUMING_SERVICE.get());
|
||||
break;
|
||||
}
|
||||
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if (JBossSAMLConstants.SERVICE_NAME.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
LocalizedNameType localName = getLocalizedName(xmlEventReader, startElement);
|
||||
attributeConsumer.addServiceName(localName);
|
||||
} else if (JBossSAMLConstants.SERVICE_DESCRIPTION.get().equals(localPart)) {
|
||||
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
LocalizedNameType localName = getLocalizedName(xmlEventReader, startElement);
|
||||
attributeConsumer.addServiceDescription(localName);
|
||||
} else if (JBossSAMLConstants.REQUESTED_ATTRIBUTE.get().equals(localPart)) {
|
||||
attributeConsumer.addRequestedAttribute(SAMLRequestedAttributeParser.getInstance().parse(xmlEventReader));
|
||||
} else
|
||||
throw logger.parserUnknownTag(localPart, startElement.getLocation());
|
||||
}
|
||||
|
||||
return attributeConsumer;
|
||||
}
|
||||
|
||||
private ExtensionsType parseExtensions(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
ExtensionsType extensions = new ExtensionsType();
|
||||
Element extElement = StaxParserUtil.getDOMElement(xmlEventReader);
|
||||
extensions.setElement(extElement);
|
||||
return extensions;
|
||||
}
|
||||
|
||||
private RoleDescriptorType parseRoleDescriptor(XMLEventReader xmlEventReader) throws ParsingException {
|
||||
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
|
||||
StaxParserUtil.validate(startElement, JBossSAMLConstants.ROLE_DESCRIPTOR.get());
|
||||
List<String> protocolEnum = parseProtocolEnumeration(startElement);
|
||||
RoleDescriptorType roleDescriptorType = new RoleDescriptorType(protocolEnum) {};
|
||||
|
||||
while (xmlEventReader.hasNext()) {
|
||||
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
|
||||
if (xmlEvent instanceof EndElement) {
|
||||
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
|
||||
StaxParserUtil.validate(end, JBossSAMLConstants.ROLE_DESCRIPTOR.get());
|
||||
break;
|
||||
}
|
||||
|
||||
startElement = (StartElement) xmlEvent;
|
||||
String localPart = startElement.getName().getLocalPart();
|
||||
|
||||
if (JBossSAMLConstants.KEY_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
|
||||
KeyDescriptorType keyDescriptor = parseKeyDescriptor(xmlEventReader);
|
||||
roleDescriptorType.addKeyDescriptor(keyDescriptor);
|
||||
} else {
|
||||
StaxParserUtil.bypassElementBlock(xmlEventReader, localPart);
|
||||
}
|
||||
}
|
||||
|
||||
return roleDescriptorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a space delimited list of strings
|
||||
*
|
||||
* @param startElement
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static List<String> parseProtocolEnumeration(StartElement startElement) {
|
||||
List<String> protocolEnum = new ArrayList<>();
|
||||
Attribute proto = startElement.getAttributeByName(JBossSAMLConstants.PROTOCOL_SUPPORT_ENUMERATION.getAsQName());
|
||||
String val = StaxParserUtil.getAttributeValue(proto);
|
||||
if (StringUtil.isNotNull(val)) {
|
||||
StringTokenizer st = new StringTokenizer(val);
|
||||
while (st.hasMoreTokens()) {
|
||||
protocolEnum.add(st.nextToken());
|
||||
}
|
||||
default:
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
|
||||
}
|
||||
return protocolEnum;
|
||||
}
|
||||
}
|
|
@ -16,24 +16,24 @@
|
|||
*/
|
||||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import org.keycloak.dom.saml.v2.metadata.ExtensionsType;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLConstants;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
|
||||
/**
|
||||
* Parses <samlp:Extensions> SAML2 element into series of DOM nodes.
|
||||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class SAMLExtensionsParser extends AbstractStaxSamlParser<ExtensionsType> {
|
||||
public class SAMLExtensionsParser extends AbstractStaxSamlMetadataParser<ExtensionsType> {
|
||||
|
||||
private static final SAMLExtensionsParser INSTANCE = new SAMLExtensionsParser();
|
||||
|
||||
private SAMLExtensionsParser() {
|
||||
super(JBossSAMLConstants.EXTENSIONS__METADATA);
|
||||
super(SAMLMetadataQNames.EXTENSIONS);
|
||||
}
|
||||
|
||||
public static SAMLExtensionsParser getInstance() {
|
||||
|
@ -46,7 +46,7 @@ public class SAMLExtensionsParser extends AbstractStaxSamlParser<ExtensionsType>
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, ExtensionsType target, JBossSAMLConstants element, StartElement elementDetail) throws ParsingException {
|
||||
target.setElement(StaxParserUtil.getDOMElement(xmlEventReader));
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, ExtensionsType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
target.addExtension(StaxParserUtil.getDOMElement(xmlEventReader));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.IDP_SSO_DESCRIPTOR;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLIDPSSODescriptorParser extends SAMLSSODescriptorTypeParser<IDPSSODescriptorType> {
|
||||
|
||||
private static final SAMLIDPSSODescriptorParser INSTANCE = new SAMLIDPSSODescriptorParser();
|
||||
|
||||
private SAMLIDPSSODescriptorParser() {
|
||||
super(IDP_SSO_DESCRIPTOR);
|
||||
}
|
||||
|
||||
public static SAMLIDPSSODescriptorParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IDPSSODescriptorType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
List<String> protocolEnum = StaxParserUtil.getRequiredStringListAttributeValue(element, SAMLMetadataQNames.ATTR_PROTOCOL_SUPPORT_ENUMERATION);
|
||||
IDPSSODescriptorType descriptor = new IDPSSODescriptorType(protocolEnum);
|
||||
|
||||
// Role descriptor optional arguments
|
||||
parseOptionalArguments(element, descriptor);
|
||||
|
||||
// IDPSSODecsriptor optional attributes
|
||||
Boolean wantAuthnRequestsSigned = StaxParserUtil.getBooleanAttributeValue(element, SAMLMetadataQNames.ATTR_WANT_AUTHN_REQUESTS_SIGNED);
|
||||
if (wantAuthnRequestsSigned != null) {
|
||||
descriptor.setWantAuthnRequestsSigned(wantAuthnRequestsSigned);
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, IDPSSODescriptorType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case SINGLE_SIGNON_SERVICE:
|
||||
target.addSingleSignOnService(SAMLSingleSignOnServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case NAMEID_MAPPING_SERVICE:
|
||||
target.addNameIDMappingService(SAMLNameIDMappingServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ASSERTION_ID_REQUEST_SERVICE:
|
||||
target.addAssertionIDRequestService(SAMLAssertinIDRequestServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ATTRIBUTE_PROFILE:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.addAttributeProfile(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ATTRIBUTE:
|
||||
target.addAttribute(SAMLAttributeParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
super.processSubElement(xmlEventReader, target, element, elementDetail);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.IndexedEndpointType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public abstract class SAMLIndexedEndpointTypeParser extends AbstractStaxSamlMetadataParser<IndexedEndpointType> {
|
||||
|
||||
public SAMLIndexedEndpointTypeParser(SAMLMetadataQNames expectedStartElement) {
|
||||
super(expectedStartElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IndexedEndpointType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
String binding = StaxParserUtil.getRequiredAttributeValue(element, SAMLMetadataQNames.ATTR_BINDING);
|
||||
String location = StaxParserUtil.getRequiredAttributeValue(element, SAMLMetadataQNames.ATTR_LOCATION);
|
||||
|
||||
IndexedEndpointType endpoint = new IndexedEndpointType(URI.create(binding), URI.create(location));
|
||||
|
||||
Boolean isDefault = StaxParserUtil.getBooleanAttributeValue(element, SAMLMetadataQNames.ATTR_IS_DEFAULT);
|
||||
if (isDefault != null) {
|
||||
endpoint.setIsDefault(isDefault);
|
||||
}
|
||||
|
||||
Integer index = StaxParserUtil.getIntegerAttributeValue(element, SAMLMetadataQNames.ATTR_INDEX);
|
||||
if (index != null)
|
||||
endpoint.setIndex(index);
|
||||
|
||||
// EndpointType attributes
|
||||
String responseLocation = StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_RESPONSE_LOCATION);
|
||||
|
||||
if (responseLocation != null) {
|
||||
endpoint.setResponseLocation(URI.create(responseLocation));
|
||||
}
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, IndexedEndpointType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.KeyTypes;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
|
||||
import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.KEY_DESCRIPTOR;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLKeyDescriptorParser extends AbstractStaxSamlMetadataParser<KeyDescriptorType> {
|
||||
|
||||
private static final SAMLKeyDescriptorParser INSTANCE = new SAMLKeyDescriptorParser();
|
||||
|
||||
public SAMLKeyDescriptorParser() {
|
||||
super(KEY_DESCRIPTOR);
|
||||
}
|
||||
|
||||
public static SAMLKeyDescriptorParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KeyDescriptorType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
KeyDescriptorType keyDescriptor = new KeyDescriptorType();
|
||||
|
||||
String use = StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_USE);
|
||||
|
||||
if (use != null && !use.isEmpty()) {
|
||||
keyDescriptor.setUse(KeyTypes.fromValue(use));
|
||||
}
|
||||
|
||||
return keyDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, KeyDescriptorType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch(element) {
|
||||
case KEY_INFO:
|
||||
target.setKeyInfo(StaxParserUtil.getDOMElement(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ENCRYPTION_METHOD:
|
||||
target.addEncryptionMethod(SAMLEncryptionMethodParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLManageNameIDServiceParser extends SAMLEndpointTypeParser {
|
||||
|
||||
private static final SAMLManageNameIDServiceParser INSTANCE = new SAMLManageNameIDServiceParser();
|
||||
|
||||
public SAMLManageNameIDServiceParser() {
|
||||
super(SAMLMetadataQNames.MANAGE_NAMEID_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLManageNameIDServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionQNames;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.xmldsig.XmlDSigQNames;
|
||||
import org.keycloak.saml.processing.core.parsers.util.HasQName;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public enum SAMLMetadataQNames implements HasQName {
|
||||
ADDITIONAL_METADATA_LOCATION("AdditionalMetadataLocation"),
|
||||
AFFILIATE_MEMBER("AffiliateMember"),
|
||||
AFFILIATION_DESCRIPTOR("AffiliationDescriptor"),
|
||||
ARTIFACT_RESOLUTION_SERVICE("ArtifactResolutionService"),
|
||||
ASSERTION_CONSUMER_SERVICE("AssertionConsumerService"),
|
||||
ASSERTION_ID_REQUEST_SERVICE("AssertionIDRequestService"),
|
||||
ATTRIBUTE_AUTHORITY_DESCRIPTOR("AttributeAuthorityDescriptor"),
|
||||
ATTRIBUTE_CONSUMING_SERVICE("AttributeConsumingService"),
|
||||
ATTRIBUTE_PROFILE("AttributeProfile"),
|
||||
ATTRIBUTE_SERVICE("AttributeService"),
|
||||
ATTRIBUTE_VALUE("AttributeValue"),
|
||||
AUTHN_AUTHORITY_DESCRIPTOR("AuthnAuthorityDescriptor"),
|
||||
AUTHN_QUERY_SERVICE("AuthnQueryService"),
|
||||
AUTHZ_SERVICE("AuthzService"),
|
||||
COMPANY("Company"),
|
||||
CONTACT_PERSON("ContactPerson"),
|
||||
EMAIL_ADDRESS("EmailAddress"),
|
||||
ENCRYPTION_METHOD("EncryptionMethod"),
|
||||
ENTITIES_DESCRIPTOR("EntitiesDescriptor"),
|
||||
ENTITY_DESCRIPTOR("EntityDescriptor"),
|
||||
EXTENSIONS("Extensions"),
|
||||
GIVEN_NAME("GivenName"),
|
||||
IDP_SSO_DESCRIPTOR("IDPSSODescriptor"),
|
||||
KEY_DESCRIPTOR("KeyDescriptor"),
|
||||
MANAGE_NAMEID_SERVICE("ManageNameIDService"),
|
||||
NAMEID_FORMAT("NameIDFormat"),
|
||||
NAMEID_MAPPING_SERVICE("NameIDMappingService"),
|
||||
ORGANIZATION_DISPLAY_NAME("OrganizationDisplayName"),
|
||||
ORGANIZATION_NAME("OrganizationName"),
|
||||
ORGANIZATION("Organization"),
|
||||
ORGANIZATION_URL("OrganizationURL"),
|
||||
ORGANIZATION_URL_ALT("OrganizationUrl"), // non-standard: KEYCLOAK-4040,
|
||||
PDP_DESCRIPTOR("PDPDescriptor"),
|
||||
REQUESTED_ATTRIBUTE("RequestedAttribute"),
|
||||
ROLE_DESCRIPTOR("RoleDescriptor"),
|
||||
SERVICE_DESCRIPTION("ServiceDescription"),
|
||||
SERVICE_NAME("ServiceName"),
|
||||
SINGLE_LOGOUT_SERVICE("SingleLogoutService"),
|
||||
SINGLE_SIGNON_SERVICE("SingleSignOnService"),
|
||||
SP_SSO_DESCRIPTOR("SPSSODescriptor"),
|
||||
SURNAME("SurName"),
|
||||
TELEPHONE_NUMBER("TelephoneNumber"),
|
||||
|
||||
// Attribute names
|
||||
ATTR_ENTITY_ID(null, "entityID"),
|
||||
ATTR_ID(null, "ID"),
|
||||
ATTR_VALID_UNTIL(null, "validUntil"),
|
||||
ATTR_CACHE_DURATION(null, "cacheDuration"),
|
||||
ATTR_PROTOCOL_SUPPORT_ENUMERATION(null, "protocolSupportEnumeration"),
|
||||
ATTR_USE(null, "use"),
|
||||
ATTR_ALGORITHM(null, "Algorithm"),
|
||||
ATTR_LANG(JBossSAMLURIConstants.XML, "lang"),
|
||||
ATTR_CONTACT_TYPE(null, "contactType"),
|
||||
ATTR_AUTHN_REQUESTS_SIGNED(null, "AuthnRequestsSigned"),
|
||||
ATTR_WANT_ASSERTIONS_SIGNED(null, "WantAssertionsSigned"),
|
||||
ATTR_WANT_AUTHN_REQUESTS_SIGNED(null, "WantAuthnRequestsSigned"),
|
||||
ATTR_BINDING(null, "Binding"),
|
||||
ATTR_LOCATION(null, "Location"),
|
||||
ATTR_IS_DEFAULT(null, "isDefault"),
|
||||
ATTR_INDEX(null, "index"),
|
||||
ATTR_RESPONSE_LOCATION(null, "ResponseLocation"),
|
||||
ATTR_FRIENDLY_NAME(null, "FriendlyName"),
|
||||
ATTR_IS_REQUIRED(null, "isRequired"),
|
||||
ATTR_NAME(null, "Name"),
|
||||
ATTR_NAME_FORMAT(null, "NameFormat"),
|
||||
|
||||
// Elements from other namespaces that can be direct subelements of this namespace's elements
|
||||
SIGNATURE(XmlDSigQNames.SIGNATURE),
|
||||
KEY_INFO(XmlDSigQNames.KEY_INFO),
|
||||
KEY_SIZE(JBossSAMLURIConstants.XMLENC_NSURI, "KeySize"),
|
||||
OAEP_PARAMS(JBossSAMLURIConstants.XMLENC_NSURI, "OAEPparams"),
|
||||
ATTR_X500_ENCODING(JBossSAMLURIConstants.X500_NSURI, "Encoding"),
|
||||
ATTRIBUTE(SAMLAssertionQNames.ATTRIBUTE),
|
||||
|
||||
UNKNOWN_ELEMENT("");
|
||||
|
||||
private final QName qName;
|
||||
|
||||
private SAMLMetadataQNames(String localName) {
|
||||
this.qName = new QName(JBossSAMLURIConstants.METADATA_NSURI.get(), localName);
|
||||
}
|
||||
|
||||
private SAMLMetadataQNames(HasQName source) {
|
||||
this.qName = source.getQName();
|
||||
}
|
||||
|
||||
private SAMLMetadataQNames(JBossSAMLURIConstants nsUri, String localName) {
|
||||
this.qName = new QName(nsUri == null ? null : nsUri.get(), localName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QName getQName() {
|
||||
return qName;
|
||||
}
|
||||
|
||||
public QName getQName(String prefix) {
|
||||
return new QName(this.qName.getNamespaceURI(), this.qName.getLocalPart(), prefix);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLNameIDMappingServiceParser extends SAMLEndpointTypeParser {
|
||||
|
||||
private static final SAMLNameIDMappingServiceParser INSTANCE = new SAMLNameIDMappingServiceParser();
|
||||
|
||||
public SAMLNameIDMappingServiceParser() {
|
||||
super(SAMLMetadataQNames.NAMEID_MAPPING_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLNameIDMappingServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.LocalizedNameType;
|
||||
import org.keycloak.dom.saml.v2.metadata.LocalizedURIType;
|
||||
import org.keycloak.dom.saml.v2.metadata.OrganizationType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import java.net.URI;
|
||||
|
||||
import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.ATTR_LANG;
|
||||
import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.ORGANIZATION;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLOrganizationParser extends AbstractStaxSamlMetadataParser<OrganizationType> {
|
||||
|
||||
private static final SAMLOrganizationParser INSTANCE = new SAMLOrganizationParser();
|
||||
|
||||
public SAMLOrganizationParser() {
|
||||
super(ORGANIZATION);
|
||||
}
|
||||
|
||||
public static SAMLOrganizationParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
@Override
|
||||
protected OrganizationType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
return new OrganizationType();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, OrganizationType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case ORGANIZATION_NAME:
|
||||
LocalizedNameType orgName = new LocalizedNameType(StaxParserUtil.getAttributeValue(elementDetail, ATTR_LANG));
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
orgName.setValue(StaxParserUtil.getElementText(xmlEventReader));
|
||||
target.addOrganizationName(orgName);
|
||||
break;
|
||||
|
||||
case ORGANIZATION_DISPLAY_NAME:
|
||||
LocalizedNameType orgDispName = new LocalizedNameType(StaxParserUtil.getAttributeValue(elementDetail, ATTR_LANG));
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
orgDispName.setValue(StaxParserUtil.getElementText(xmlEventReader));
|
||||
target.addOrganizationDisplayName(orgDispName);
|
||||
break;
|
||||
|
||||
case ORGANIZATION_URL:
|
||||
case ORGANIZATION_URL_ALT:
|
||||
LocalizedURIType orgURL = new LocalizedURIType(StaxParserUtil.getAttributeValue(elementDetail, ATTR_LANG));
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
orgURL.setValue(URI.create(StaxParserUtil.getElementText(xmlEventReader)));
|
||||
target.addOrganizationURL(orgURL);
|
||||
break;
|
||||
|
||||
case EXTENSIONS:
|
||||
target.setExtensions(SAMLExtensionsParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.PDPDescriptorType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLPDPDescriptorParser extends SAMLRoleDecriptorTypeParser<PDPDescriptorType> {
|
||||
|
||||
private static final SAMLPDPDescriptorParser INSTANCE = new SAMLPDPDescriptorParser();
|
||||
|
||||
public SAMLPDPDescriptorParser() {
|
||||
super(SAMLMetadataQNames.PDP_DESCRIPTOR);
|
||||
}
|
||||
|
||||
public static SAMLPDPDescriptorParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PDPDescriptorType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
List<String> protocolEnum = StaxParserUtil.getRequiredStringListAttributeValue(element, SAMLMetadataQNames.ATTR_PROTOCOL_SUPPORT_ENUMERATION);
|
||||
PDPDescriptorType descriptor = new PDPDescriptorType(protocolEnum);
|
||||
|
||||
parseOptionalArguments(element, descriptor);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, PDPDescriptorType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case AUTHZ_SERVICE:
|
||||
target.addAuthZService(SAMLAuthzServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ASSERTION_ID_REQUEST_SERVICE:
|
||||
target.addAssertionIDRequestService(SAMLAssertinIDRequestServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case NAMEID_FORMAT:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
super.processSubElement(xmlEventReader, target, element, elementDetail);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,31 +17,25 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.RequestedAttributeType;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLConstants;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.Attribute;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAttributeValueParser;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionQNames;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAttributeValueParser;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
|
||||
/**
|
||||
* Parse the <conditions> in the saml assertion
|
||||
*
|
||||
* @since Oct 14, 2010
|
||||
*/
|
||||
public class SAMLRequestedAttributeParser extends AbstractStaxSamlParser<RequestedAttributeType> {
|
||||
public class SAMLRequestedAttributeParser extends AbstractStaxSamlMetadataParser<RequestedAttributeType> {
|
||||
|
||||
private static final SAMLRequestedAttributeParser INSTANCE = new SAMLRequestedAttributeParser();
|
||||
private static final QName X500_ENCODING = new QName(JBossSAMLURIConstants.X500_NSURI.get(), JBossSAMLConstants.ENCODING.get(),
|
||||
JBossSAMLURIConstants.X500_PREFIX.get());
|
||||
|
||||
|
||||
private SAMLRequestedAttributeParser() {
|
||||
super(JBossSAMLConstants.REQUESTED_ATTRIBUTE);
|
||||
super(SAMLMetadataQNames.REQUESTED_ATTRIBUTE);
|
||||
}
|
||||
|
||||
public static SAMLRequestedAttributeParser getInstance() {
|
||||
|
@ -50,24 +44,22 @@ public class SAMLRequestedAttributeParser extends AbstractStaxSamlParser<Request
|
|||
|
||||
@Override
|
||||
protected RequestedAttributeType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
RequestedAttributeType attributeType;
|
||||
RequestedAttributeType attributeType = new RequestedAttributeType(StaxParserUtil.getRequiredAttributeValue(element, SAMLAssertionQNames.ATTR_NAME));
|
||||
|
||||
// TODO: replace all constants with SamlMetadataQNames ones
|
||||
attributeType = new RequestedAttributeType(StaxParserUtil.getRequiredAttributeValue(element, SAMLAssertionQNames.ATTR_NAME));
|
||||
attributeType.setFriendlyName(StaxParserUtil.getAttributeValue(element, JBossSAMLConstants.FRIENDLY_NAME.get()));
|
||||
attributeType.setIsRequired(StaxParserUtil.getBooleanAttributeValue(element, JBossSAMLConstants.IS_REQUIRED.get()));
|
||||
attributeType.setNameFormat(StaxParserUtil.getAttributeValue(element, JBossSAMLConstants.NAME_FORMAT.get()));
|
||||
attributeType.setFriendlyName(StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_FRIENDLY_NAME));
|
||||
attributeType.setIsRequired(StaxParserUtil.getBooleanAttributeValue(element, SAMLMetadataQNames.ATTR_IS_REQUIRED));
|
||||
attributeType.setNameFormat(StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_NAME_FORMAT));
|
||||
|
||||
Attribute x500EncodingAttr = element.getAttributeByName(X500_ENCODING);
|
||||
if (x500EncodingAttr != null) {
|
||||
attributeType.getOtherAttributes().put(x500EncodingAttr.getName(), StaxParserUtil.getAttributeValue(x500EncodingAttr));
|
||||
String encoding = StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_X500_ENCODING);
|
||||
if (encoding != null && !encoding.isEmpty()) {
|
||||
attributeType.getOtherAttributes().put(SAMLMetadataQNames.ATTR_X500_ENCODING.getQName(), encoding);
|
||||
}
|
||||
|
||||
return attributeType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, RequestedAttributeType target, JBossSAMLConstants element, StartElement elementDetail) throws ParsingException {
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, RequestedAttributeType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case ATTRIBUTE_VALUE:
|
||||
target.addAttributeValue(SAMLAttributeValueParser.getInstance().parse(xmlEventReader));
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.RoleDescriptorType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public abstract class SAMLRoleDecriptorTypeParser<T extends RoleDescriptorType> extends AbstractStaxSamlMetadataParser<T> {
|
||||
|
||||
public SAMLRoleDecriptorTypeParser(SAMLMetadataQNames expectedStartElement) {
|
||||
super(expectedStartElement);
|
||||
}
|
||||
|
||||
protected void parseOptionalArguments(StartElement element, RoleDescriptorType descriptor) throws ParsingException {
|
||||
descriptor.setID(StaxParserUtil.getAttributeValue(element, SAMLMetadataQNames.ATTR_ID));
|
||||
descriptor.setValidUntil(StaxParserUtil.getXmlTimeAttributeValue(element, SAMLMetadataQNames.ATTR_VALID_UNTIL));
|
||||
descriptor.setCacheDuration(StaxParserUtil.getXmlDurationAttributeValue(element, SAMLMetadataQNames.ATTR_CACHE_DURATION));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, T target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case KEY_DESCRIPTOR:
|
||||
target.addKeyDescriptor(SAMLKeyDescriptorParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case SIGNATURE:
|
||||
Element sig = StaxParserUtil.getDOMElement(xmlEventReader);
|
||||
target.setSignature(sig);
|
||||
break;
|
||||
|
||||
case EXTENSIONS:
|
||||
target.setExtensions(SAMLExtensionsParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ORGANIZATION:
|
||||
target.setOrganization(SAMLOrganizationParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case CONTACT_PERSON:
|
||||
target.addContactPerson(SAMLContactPersonParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLMetadataQNames.SP_SSO_DESCRIPTOR;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLSPSSODescriptorParser extends SAMLSSODescriptorTypeParser<SPSSODescriptorType> {
|
||||
|
||||
private static final SAMLSPSSODescriptorParser INSTANCE = new SAMLSPSSODescriptorParser();
|
||||
|
||||
private SAMLSPSSODescriptorParser() {
|
||||
super(SP_SSO_DESCRIPTOR);
|
||||
}
|
||||
|
||||
public static SAMLSPSSODescriptorParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SPSSODescriptorType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
|
||||
List<String> protocolEnum = StaxParserUtil.getRequiredStringListAttributeValue(element, SAMLMetadataQNames.ATTR_PROTOCOL_SUPPORT_ENUMERATION);
|
||||
SPSSODescriptorType descriptor = new SPSSODescriptorType(protocolEnum);
|
||||
|
||||
// Role descriptor optional arguments
|
||||
parseOptionalArguments(element, descriptor);
|
||||
|
||||
// SPSSODecsriptor optional attributes
|
||||
Boolean authnRequestsSigned = StaxParserUtil.getBooleanAttributeValue(element, SAMLMetadataQNames.ATTR_AUTHN_REQUESTS_SIGNED);
|
||||
if (authnRequestsSigned != null) {
|
||||
descriptor.setAuthnRequestsSigned(authnRequestsSigned);
|
||||
}
|
||||
|
||||
Boolean wantAssertionSigned = StaxParserUtil.getBooleanAttributeValue(element, SAMLMetadataQNames.ATTR_WANT_ASSERTIONS_SIGNED);
|
||||
if (wantAssertionSigned != null) {
|
||||
descriptor.setWantAssertionsSigned(wantAssertionSigned);
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, SPSSODescriptorType target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case ASSERTION_CONSUMER_SERVICE:
|
||||
target.addAssertionConsumerService(SAMLAssertionConsumerServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case ATTRIBUTE_CONSUMING_SERVICE:
|
||||
target.addAttributeConsumerService(SAMLAttributeConsumingServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
super.processSubElement(xmlEventReader, target, element, elementDetail);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
import org.keycloak.dom.saml.v2.metadata.SSODescriptorType;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
import javax.xml.stream.events.StartElement;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public abstract class SAMLSSODescriptorTypeParser<T extends SSODescriptorType> extends SAMLRoleDecriptorTypeParser<T> {
|
||||
|
||||
public SAMLSSODescriptorTypeParser(SAMLMetadataQNames expectedStartElement) {
|
||||
super(expectedStartElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processSubElement(XMLEventReader xmlEventReader, T target, SAMLMetadataQNames element, StartElement elementDetail) throws ParsingException {
|
||||
switch (element) {
|
||||
case ARTIFACT_RESOLUTION_SERVICE:
|
||||
target.addArtifactResolutionService(SAMLArtifactResolutionServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case SINGLE_LOGOUT_SERVICE:
|
||||
target.addSingleLogoutService(SAMLSingleLogoutServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case MANAGE_NAMEID_SERVICE:
|
||||
target.addSingleLogoutService(SAMLManageNameIDServiceParser.getInstance().parse(xmlEventReader));
|
||||
break;
|
||||
|
||||
case NAMEID_FORMAT:
|
||||
StaxParserUtil.advance(xmlEventReader);
|
||||
target.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader));
|
||||
break;
|
||||
|
||||
default:
|
||||
super.processSubElement(xmlEventReader, target, element, elementDetail);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLSingleLogoutServiceParser extends SAMLEndpointTypeParser {
|
||||
|
||||
private static final SAMLSingleLogoutServiceParser INSTANCE = new SAMLSingleLogoutServiceParser();
|
||||
|
||||
public SAMLSingleLogoutServiceParser() {
|
||||
super(SAMLMetadataQNames.SINGLE_LOGOUT_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLSingleLogoutServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.saml.processing.core.parsers.saml.metadata;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
public class SAMLSingleSignOnServiceParser extends SAMLEndpointTypeParser {
|
||||
|
||||
private static final SAMLSingleSignOnServiceParser INSTANCE = new SAMLSingleSignOnServiceParser();
|
||||
|
||||
public SAMLSingleSignOnServiceParser() {
|
||||
super(SAMLMetadataQNames.SINGLE_SIGNON_SERVICE);
|
||||
}
|
||||
|
||||
public static SAMLSingleSignOnServiceParser getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -16,24 +16,12 @@
|
|||
*/
|
||||
package org.keycloak.saml.processing.core.parsers.saml;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.PrivateKey;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.keycloak.common.util.Base64;
|
||||
import org.keycloak.common.util.DerUtils;
|
||||
import org.keycloak.common.util.StreamUtil;
|
||||
|
@ -50,7 +38,21 @@ import org.keycloak.dom.saml.v2.assertion.NameIDType;
|
|||
import org.keycloak.dom.saml.v2.assertion.StatementAbstractType;
|
||||
import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationType;
|
||||
import org.keycloak.dom.saml.v2.assertion.SubjectType;
|
||||
import org.keycloak.dom.saml.v2.metadata.AttributeAuthorityDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.AttributeConsumingServiceType;
|
||||
import org.keycloak.dom.saml.v2.metadata.AuthnAuthorityDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.EndpointType;
|
||||
import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.IndexedEndpointType;
|
||||
import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.KeyTypes;
|
||||
import org.keycloak.dom.saml.v2.metadata.LocalizedNameType;
|
||||
import org.keycloak.dom.saml.v2.metadata.LocalizedURIType;
|
||||
import org.keycloak.dom.saml.v2.metadata.PDPDescriptorType;
|
||||
import org.keycloak.dom.saml.v2.metadata.RequestedAttributeType;
|
||||
import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
|
||||
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
|
||||
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
|
||||
import org.keycloak.dom.saml.v2.protocol.ResponseType;
|
||||
|
@ -60,6 +62,7 @@ import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType;
|
|||
import org.keycloak.dom.xmlsec.w3.xmldsig.RSAKeyValueType;
|
||||
import org.keycloak.dom.xmlsec.w3.xmldsig.X509CertificateType;
|
||||
import org.keycloak.dom.xmlsec.w3.xmldsig.X509DataType;
|
||||
import org.keycloak.dom.xmlsec.w3.xmlenc.EncryptionMethodType;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||
import org.keycloak.saml.common.exceptions.ConfigurationException;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
|
@ -67,11 +70,38 @@ import org.keycloak.saml.common.exceptions.ProcessingException;
|
|||
import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
|
||||
import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
|
||||
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.emptyCollectionOf;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.everyItem;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test class for SAML parser.
|
||||
*
|
||||
|
@ -251,12 +281,341 @@ public class SAMLParserTest {
|
|||
|
||||
@Test
|
||||
public void testSaml20MetadataEntityDescriptorIdP() throws Exception {
|
||||
assertParsed("saml20-entity-descriptor-idp.xml", EntityDescriptorType.class);
|
||||
EntityDescriptorType entityDescriptor = assertParsed("saml20-entity-descriptor-idp.xml", EntityDescriptorType.class);
|
||||
|
||||
List<EntityDescriptorType.EDTChoiceType> descriptors = entityDescriptor.getChoiceType();
|
||||
assertThat(descriptors, hasSize(2));
|
||||
|
||||
// IDPSSO descriptor
|
||||
IDPSSODescriptorType idpDescriptor = descriptors.get(0).getDescriptors().get(0).getIdpDescriptor();
|
||||
assertThat(idpDescriptor, is(notNullValue()));
|
||||
assertThat(idpDescriptor.isWantAuthnRequestsSigned(), is(true));
|
||||
assertThat(idpDescriptor.getProtocolSupportEnumeration(), contains("urn:oasis:names:tc:SAML:2.0:protocol"));
|
||||
|
||||
// Key descriptor
|
||||
List<KeyDescriptorType> keyDescriptors = idpDescriptor.getKeyDescriptor();
|
||||
assertThat(keyDescriptors, hasSize(1));
|
||||
|
||||
KeyDescriptorType signingKey = keyDescriptors.get(0);
|
||||
assertThat(signingKey.getUse(), is(KeyTypes.SIGNING));
|
||||
assertThat(signingKey.getEncryptionMethod(), is(emptyCollectionOf(EncryptionMethodType.class)));
|
||||
assertThat(signingKey.getKeyInfo().getElementsByTagName("ds:KeyName").item(0).getTextContent(), is("IdentityProvider.com SSO Key"));
|
||||
|
||||
// Single logout services
|
||||
assertThat(idpDescriptor.getSingleLogoutService(), hasSize(2));
|
||||
EndpointType singleLS1 = idpDescriptor.getSingleLogoutService().get(0);
|
||||
assertThat(singleLS1.getBinding(), is(URI.create("urn:oasis:names:tc:SAML:2.0:bindings:SOAP")));
|
||||
assertThat(singleLS1.getLocation(), is(URI.create("https://IdentityProvider.com/SAML/SLO/SOAP")));
|
||||
assertThat(singleLS1.getResponseLocation(), is(nullValue()));
|
||||
assertThat(singleLS1.getAny(), is(emptyCollectionOf(Object.class)));
|
||||
assertThat(singleLS1.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
EndpointType singleLS2 = idpDescriptor.getSingleLogoutService().get(1);
|
||||
assertThat(singleLS2.getBinding(), is(URI.create("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect")));
|
||||
assertThat(singleLS2.getLocation(), is(URI.create("https://IdentityProvider.com/SAML/SLO/Browser")));
|
||||
assertThat(singleLS2.getResponseLocation(), is(URI.create("https://IdentityProvider.com/SAML/SLO/Response")));
|
||||
assertThat(singleLS2.getAny(), is(emptyCollectionOf(Object.class)));
|
||||
assertThat(singleLS2.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
// NameID
|
||||
assertThat(idpDescriptor.getNameIDFormat(),
|
||||
containsInAnyOrder("urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName",
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
|
||||
));
|
||||
|
||||
// Single sign on services
|
||||
assertThat(idpDescriptor.getSingleSignOnService(), hasSize(2));
|
||||
|
||||
EndpointType singleSO1 = idpDescriptor.getSingleSignOnService().get(0);
|
||||
assertThat(singleSO1.getBinding(), is(URI.create("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect")));
|
||||
assertThat(singleSO1.getLocation(), is(URI.create("https://IdentityProvider.com/SAML/SSO/Browser")));
|
||||
assertThat(singleSO1.getResponseLocation(), is(nullValue()));
|
||||
assertThat(singleSO1.getAny(), is(emptyCollectionOf(Object.class)));
|
||||
assertThat(singleSO1.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
EndpointType singleSO2 = idpDescriptor.getSingleSignOnService().get(1);
|
||||
assertThat(singleSO2.getBinding(), is(URI.create("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST")));
|
||||
assertThat(singleSO2.getLocation(), is(URI.create("https://IdentityProvider.com/SAML/SSO/Browser")));
|
||||
assertThat(singleSO2.getResponseLocation(), is(nullValue()));
|
||||
assertThat(singleSO2.getAny(), is(emptyCollectionOf(Object.class)));
|
||||
assertThat(singleSO2.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
// Attributes
|
||||
assertThat(idpDescriptor.getAttribute(), hasSize(2));
|
||||
|
||||
AttributeType attr1 = idpDescriptor.getAttribute().get(0);
|
||||
assertThat(attr1.getNameFormat(), is("urn:oasis:names:tc:SAML:2.0:attrname-format:uri"));
|
||||
assertThat(attr1.getName(), is("urn:oid:1.3.6.1.4.1.5923.1.1.1.6"));
|
||||
assertThat(attr1.getFriendlyName(), is("eduPersonPrincipalName"));
|
||||
assertThat(attr1.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
assertThat(attr1.getAttributeValue(), is(emptyCollectionOf(Object.class)));
|
||||
|
||||
AttributeType attr2 = idpDescriptor.getAttribute().get(1);
|
||||
assertThat(attr2.getNameFormat(), is("urn:oasis:names:tc:SAML:2.0:attrname-format:uri"));
|
||||
assertThat(attr2.getName(), is("urn:oid:1.3.6.1.4.1.5923.1.1.1.1"));
|
||||
assertThat(attr2.getFriendlyName(), is("eduPersonAffiliation"));
|
||||
assertThat(attr2.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
assertThat(attr2.getAttributeValue(), containsInAnyOrder((Object) "member", "student", "faculty", "employee", "staff"));
|
||||
|
||||
// Organization
|
||||
assertThat(entityDescriptor.getOrganization().getOrganizationName(), hasSize(1));
|
||||
LocalizedNameType orgName = entityDescriptor.getOrganization().getOrganizationName().get(0);
|
||||
assertThat(orgName.getLang(), is("en"));
|
||||
assertThat(orgName.getValue(), is("Identity Providers R\n US"));
|
||||
|
||||
assertThat(entityDescriptor.getOrganization().getOrganizationDisplayName(), hasSize(1));
|
||||
LocalizedNameType orgDispName = entityDescriptor.getOrganization().getOrganizationDisplayName().get(0);
|
||||
assertThat(orgDispName.getLang(), is("en"));
|
||||
assertThat(orgDispName.getValue(), is("Identity Providers R US, a Division of Lerxst Corp."));
|
||||
|
||||
assertThat(entityDescriptor.getOrganization().getOrganizationURL(), hasSize(1));
|
||||
LocalizedURIType orgURL = entityDescriptor.getOrganization().getOrganizationURL().get(0);
|
||||
assertThat(orgURL.getLang(), is("en"));
|
||||
assertThat(orgURL.getValue(), is(URI.create("https://IdentityProvider.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSAML20MetadataEntityDescriptorAttrA() throws Exception{
|
||||
EntityDescriptorType entityDescriptor = assertParsed("saml20-entity-descriptor-idp.xml", EntityDescriptorType.class);
|
||||
|
||||
List<EntityDescriptorType.EDTChoiceType> descriptors = entityDescriptor.getChoiceType();
|
||||
assertThat(descriptors, hasSize(2));
|
||||
|
||||
AttributeAuthorityDescriptorType aaDescriptor = descriptors.get(1).getDescriptors().get(0).getAttribDescriptor();
|
||||
assertThat(aaDescriptor, is(notNullValue()));
|
||||
assertThat(aaDescriptor.getProtocolSupportEnumeration(), contains("urn:oasis:names:tc:SAML:2.0:protocol"));
|
||||
|
||||
// Key descriptor
|
||||
List<KeyDescriptorType> keyDescriptors = aaDescriptor.getKeyDescriptor();
|
||||
assertThat(keyDescriptors, hasSize(1));
|
||||
|
||||
KeyDescriptorType signingKey = keyDescriptors.get(0);
|
||||
assertThat(signingKey.getUse(), is(KeyTypes.SIGNING));
|
||||
assertThat(signingKey.getEncryptionMethod(), is(emptyCollectionOf(EncryptionMethodType.class)));
|
||||
assertThat(signingKey.getKeyInfo().getElementsByTagName("ds:KeyName").item(0).getTextContent(), is("IdentityProvider.com AA Key"));
|
||||
|
||||
// Attribute service
|
||||
assertThat(aaDescriptor.getAttributeService(), hasSize(1));
|
||||
EndpointType attrServ = aaDescriptor.getAttributeService().get(0);
|
||||
assertThat(attrServ.getBinding(), is(URI.create("urn:oasis:names:tc:SAML:2.0:bindings:SOAP")));
|
||||
assertThat(attrServ.getLocation(), is(URI.create("https://IdentityProvider.com/SAML/AA/SOAP")));
|
||||
assertThat(attrServ.getResponseLocation(), is(nullValue()));
|
||||
assertThat(attrServ.getAny(), is(emptyCollectionOf(Object.class)));
|
||||
assertThat(attrServ.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
// AssertionIDRequestService
|
||||
assertThat(aaDescriptor.getAssertionIDRequestService(), hasSize(1));
|
||||
EndpointType assertIDRServ = aaDescriptor.getAssertionIDRequestService().get(0);
|
||||
assertThat(assertIDRServ.getBinding(), is(URI.create("urn:oasis:names:tc:SAML:2.0:bindings:URI")));
|
||||
assertThat(assertIDRServ.getLocation(), is(URI.create("https://IdentityProvider.com/SAML/AA/URI")));
|
||||
assertThat(assertIDRServ.getResponseLocation(), is(nullValue()));
|
||||
assertThat(assertIDRServ.getAny(), is(emptyCollectionOf(Object.class)));
|
||||
assertThat(assertIDRServ.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
// NameID
|
||||
assertThat(aaDescriptor.getNameIDFormat(),
|
||||
containsInAnyOrder("urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName",
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
|
||||
"urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
|
||||
));
|
||||
|
||||
assertThat(aaDescriptor.getAttribute(), hasSize(2));
|
||||
|
||||
AttributeType attr1 = aaDescriptor.getAttribute().get(0);
|
||||
assertThat(attr1.getNameFormat(), is("urn:oasis:names:tc:SAML:2.0:attrname-format:uri"));
|
||||
assertThat(attr1.getName(), is("urn:oid:1.3.6.1.4.1.5923.1.1.1.6"));
|
||||
assertThat(attr1.getFriendlyName(), is("eduPersonPrincipalName"));
|
||||
assertThat(attr1.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
assertThat(attr1.getAttributeValue(), is(emptyCollectionOf(Object.class)));
|
||||
|
||||
AttributeType attr2 = aaDescriptor.getAttribute().get(1);
|
||||
assertThat(attr2.getNameFormat(), is("urn:oasis:names:tc:SAML:2.0:attrname-format:uri"));
|
||||
assertThat(attr2.getName(), is("urn:oid:1.3.6.1.4.1.5923.1.1.1.1"));
|
||||
assertThat(attr2.getFriendlyName(), is("eduPersonAffiliation"));
|
||||
assertThat(attr2.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
assertThat(attr2.getAttributeValue(), containsInAnyOrder((Object) "member", "student", "faculty", "employee", "staff"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaml20MetadataEntityDescriptorSP() throws Exception {
|
||||
assertParsed("saml20-entity-descriptor-sp.xml", EntityDescriptorType.class);
|
||||
EntityDescriptorType entityDescriptor = assertParsed("saml20-entity-descriptor-sp.xml", EntityDescriptorType.class);
|
||||
|
||||
assertThat(entityDescriptor.getEntityID(), is("https://ServiceProvider.com/SAML"));
|
||||
assertThat(entityDescriptor.getValidUntil(), is(nullValue()));
|
||||
assertThat(entityDescriptor.getCacheDuration(), is(nullValue()));
|
||||
assertThat(entityDescriptor.getID(), is(nullValue()));
|
||||
|
||||
assertThat(entityDescriptor.getExtensions(), is(nullValue()));
|
||||
|
||||
List<EntityDescriptorType.EDTChoiceType> descriptors = entityDescriptor.getChoiceType();
|
||||
assertThat(descriptors, hasSize(1));
|
||||
|
||||
// SP Descriptor
|
||||
SPSSODescriptorType spDescriptor = descriptors.get(0).getDescriptors().get(0).getSpDescriptor();
|
||||
assertThat(spDescriptor, is(notNullValue()));
|
||||
|
||||
assertThat(spDescriptor.isAuthnRequestsSigned(), is(true));
|
||||
assertThat(spDescriptor.isWantAssertionsSigned(), is(false));
|
||||
assertThat(spDescriptor.getProtocolSupportEnumeration(), contains("urn:oasis:names:tc:SAML:2.0:protocol"));
|
||||
|
||||
// Key descriptor
|
||||
List<KeyDescriptorType> keyDescriptors = spDescriptor.getKeyDescriptor();
|
||||
assertThat(keyDescriptors, hasSize(2));
|
||||
|
||||
KeyDescriptorType signingKey = keyDescriptors.get(0);
|
||||
assertThat(signingKey.getUse(), is(KeyTypes.SIGNING));
|
||||
assertThat(signingKey.getEncryptionMethod(), is(emptyCollectionOf(EncryptionMethodType.class)));
|
||||
assertThat(signingKey.getKeyInfo().getElementsByTagName("ds:KeyName").item(0).getTextContent(), is("ServiceProvider.com SSO Key"));
|
||||
|
||||
KeyDescriptorType encryptionKey = keyDescriptors.get(1);
|
||||
assertThat(encryptionKey.getUse(), is(KeyTypes.ENCRYPTION));
|
||||
assertThat(encryptionKey.getKeyInfo().getElementsByTagName("ds:KeyName").item(0).getTextContent(), is("ServiceProvider.com Encrypt Key"));
|
||||
|
||||
List<EncryptionMethodType> encryptionMethods = encryptionKey.getEncryptionMethod();
|
||||
assertThat(encryptionMethods, Matchers.<EncryptionMethodType>hasSize(1));
|
||||
assertThat(encryptionMethods.get(0).getAlgorithm(), is("http://www.w3.org/2001/04/xmlenc#rsa-1_5"));
|
||||
assertThat(encryptionMethods.get(0).getEncryptionMethod(), is(nullValue()));
|
||||
|
||||
// Single logout services
|
||||
assertThat(spDescriptor.getSingleLogoutService(), hasSize(2));
|
||||
EndpointType singleLS1 = spDescriptor.getSingleLogoutService().get(0);
|
||||
assertThat(singleLS1.getBinding(), is(URI.create("urn:oasis:names:tc:SAML:2.0:bindings:SOAP")));
|
||||
assertThat(singleLS1.getLocation(), is(URI.create("https://ServiceProvider.com/SAML/SLO/SOAP")));
|
||||
assertThat(singleLS1.getResponseLocation(), is(nullValue()));
|
||||
assertThat(singleLS1.getAny(), is(emptyCollectionOf(Object.class)));
|
||||
assertThat(singleLS1.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
EndpointType singleLS2 = spDescriptor.getSingleLogoutService().get(1);
|
||||
assertThat(singleLS2.getBinding(), is(URI.create("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect")));
|
||||
assertThat(singleLS2.getLocation(), is(URI.create("https://ServiceProvider.com/SAML/SLO/Browser")));
|
||||
assertThat(singleLS2.getResponseLocation(), is(URI.create("https://ServiceProvider.com/SAML/SLO/Response")));
|
||||
assertThat(singleLS2.getAny(), is(emptyCollectionOf(Object.class)));
|
||||
assertThat(singleLS2.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
// NameID
|
||||
assertThat(spDescriptor.getNameIDFormat(), contains("urn:oasis:names:tc:SAML:2.0:nameid-format:transient"));
|
||||
|
||||
// Assertion consumer services
|
||||
List<IndexedEndpointType> assertionConsumerServices = spDescriptor.getAssertionConsumerService();
|
||||
assertThat(assertionConsumerServices, hasSize(2));
|
||||
|
||||
IndexedEndpointType assertionCS1 = assertionConsumerServices.get(0);
|
||||
assertThat(assertionCS1.getIndex(), is(0));
|
||||
assertThat(assertionCS1.isIsDefault(), is(true));
|
||||
assertThat(assertionCS1.getBinding(), is(URI.create("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact")));
|
||||
assertThat(assertionCS1.getLocation(), is(URI.create("https://ServiceProvider.com/SAML/SSO/Artifact")));
|
||||
assertThat(assertionCS1.getResponseLocation(), is(nullValue()));
|
||||
assertThat(assertionCS1.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
IndexedEndpointType assertionCS2 = assertionConsumerServices.get(1);
|
||||
assertThat(assertionCS2.getIndex(), is(1));
|
||||
assertThat(assertionCS2.isIsDefault(), is(nullValue()));
|
||||
assertThat(assertionCS2.getBinding(), is(URI.create("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST")));
|
||||
assertThat(assertionCS2.getLocation(), is(URI.create("https://ServiceProvider.com/SAML/SSO/POST")));
|
||||
assertThat(assertionCS2.getResponseLocation(), is(nullValue()));
|
||||
assertThat(assertionCS2.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
// Attribute consuming services
|
||||
List<AttributeConsumingServiceType> attributeConsumingServices = spDescriptor.getAttributeConsumingService();
|
||||
assertThat(attributeConsumingServices, hasSize(1));
|
||||
|
||||
AttributeConsumingServiceType attributeConsumingService = attributeConsumingServices.get(0);
|
||||
assertThat(attributeConsumingService.getIndex(), is(0));
|
||||
assertThat(attributeConsumingService.getServiceName(), hasSize(1));
|
||||
LocalizedNameType servName = attributeConsumingService.getServiceName().get(0);
|
||||
assertThat(servName.getLang(), is("en"));
|
||||
assertThat(servName.getValue(), is("Academic Journals R US"));
|
||||
assertThat(attributeConsumingService.getServiceDescription(), is(emptyCollectionOf(LocalizedNameType.class)));
|
||||
|
||||
List<RequestedAttributeType> requestedAttributes = attributeConsumingService.getRequestedAttribute();
|
||||
assertThat(requestedAttributes, hasSize(1));
|
||||
|
||||
// Requested attribute
|
||||
RequestedAttributeType requestedAttribute = requestedAttributes.get(0);
|
||||
assertThat(requestedAttribute.getNameFormat(), is("urn:oasis:names:tc:SAML:2.0:attrname-format:uri"));
|
||||
assertThat(requestedAttribute.getName(), is("urn:oid:1.3.6.1.4.1.5923.1.1.1.7"));
|
||||
assertThat(requestedAttribute.getFriendlyName(), is("eduPersonEntitlement"));
|
||||
|
||||
assertThat(requestedAttribute.getAttributeValue(), hasSize(1));
|
||||
assertThat((String) requestedAttribute.getAttributeValue().get(0), is("https://ServiceProvider.com/entitlements/123456789"));
|
||||
|
||||
assertThat(requestedAttribute.getOtherAttributes(), is(Collections.<QName, String>emptyMap()));
|
||||
|
||||
// Organization
|
||||
assertThat(entityDescriptor.getOrganization().getOrganizationName(), hasSize(1));
|
||||
LocalizedNameType orgName = entityDescriptor.getOrganization().getOrganizationName().get(0);
|
||||
assertThat(orgName.getLang(), is("en"));
|
||||
assertThat(orgName.getValue(), is("Academic Journals R\n US"));
|
||||
|
||||
assertThat(entityDescriptor.getOrganization().getOrganizationDisplayName(), hasSize(1));
|
||||
LocalizedNameType orgDispName = entityDescriptor.getOrganization().getOrganizationDisplayName().get(0);
|
||||
assertThat(orgDispName.getLang(), is("en"));
|
||||
assertThat(orgDispName.getValue(), is("Academic Journals R US, a Division of Dirk Corp."));
|
||||
|
||||
assertThat(entityDescriptor.getOrganization().getOrganizationURL(), hasSize(1));
|
||||
LocalizedURIType orgURL = entityDescriptor.getOrganization().getOrganizationURL().get(0);
|
||||
assertThat(orgURL.getLang(), is("en"));
|
||||
assertThat(orgURL.getValue(), is(URI.create("https://ServiceProvider.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaml20MetadataEntityDescriptorPDP() throws Exception {
|
||||
EntityDescriptorType descriptor = assertParsed("saml20-entity-descriptor-pdp.xml", EntityDescriptorType.class);
|
||||
|
||||
assertThat(descriptor.getChoiceType(), Matchers.<EntityDescriptorType.EDTChoiceType>hasSize(1));
|
||||
assertThat(descriptor.getChoiceType().get(0).getDescriptors().get(0).getPdpDescriptor(), is(notNullValue()));
|
||||
|
||||
PDPDescriptorType pdpDescriptor = descriptor.getChoiceType().get(0).getDescriptors().get(0).getPdpDescriptor();
|
||||
|
||||
assertThat(pdpDescriptor.getKeyDescriptor(), Matchers.<KeyDescriptorType>hasSize(1));
|
||||
|
||||
KeyDescriptorType keyDescriptorType = pdpDescriptor.getKeyDescriptor().get(0);
|
||||
assertThat(keyDescriptorType.getEncryptionMethod(), Matchers.<EncryptionMethodType>hasSize(1));
|
||||
|
||||
EncryptionMethodType encryptionMethodType = keyDescriptorType.getEncryptionMethod().get(0);
|
||||
assertThat(encryptionMethodType.getAlgorithm(), is("http://www.example.com/"));
|
||||
|
||||
EncryptionMethodType.EncryptionMethod encryptionMethod = encryptionMethodType.getEncryptionMethod();
|
||||
assertThat(encryptionMethod.getKeySize(), is(BigInteger.ONE));
|
||||
assertThat(encryptionMethod.getOAEPparams(), is("GpM7".getBytes()));
|
||||
|
||||
// EndpointType parser already tested so we are not checking further
|
||||
assertThat(pdpDescriptor.getAuthzService(), Matchers.<EndpointType>hasSize(1));
|
||||
assertThat(pdpDescriptor.getAssertionIDRequestService(), Matchers.<EndpointType>hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaml20MetadataEntityDescriptorAuthnAuthority() throws Exception {
|
||||
EntityDescriptorType descriptor = assertParsed("saml20-entity-descriptor-authn-authority.xml", EntityDescriptorType.class);
|
||||
|
||||
assertThat(descriptor.getChoiceType(), Matchers.<EntityDescriptorType.EDTChoiceType>hasSize(1));
|
||||
assertThat(descriptor.getChoiceType().get(0).getDescriptors().get(0).getAuthnDescriptor(), is(notNullValue()));
|
||||
|
||||
AuthnAuthorityDescriptorType authnDescriptor = descriptor.getChoiceType().get(0).getDescriptors().get(0).getAuthnDescriptor();
|
||||
|
||||
assertThat(authnDescriptor.getAssertionIDRequestService(), hasSize(1));
|
||||
assertThat(authnDescriptor.getAuthnQueryService(), hasSize(1));
|
||||
assertThat(authnDescriptor.getProtocolSupportEnumeration(), containsInAnyOrder("http://www.example.com/", "http://www.example2.com/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaml20MetadataEntitiesDescriptor() throws Exception {
|
||||
EntitiesDescriptorType entities = assertParsed("saml20-entities-descriptor.xml", EntitiesDescriptorType.class);
|
||||
|
||||
assertThat(entities.getName(), is("https://your-federation.org/metadata/federation-name.xml"));
|
||||
assertThat(entities.getID(), is(nullValue()));
|
||||
assertThat(entities.getCacheDuration(), is(nullValue()));
|
||||
assertThat(entities.getExtensions(), is(nullValue()));
|
||||
assertThat(entities.getSignature(), is(nullValue()));
|
||||
assertThat(entities.getValidUntil(), is(nullValue()));
|
||||
assertThat(entities.getEntityDescriptor(), hasSize(3));
|
||||
assertThat(entities.getEntityDescriptor().get(0), instanceOf(EntityDescriptorType.class));
|
||||
assertThat(entities.getEntityDescriptor().get(1), instanceOf(EntityDescriptorType.class));
|
||||
assertThat(entities.getEntityDescriptor().get(2), instanceOf(EntitiesDescriptorType.class));
|
||||
|
||||
EntitiesDescriptorType nestedEntities = (EntitiesDescriptorType) entities.getEntityDescriptor().get(2);
|
||||
assertThat(nestedEntities.getEntityDescriptor(), hasSize(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -341,6 +700,86 @@ public class SAMLParserTest {
|
|||
assertParsed("saml20-authnrequest-invalid-namespace.xml", AuthnRequestType.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidEndElement() throws Exception {
|
||||
thrown.expect(ParsingException.class);
|
||||
thrown.expectMessage(containsString("The element type \"NameIDFormat\" must be terminated by the matching end-tag \"</NameIDFormat>\"."));
|
||||
|
||||
assertParsed("saml20-entity-descriptor-idp-invalid-end-element.xml", EntityDescriptorType.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeIDPSSODescriptorType() throws Exception {
|
||||
testMissingAttribute("IDPSSODescriptorType", "protocolSupportEnumeration");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeSPSSODescriptorType() throws Exception {
|
||||
testMissingAttribute("SPSSODescriptorType", "protocolSupportEnumeration");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeAttributeAuthorityDescriptorType() throws Exception {
|
||||
testMissingAttribute("AttributeAuthorityDescriptorType", "protocolSupportEnumeration");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeAuthnAuthorityDescriptorType() throws Exception {
|
||||
testMissingAttribute("AuthnAuthorityDescriptorType", "protocolSupportEnumeration");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributePDPDescriptorType() throws Exception {
|
||||
testMissingAttribute("PDPDescriptorType", "protocolSupportEnumeration");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeAttributeConsumingServiceType() throws Exception {
|
||||
testMissingAttribute("AttributeConsumingServiceType", "index");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeAttributeType() throws Exception {
|
||||
testMissingAttribute("AttributeType", "Name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeContactType() throws Exception {
|
||||
testMissingAttribute("ContactType", "contactType");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeEncryptionMethodType() throws Exception {
|
||||
testMissingAttribute("EncryptionMethodType", "Algorithm");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeEndpointTypeBinding() throws Exception {
|
||||
testMissingAttribute("EndpointType", "Binding");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeEndpointTypeLocation() throws Exception {
|
||||
testMissingAttribute("EndpointType", "Location");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeEntityDescriptorType() throws Exception {
|
||||
testMissingAttribute("EntityDescriptorType", "entityID");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingRequiredAttributeRequestedAttributeType() throws Exception {
|
||||
testMissingAttribute("RequestedAttributeType", "Name");
|
||||
}
|
||||
|
||||
private void testMissingAttribute(String type, String attributeName) throws Exception {
|
||||
thrown.expect(ParsingException.class);
|
||||
thrown.expectMessage(containsString("Parser: Required attribute missing: " + attributeName));
|
||||
|
||||
assertParsed("missing-attribute/saml20-" + type + "-" + attributeName + ".xml", EntityDescriptorType.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthnRequestScoping() throws Exception {
|
||||
assertParsed("KEYCLOAK-6109-authnrequest-scoping.xml", AuthnRequestType.class);
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
entityID="https://IdentityProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
|
||||
<AttributeAuthorityDescriptor>
|
||||
|
||||
</AttributeAuthorityDescriptor>
|
||||
<Organization>
|
||||
<OrganizationName xml:lang="en">Identity Providers R
|
||||
US</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en">
|
||||
Identity Providers R US, a Division of Lerxst Corp.
|
||||
</OrganizationDisplayName>
|
||||
<OrganizationURL
|
||||
xml:lang="en">https://IdentityProvider.com</OrganizationURL>
|
||||
</Organization>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,20 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
entityID="https://ServiceProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<SPSSODescriptor AuthnRequestsSigned="true"
|
||||
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
<AttributeConsumingService>
|
||||
<ServiceName xml:lang="en">Academic Journals R US</ServiceName>
|
||||
<RequestedAttribute
|
||||
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7"
|
||||
FriendlyName="eduPersonEntitlement">
|
||||
<saml:AttributeValue>
|
||||
https://ServiceProvider.com/entitlements/123456789
|
||||
</saml:AttributeValue>
|
||||
</RequestedAttribute>
|
||||
</AttributeConsumingService>
|
||||
</SPSSODescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,13 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
entityID="https://IdentityProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<IDPSSODescriptor WantAuthnRequestsSigned="true"
|
||||
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
<saml:Attribute
|
||||
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
FriendlyName="eduPersonPrincipalName">
|
||||
</saml:Attribute>
|
||||
</IDPSSODescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,10 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
|
||||
entityID="https://IdentityProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<AuthnAuthorityDescriptor ID="ID">
|
||||
|
||||
</AuthnAuthorityDescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,18 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
|
||||
entityID="https://IdentityProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<PDPDescriptor ID="ID" protocolSupportEnumeration="http://www.example.com/ http://www.example.com/">
|
||||
|
||||
<ContactPerson>
|
||||
<Company>string</Company>
|
||||
<GivenName>string</GivenName>
|
||||
<SurName>string</SurName>
|
||||
<EmailAddress>http://www.example.com/</EmailAddress>
|
||||
<TelephoneNumber>string</TelephoneNumber>
|
||||
</ContactPerson>
|
||||
|
||||
</PDPDescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,19 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
|
||||
entityID="https://IdentityProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<PDPDescriptor ID="ID" protocolSupportEnumeration="http://www.example.com/ http://www.example.com/">
|
||||
|
||||
<KeyDescriptor>
|
||||
<ds:KeyInfo>
|
||||
<ds:KeyName>string</ds:KeyName>
|
||||
</ds:KeyInfo>
|
||||
<EncryptionMethod>
|
||||
<xenc:KeySize>1</xenc:KeySize>
|
||||
<xenc:OAEPparams>GpM7</xenc:OAEPparams>
|
||||
</EncryptionMethod>
|
||||
</KeyDescriptor>
|
||||
</PDPDescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,12 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
entityID="https://ServiceProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<SPSSODescriptor AuthnRequestsSigned="true"
|
||||
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
|
||||
<SingleLogoutService
|
||||
Location="https://ServiceProvider.com/SAML/SLO/SOAP"/>
|
||||
</SPSSODescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,11 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
entityID="https://ServiceProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<SPSSODescriptor AuthnRequestsSigned="true"
|
||||
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
<SingleLogoutService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"/>
|
||||
</SPSSODescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,4 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,9 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
entityID="https://IdentityProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<IDPSSODescriptor WantAuthnRequestsSigned="true">
|
||||
|
||||
</IDPSSODescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,10 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
|
||||
entityID="https://IdentityProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<PDPDescriptor ID="ID">
|
||||
|
||||
</PDPDescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,19 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
entityID="https://ServiceProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<SPSSODescriptor AuthnRequestsSigned="true"
|
||||
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
<AttributeConsumingService index="0">
|
||||
<ServiceName xml:lang="en">Academic Journals R US</ServiceName>
|
||||
<RequestedAttribute
|
||||
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
FriendlyName="eduPersonEntitlement">
|
||||
<saml:AttributeValue>
|
||||
https://ServiceProvider.com/entitlements/123456789
|
||||
</saml:AttributeValue>
|
||||
</RequestedAttribute>
|
||||
</AttributeConsumingService>
|
||||
</SPSSODescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,9 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
entityID="https://ServiceProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<SPSSODescriptor AuthnRequestsSigned="true">
|
||||
|
||||
</SPSSODescriptor>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,240 @@
|
|||
<EntitiesDescriptor Name="https://your-federation.org/metadata/federation-name.xml"
|
||||
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
xmlns:shibmd="urn:mace:shibboleth:metadata:1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<EntityDescriptor entityID="https://idp.example.org/idp/shibboleth">
|
||||
|
||||
<IDPSSODescriptor protocolSupportEnumeration="urn:mace:shibboleth:1.0 urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
<Extensions>
|
||||
<shibmd:Scope regexp="false">example.org</shibmd:Scope>
|
||||
</Extensions>
|
||||
<KeyDescriptor>
|
||||
<ds:KeyInfo>
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>...</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
</ds:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
|
||||
<NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
|
||||
|
||||
<SingleSignOnService Binding="urn:mace:shibboleth:1.0:profiles:AuthnRequest"
|
||||
Location="https://idp.example.org/idp/profile/Shibboleth/SSO" />
|
||||
|
||||
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||
Location="https://idp.example.org/idp/profile/SAML2/POST/SSO" />
|
||||
|
||||
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
|
||||
Location="https://idp.example.org/idp/profile/SAML2/Redirect/SSO" />
|
||||
</IDPSSODescriptor>
|
||||
|
||||
<AttributeAuthorityDescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
|
||||
<KeyDescriptor>
|
||||
<ds:KeyInfo>
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>...</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
</ds:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
|
||||
<AttributeService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding"
|
||||
Location="https://idp.example.org:8443/idp/profile/SAML1/SOAP/AttributeQuery" />
|
||||
|
||||
<AttributeService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
|
||||
Location="https://idp.example.org:8443/idp/profile/SAML2/SOAP/AttributeQuery" />
|
||||
|
||||
<NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
|
||||
|
||||
</AttributeAuthorityDescriptor>
|
||||
|
||||
<Organization>
|
||||
<OrganizationName xml:lang="en">Your Identities</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en"> Your Identities</OrganizationDisplayName>
|
||||
<OrganizationURL xml:lang="en">http://www.example.org/</OrganizationURL>
|
||||
</Organization>
|
||||
<ContactPerson contactType="technical">
|
||||
<GivenName>Your</GivenName>
|
||||
<SurName>Contact</SurName>
|
||||
<EmailAddress>admin@example.org</EmailAddress>
|
||||
</ContactPerson>
|
||||
|
||||
</EntityDescriptor>
|
||||
|
||||
<!-- A service provider. -->
|
||||
<EntityDescriptor entityID="https://sp.example.org/shibboleth-sp">
|
||||
<SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol">
|
||||
|
||||
<Extensions>
|
||||
<idpdisc:DiscoveryResponse xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol"
|
||||
index="1" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol"
|
||||
Location="http://sp.example.org/Shibboleth.sso/DS"/>
|
||||
<idpdisc:DiscoveryResponse xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol"
|
||||
index="2" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol"
|
||||
Location="https://sp.example.org/Shibboleth.sso/DS"/>
|
||||
</Extensions>
|
||||
|
||||
<KeyDescriptor>
|
||||
<ds:KeyInfo>
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>...</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
</ds:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
|
||||
<NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
|
||||
|
||||
<AssertionConsumerService index="1" isDefault="true"
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||
Location="https://sp.example.org/Shibboleth.sso/SAML2/POST"/>
|
||||
<AssertionConsumerService index="2"
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
|
||||
Location="https://sp.example.org/Shibboleth.sso/SAML2/POST-SimpleSign"/>
|
||||
<AssertionConsumerService index="3"
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
|
||||
Location="https://sp.example.org/Shibboleth.sso/SAML2/Artifact"/>
|
||||
<AssertionConsumerService index="4"
|
||||
Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post"
|
||||
Location="https://sp.example.org/Shibboleth.sso/SAML/POST"/>
|
||||
<AssertionConsumerService index="5"
|
||||
Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01"
|
||||
Location="https://sp.example.org/Shibboleth.sso/SAML/Artifact"/>
|
||||
|
||||
</SPSSODescriptor>
|
||||
|
||||
<Organization>
|
||||
<OrganizationName xml:lang="en">Your Service</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en">Your Service</OrganizationDisplayName>
|
||||
<OrganizationURL xml:lang="en">http://sp.example.org/</OrganizationURL>
|
||||
</Organization>
|
||||
<ContactPerson contactType="technical">
|
||||
<GivenName>Your</GivenName>
|
||||
<SurName>Admin</SurName>
|
||||
<EmailAddress>admin@example.org</EmailAddress>
|
||||
</ContactPerson>
|
||||
|
||||
</EntityDescriptor>
|
||||
|
||||
<EntitiesDescriptor>
|
||||
<EntityDescriptor entityID="https://idp.example.org/idp/shibboleth">
|
||||
|
||||
<IDPSSODescriptor protocolSupportEnumeration="urn:mace:shibboleth:1.0 urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
<Extensions>
|
||||
<shibmd:Scope regexp="false">example.org</shibmd:Scope>
|
||||
</Extensions>
|
||||
<KeyDescriptor>
|
||||
<ds:KeyInfo>
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>...</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
</ds:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
|
||||
<NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
|
||||
|
||||
<SingleSignOnService Binding="urn:mace:shibboleth:1.0:profiles:AuthnRequest"
|
||||
Location="https://idp.example.org/idp/profile/Shibboleth/SSO" />
|
||||
|
||||
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||
Location="https://idp.example.org/idp/profile/SAML2/POST/SSO" />
|
||||
|
||||
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
|
||||
Location="https://idp.example.org/idp/profile/SAML2/Redirect/SSO" />
|
||||
</IDPSSODescriptor>
|
||||
|
||||
<AttributeAuthorityDescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
|
||||
<KeyDescriptor>
|
||||
<ds:KeyInfo>
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>...</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
</ds:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
|
||||
<AttributeService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding"
|
||||
Location="https://idp.example.org:8443/idp/profile/SAML1/SOAP/AttributeQuery" />
|
||||
|
||||
<AttributeService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
|
||||
Location="https://idp.example.org:8443/idp/profile/SAML2/SOAP/AttributeQuery" />
|
||||
|
||||
<NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
|
||||
|
||||
</AttributeAuthorityDescriptor>
|
||||
|
||||
<Organization>
|
||||
<OrganizationName xml:lang="en">Your Identities</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en"> Your Identities</OrganizationDisplayName>
|
||||
<OrganizationURL xml:lang="en">http://www.example.org/</OrganizationURL>
|
||||
</Organization>
|
||||
<ContactPerson contactType="technical">
|
||||
<GivenName>Your</GivenName>
|
||||
<SurName>Contact</SurName>
|
||||
<EmailAddress>admin@example.org</EmailAddress>
|
||||
</ContactPerson>
|
||||
|
||||
</EntityDescriptor>
|
||||
|
||||
<!-- A service provider. -->
|
||||
<EntityDescriptor entityID="https://sp.example.org/shibboleth-sp">
|
||||
<SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol">
|
||||
|
||||
<Extensions>
|
||||
<idpdisc:DiscoveryResponse xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol"
|
||||
index="1" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol"
|
||||
Location="http://sp.example.org/Shibboleth.sso/DS"/>
|
||||
<idpdisc:DiscoveryResponse xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol"
|
||||
index="2" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol"
|
||||
Location="https://sp.example.org/Shibboleth.sso/DS"/>
|
||||
</Extensions>
|
||||
|
||||
<KeyDescriptor>
|
||||
<ds:KeyInfo>
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>...</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
</ds:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
|
||||
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
|
||||
<NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
|
||||
|
||||
<AssertionConsumerService index="1" isDefault="true"
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||
Location="https://sp.example.org/Shibboleth.sso/SAML2/POST"/>
|
||||
<AssertionConsumerService index="2"
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
|
||||
Location="https://sp.example.org/Shibboleth.sso/SAML2/POST-SimpleSign"/>
|
||||
<AssertionConsumerService index="3"
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
|
||||
Location="https://sp.example.org/Shibboleth.sso/SAML2/Artifact"/>
|
||||
<AssertionConsumerService index="4"
|
||||
Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post"
|
||||
Location="https://sp.example.org/Shibboleth.sso/SAML/POST"/>
|
||||
<AssertionConsumerService index="5"
|
||||
Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01"
|
||||
Location="https://sp.example.org/Shibboleth.sso/SAML/Artifact"/>
|
||||
|
||||
</SPSSODescriptor>
|
||||
|
||||
<Organization>
|
||||
<OrganizationName xml:lang="en">Your Service</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en">Your Service</OrganizationDisplayName>
|
||||
<OrganizationURL xml:lang="en">http://sp.example.org/</OrganizationURL>
|
||||
</Organization>
|
||||
<ContactPerson contactType="technical">
|
||||
<GivenName>Your</GivenName>
|
||||
<SurName>Admin</SurName>
|
||||
<EmailAddress>admin@example.org</EmailAddress>
|
||||
</ContactPerson>
|
||||
|
||||
</EntityDescriptor>
|
||||
</EntitiesDescriptor>
|
||||
|
||||
</EntitiesDescriptor>
|
|
@ -0,0 +1,58 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
|
||||
entityID="https://IdentityProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<AuthnAuthorityDescriptor ID="ID" protocolSupportEnumeration="http://www.example.com/ http://www.example2.com/">
|
||||
<ds:Signature>
|
||||
<ds:SignedInfo>
|
||||
<ds:CanonicalizationMethod Algorithm="http://www.example.com/">...</ds:CanonicalizationMethod>
|
||||
<ds:SignatureMethod Algorithm="http://www.example.com/">...</ds:SignatureMethod>
|
||||
<ds:Reference URI="http://www.example.com/">...</ds:Reference>
|
||||
</ds:SignedInfo>
|
||||
<ds:SignatureValue>GpM7</ds:SignatureValue>
|
||||
<ds:KeyInfo>
|
||||
<ds:KeyName>string</ds:KeyName>
|
||||
</ds:KeyInfo>
|
||||
<ds:Object>...</ds:Object>
|
||||
</ds:Signature>
|
||||
<Extensions>...</Extensions>
|
||||
<KeyDescriptor>
|
||||
<ds:KeyInfo>
|
||||
<ds:KeyName>string</ds:KeyName>
|
||||
</ds:KeyInfo>
|
||||
<EncryptionMethod Algorithm="http://www.example.com/">
|
||||
<xenc:KeySize>1</xenc:KeySize>
|
||||
<xenc:OAEPparams>GpM7</xenc:OAEPparams>
|
||||
</EncryptionMethod>
|
||||
</KeyDescriptor>
|
||||
<Organization>
|
||||
<Extensions>
|
||||
</Extensions>
|
||||
<OrganizationName xml:lang="en-US">string</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en-US">string</OrganizationDisplayName>
|
||||
<OrganizationURL xml:lang="en-US">http://www.example.com/</OrganizationURL>
|
||||
</Organization>
|
||||
<ContactPerson contactType="technical">
|
||||
<Extensions>...</Extensions>
|
||||
<Company>string</Company>
|
||||
<GivenName>string</GivenName>
|
||||
<SurName>string</SurName>
|
||||
<EmailAddress>http://www.example.com/</EmailAddress>
|
||||
<TelephoneNumber>string</TelephoneNumber>
|
||||
</ContactPerson>
|
||||
<AuthnQueryService Binding="http://www.example.com/" Location="http://www.example.com/">...</AuthnQueryService>
|
||||
<AssertionIDRequestService Binding="http://www.example.com/" Location="http://www.example.com/">...</AssertionIDRequestService>
|
||||
<NameIDFormat>http://www.example.com/</NameIDFormat>
|
||||
</AuthnAuthorityDescriptor>
|
||||
<Organization>
|
||||
<OrganizationName xml:lang="en">Identity Providers R
|
||||
US</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en">
|
||||
Identity Providers R US, a Division of Lerxst Corp.
|
||||
</OrganizationDisplayName>
|
||||
<OrganizationURL
|
||||
xml:lang="en">https://IdentityProvider.com</OrganizationURL>
|
||||
</Organization>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,101 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
entityID="https://IdentityProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<IDPSSODescriptor WantAuthnRequestsSigned="true"
|
||||
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
<KeyDescriptor use="signing">
|
||||
<ds:KeyInfo>
|
||||
<ds:KeyName>IdentityProvider.com SSO Key</ds:KeyName>
|
||||
</ds:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
<ArtifactResolutionService isDefault="true" index="0"
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
|
||||
Location="https://IdentityProvider.com/SAML/Artifact"/>
|
||||
<SingleLogoutService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
|
||||
Location="https://IdentityProvider.com/SAML/SLO/SOAP"/>
|
||||
<SingleLogoutService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
|
||||
Location="https://IdentityProvider.com/SAML/SLO/Browser"
|
||||
ResponseLocation="https://IdentityProvider.com/SAML/SLO/Response"/>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
|
||||
</NameIDFormat>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
|
||||
</NameIDFormat>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:2.0:nameid-format:transient
|
||||
</Invalid-end-tag>
|
||||
<SingleSignOnService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
|
||||
Location="https://IdentityProvider.com/SAML/SSO/Browser"/>
|
||||
<SingleSignOnService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||
Location="https://IdentityProvider.com/SAML/SSO/Browser"/>
|
||||
<saml:Attribute
|
||||
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6"
|
||||
FriendlyName="eduPersonPrincipalName">
|
||||
</saml:Attribute>
|
||||
<saml:Attribute
|
||||
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"
|
||||
FriendlyName="eduPersonAffiliation">
|
||||
<saml:AttributeValue>member</saml:AttributeValue>
|
||||
<saml:AttributeValue>student</saml:AttributeValue>
|
||||
<saml:AttributeValue>faculty</saml:AttributeValue>
|
||||
<saml:AttributeValue>employee</saml:AttributeValue>
|
||||
<saml:AttributeValue>staff</saml:AttributeValue>
|
||||
</saml:Attribute>
|
||||
</IDPSSODescriptor>
|
||||
<AttributeAuthorityDescriptor
|
||||
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||
<KeyDescriptor use="signing">
|
||||
<ds:KeyInfo>
|
||||
<ds:KeyName>IdentityProvider.com AA Key</ds:KeyName>
|
||||
</ds:KeyInfo>
|
||||
</KeyDescriptor>
|
||||
<AttributeService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
|
||||
Location="https://IdentityProvider.com/SAML/AA/SOAP"/>
|
||||
<AssertionIDRequestService
|
||||
Binding="urn:oasis:names:tc:SAML:2.0:bindings:URI"
|
||||
Location="https://IdentityProvider.com/SAML/AA/URI"/>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
|
||||
</NameIDFormat>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
|
||||
</NameIDFormat>
|
||||
<NameIDFormat>
|
||||
urn:oasis:names:tc:SAML:2.0:nameid-format:transient
|
||||
</NameIDFormat>
|
||||
<saml:Attribute
|
||||
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6"
|
||||
FriendlyName="eduPersonPrincipalName">
|
||||
</saml:Attribute>
|
||||
<saml:Attribute
|
||||
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
|
||||
Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"
|
||||
FriendlyName="eduPersonAffiliation">
|
||||
<saml:AttributeValue>member</saml:AttributeValue>
|
||||
<saml:AttributeValue>student</saml:AttributeValue>
|
||||
<saml:AttributeValue>faculty</saml:AttributeValue>
|
||||
<saml:AttributeValue>employee</saml:AttributeValue>
|
||||
<saml:AttributeValue>staff</saml:AttributeValue>
|
||||
</saml:Attribute>
|
||||
</AttributeAuthorityDescriptor>
|
||||
<Organization>
|
||||
<OrganizationName xml:lang="en">Identity Providers R
|
||||
US</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en">
|
||||
Identity Providers R US, a Division of Lerxst Corp.
|
||||
</OrganizationDisplayName>
|
||||
<OrganizationURL
|
||||
xml:lang="en">https://IdentityProvider.com</OrganizationURL>
|
||||
</Organization>
|
||||
</EntityDescriptor>
|
|
@ -0,0 +1,58 @@
|
|||
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
|
||||
entityID="https://IdentityProvider.com/SAML">
|
||||
<ds:Signature>...</ds:Signature>
|
||||
<PDPDescriptor ID="ID" protocolSupportEnumeration="http://www.example.com/ http://www.example.com/">
|
||||
<ds:Signature>
|
||||
<ds:SignedInfo>
|
||||
<ds:CanonicalizationMethod Algorithm="http://www.example.com/">...</ds:CanonicalizationMethod>
|
||||
<ds:SignatureMethod Algorithm="http://www.example.com/">...</ds:SignatureMethod>
|
||||
<ds:Reference URI="http://www.example.com/">...</ds:Reference>
|
||||
</ds:SignedInfo>
|
||||
<ds:SignatureValue>GpM7</ds:SignatureValue>
|
||||
<ds:KeyInfo>
|
||||
<ds:KeyName>string</ds:KeyName>
|
||||
</ds:KeyInfo>
|
||||
<ds:Object>Any text, intermingled with:</ds:Object>
|
||||
</ds:Signature>
|
||||
<Extensions>
|
||||
</Extensions>
|
||||
<KeyDescriptor>
|
||||
<ds:KeyInfo>
|
||||
<ds:KeyName>string</ds:KeyName>
|
||||
</ds:KeyInfo>
|
||||
<EncryptionMethod Algorithm="http://www.example.com/">
|
||||
<xenc:KeySize>1</xenc:KeySize>
|
||||
<xenc:OAEPparams>GpM7</xenc:OAEPparams>
|
||||
</EncryptionMethod>
|
||||
</KeyDescriptor>
|
||||
<Organization>
|
||||
<OrganizationName xml:lang="en-US">string</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en-US">string</OrganizationDisplayName>
|
||||
<OrganizationURL xml:lang="en-US">http://www.example.com/</OrganizationURL>
|
||||
</Organization>
|
||||
<ContactPerson contactType="technical">
|
||||
<Company>string</Company>
|
||||
<GivenName>string</GivenName>
|
||||
<SurName>string</SurName>
|
||||
<EmailAddress>http://www.example.com/</EmailAddress>
|
||||
<TelephoneNumber>string</TelephoneNumber>
|
||||
</ContactPerson>
|
||||
<AuthzService Binding="http://www.example.com/" Location="http://www.example.com/">
|
||||
</AuthzService>
|
||||
<AssertionIDRequestService Binding="http://www.example.com/" Location="http://www.example.com/">
|
||||
</AssertionIDRequestService>
|
||||
<NameIDFormat>http://www.example.com/</NameIDFormat>
|
||||
</PDPDescriptor>
|
||||
<Organization>
|
||||
<OrganizationName xml:lang="en">Identity Providers R
|
||||
US</OrganizationName>
|
||||
<OrganizationDisplayName xml:lang="en">
|
||||
Identity Providers R US, a Division of Lerxst Corp.
|
||||
</OrganizationDisplayName>
|
||||
<OrganizationURL
|
||||
xml:lang="en">https://IdentityProvider.com</OrganizationURL>
|
||||
</Organization>
|
||||
</EntityDescriptor>
|
Loading…
Reference in a new issue