[KEYCLOAK-6412] - Handle Proxy Restriction Tag incl. Test

This commit is contained in:
Patric Vormstein 2018-03-21 14:41:47 +01:00 committed by Hynek Mlnařík
parent bb3c76a9d9
commit fe98c30077
5 changed files with 145 additions and 0 deletions

View file

@ -64,6 +64,7 @@ public enum SAMLAssertionQNames implements HasQName {
// Attribute names // Attribute names
ATTR_ADDRESS(null, "Address"), ATTR_ADDRESS(null, "Address"),
ATTR_AUTHN_INSTANT(null, "AuthnInstant"), ATTR_AUTHN_INSTANT(null, "AuthnInstant"),
ATTR_COUNT(null, "Count"),
ATTR_DNS_NAME(null, "DNSName"), ATTR_DNS_NAME(null, "DNSName"),
ATTR_FORMAT(null, "Format"), ATTR_FORMAT(null, "Format"),
ATTR_FRIENDLY_NAME(null, "FriendlyName"), ATTR_FRIENDLY_NAME(null, "FriendlyName"),

View file

@ -19,6 +19,7 @@ package org.keycloak.saml.processing.core.parsers.saml.assertion;
import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType; import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType;
import org.keycloak.dom.saml.v2.assertion.ConditionsType; import org.keycloak.dom.saml.v2.assertion.ConditionsType;
import org.keycloak.dom.saml.v2.assertion.OneTimeUseType; import org.keycloak.dom.saml.v2.assertion.OneTimeUseType;
import org.keycloak.dom.saml.v2.assertion.ProxyRestrictionType;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.common.util.StaxParserUtil;
import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLEventReader;
@ -64,6 +65,11 @@ public class SAMLConditionsParser extends AbstractStaxSamlAssertionParser<Condit
target.addCondition(oneTimeUseCondition); target.addCondition(oneTimeUseCondition);
break; break;
case PROXY_RESTRICTION:
ProxyRestrictionType proxyRestriction = SAMLProxyRestrictionParser.getInstance().parse(xmlEventReader);
target.addCondition(proxyRestriction);
break;
default: default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation()); throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
} }

View file

@ -0,0 +1,55 @@
package org.keycloak.saml.processing.core.parsers.saml.assertion;
import org.keycloak.dom.saml.v2.assertion.ProxyRestrictionType;
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 java.net.URI;
/**
* Parse the <ProxyRestriction Count=\"\"> tag
*
* @author Patric Vormstein
* @since 21.03.2018
*/
public class SAMLProxyRestrictionParser extends AbstractStaxSamlAssertionParser<ProxyRestrictionType> {
private static final SAMLProxyRestrictionParser INSTANCE = new SAMLProxyRestrictionParser();
public SAMLProxyRestrictionParser() {
super(SAMLAssertionQNames.PROXY_RESTRICTION);
}
public static SAMLProxyRestrictionParser getInstance() {
return INSTANCE;
}
@Override
protected ProxyRestrictionType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
ProxyRestrictionType proxyRestriction = new ProxyRestrictionType();
Integer count = StaxParserUtil.getIntegerAttributeValue(element, SAMLAssertionQNames.ATTR_COUNT);
if (count != null) {
proxyRestriction.setCount(BigInteger.valueOf(count));
}
return proxyRestriction;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, ProxyRestrictionType target, SAMLAssertionQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case AUDIENCE:
StaxParserUtil.advance(xmlEventReader);
String audienceValue = StaxParserUtil.getElementText(xmlEventReader);
target.addAudience(URI.create(audienceValue));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -279,6 +279,11 @@ public class SAMLParserTest {
assertParsed("KEYCLOAK-4040-sharefile-metadata.xml", EntityDescriptorType.class); assertParsed("KEYCLOAK-4040-sharefile-metadata.xml", EntityDescriptorType.class);
} }
@Test
public void testProxyRestrictionTagHandling() throws Exception {
assertParsed("KEYCLOAK-6412-response-with-proxy-restriction.xml", ResponseType.class);
}
@Test @Test
public void testSaml20MetadataEntityDescriptorIdP() throws Exception { public void testSaml20MetadataEntityDescriptorIdP() throws Exception {
EntityDescriptorType entityDescriptor = assertParsed("saml20-entity-descriptor-idp.xml", EntityDescriptorType.class); EntityDescriptorType entityDescriptor = assertParsed("saml20-entity-descriptor-idp.xml", EntityDescriptorType.class);

View file

@ -0,0 +1,78 @@
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" Consent="urn:oasis:names:tc:SAML:2.0:consent:obtained" Destination="http://localhost:8080/auth/realms/ECAS/broker/saml/endpoint" ID="_11fb0d9a-26ea-4105-ba35-67d184456c55" InResponseTo="ID_abd144a0-9cd8-43cd-9c7c-861b6aa48755" IssueInstant="2018-01-29T14:45:47.774Z" Version="2.0">
<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://joe-docker:7002/cas/login</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<ds:Reference URI="#_11fb0d9a-26ea-4105-ba35-67d184456c55">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs" />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>[omitted]</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>[ommitted]</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509SubjectName>[ommitted]</ds:X509SubjectName>
<ds:X509Certificate>[ommitted]</ds:X509Certificate>
<ds:X509Certificate>[ommitted]</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
<saml2p:StatusMessage>Successful ECAS authentication</saml2p:StatusMessage>
</saml2p:Status>
<saml2:Assertion ID="_90dc4b3e-77a2-461d-90ce-9b1960f91eb5" IssueInstant="2018-01-29T14:45:47.774Z" Version="2.0">
<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://joe-docker:7002/cas/login</saml2:Issuer>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">chucknorris</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData InResponseTo="ID_abd144a0-9cd8-43cd-9c7c-861b6aa48755" NotOnOrAfter="2018-01-29T15:15:47.774Z" Recipient="http://localhost:8080/auth/realms/ECAS/broker/saml/endpoint" />
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2018-01-29T14:15:47.774Z" NotOnOrAfter="2018-01-29T15:15:47.774Z">
<saml2:AudienceRestriction>
<saml2:Audience>http://localhost:8080/auth/realms/ECAS</saml2:Audience>
</saml2:AudienceRestriction>
<saml2:OneTimeUse />
<saml2:ProxyRestriction Count="0" />
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2018-01-29T14:45:47.774Z" SessionIndex="_5d64dcef-5e81-496f-bfad-0109b0a5c2f0" SessionNotOnOrAfter="2018-01-29T15:15:47.774Z">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
<saml2:AttributeStatement>
<saml2:Attribute FriendlyName="Organisation" Name="domain" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">eu.europa.ec</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute FriendlyName="Organisation Username" Name="domainUsername" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">chucknorris</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute FriendlyName="Email" Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">texasranger@chuck_norris.com.eu</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute FriendlyName="First Name" Name="firstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Chuck</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute FriendlyName="Groups" Name="groups" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">INTERNET</saml2:AttributeValue>
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">DG_DIGIT</saml2:AttributeValue>
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">LIVENEWS</saml2:AttributeValue>
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">TEXAS_RANGER</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute FriendlyName="Last Name" Name="lastName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">NORRIS</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute FriendlyName="User Identifier" Name="user" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">chucknorris</saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
</saml2:Assertion>
</saml2p:Response>