KEYCLOAK-6473 KEYCLOAK-6472 SAML parser refactor + protocol parsers

This commit is contained in:
Hynek Mlnarik 2018-01-29 15:17:43 +01:00 committed by Hynek Mlnařík
parent 898347366d
commit e7cdb8ad54
117 changed files with 4747 additions and 3060 deletions

View file

@ -61,7 +61,7 @@ public class IDPXmlParser extends AbstractParser {
break; break;
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader); EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader);
String endElementName = StaxParserUtil.getEndElementName(endElement); String endElementName = StaxParserUtil.getElementName(endElement);
if (endElementName.equals(ConfigXmlConstants.IDP_ELEMENT)) if (endElementName.equals(ConfigXmlConstants.IDP_ELEMENT))
break; break;
else else
@ -70,7 +70,7 @@ public class IDPXmlParser extends AbstractParser {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(ConfigXmlConstants.SINGLE_SIGN_ON_SERVICE_ELEMENT)) { if (tag.equals(ConfigXmlConstants.SINGLE_SIGN_ON_SERVICE_ELEMENT)) {
IDP.SingleSignOnService sso = parseSingleSignOnService(xmlEventReader, signaturesRequired); IDP.SingleSignOnService sso = parseSingleSignOnService(xmlEventReader, signaturesRequired);
idp.setSingleSignOnService(sso); idp.setSingleSignOnService(sso);
@ -142,22 +142,18 @@ public class IDPXmlParser extends AbstractParser {
break; break;
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader); EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader);
String endElementName = StaxParserUtil.getEndElementName(endElement); String endElementName = StaxParserUtil.getElementName(endElement);
if (endElementName.equals(ConfigXmlConstants.ROLE_IDENTIFIERS_ELEMENT)) if (endElementName.equals(ConfigXmlConstants.ROLE_IDENTIFIERS_ELEMENT))
break; break;
else else
continue; continue;
} }
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
StaxParserUtil.bypassElementBlock(xmlEventReader, tag); StaxParserUtil.bypassElementBlock(xmlEventReader, tag);
} }
return config; return config;
} }
@Override
public boolean supports(QName qname) {
return false;
}
} }

View file

@ -47,16 +47,16 @@ public class KeyXmlParser extends AbstractParser {
break; break;
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader); EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader);
String endElementName = StaxParserUtil.getEndElementName(endElement); String endElementName = StaxParserUtil.getElementName(endElement);
if (endElementName.equals(ConfigXmlConstants.KEY_ELEMENT)) if (endElementName.equals(ConfigXmlConstants.KEY_ELEMENT))
break; break;
else else
throw logger.parserUnknownEndElement(endElementName); throw logger.parserUnknownEndElement(endElementName, xmlEvent.getLocation());
} }
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(ConfigXmlConstants.KEYS_STORE_ELEMENT)) { if (tag.equals(ConfigXmlConstants.KEYS_STORE_ELEMENT)) {
key.setKeystore(parseKeyStore(xmlEventReader)); key.setKeystore(parseKeyStore(xmlEventReader));
} else if (tag.equals(ConfigXmlConstants.CERTIFICATE_PEM_ELEMENT)) { } else if (tag.equals(ConfigXmlConstants.CERTIFICATE_PEM_ELEMENT)) {
@ -100,7 +100,7 @@ public class KeyXmlParser extends AbstractParser {
break; break;
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader); EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader);
String endElementName = StaxParserUtil.getEndElementName(endElement); String endElementName = StaxParserUtil.getElementName(endElement);
if (endElementName.equals(ConfigXmlConstants.KEYS_STORE_ELEMENT)) if (endElementName.equals(ConfigXmlConstants.KEYS_STORE_ELEMENT))
break; break;
else else
@ -109,7 +109,7 @@ public class KeyXmlParser extends AbstractParser {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(ConfigXmlConstants.CERTIFICATE_ELEMENT)) { if (tag.equals(ConfigXmlConstants.CERTIFICATE_ELEMENT)) {
StartElement element = StaxParserUtil.getNextStartElement(xmlEventReader); StartElement element = StaxParserUtil.getNextStartElement(xmlEventReader);
keyStore.setCertificateAlias(SPXmlParser.getAttributeValue(element, ConfigXmlConstants.ALIAS_ATTR)); keyStore.setCertificateAlias(SPXmlParser.getAttributeValue(element, ConfigXmlConstants.ALIAS_ATTR));
@ -138,8 +138,4 @@ public class KeyXmlParser extends AbstractParser {
} }
@Override
public boolean supports(QName qname) {
return false;
}
} }

View file

@ -42,7 +42,7 @@ public class KeycloakSamlAdapterXMLParser extends AbstractParser {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(ConfigXmlConstants.SP_ELEMENT)) { if (tag.equals(ConfigXmlConstants.SP_ELEMENT)) {
SPXmlParser parser = new SPXmlParser(); SPXmlParser parser = new SPXmlParser();
SP sp = (SP)parser.parse(xmlEventReader); SP sp = (SP)parser.parse(xmlEventReader);
@ -55,8 +55,4 @@ public class KeycloakSamlAdapterXMLParser extends AbstractParser {
return adapter; return adapter;
} }
@Override
public boolean supports(QName qname) {
return false;
}
} }

View file

@ -47,16 +47,16 @@ public class KeysXmlParser extends AbstractParser {
break; break;
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader); EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader);
String endElementName = StaxParserUtil.getEndElementName(endElement); String endElementName = StaxParserUtil.getElementName(endElement);
if (endElementName.equals(ConfigXmlConstants.KEYS_ELEMENT)) if (endElementName.equals(ConfigXmlConstants.KEYS_ELEMENT))
break; break;
else else
throw logger.parserUnknownEndElement(endElementName); throw logger.parserUnknownEndElement(endElementName, xmlEvent.getLocation());
} }
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(ConfigXmlConstants.KEY_ELEMENT)) { if (tag.equals(ConfigXmlConstants.KEY_ELEMENT)) {
KeyXmlParser parser = new KeyXmlParser(); KeyXmlParser parser = new KeyXmlParser();
Key key = (Key)parser.parse(xmlEventReader); Key key = (Key)parser.parse(xmlEventReader);
@ -69,8 +69,4 @@ public class KeysXmlParser extends AbstractParser {
return keys; return keys;
} }
@Override
public boolean supports(QName qname) {
return false;
}
} }

View file

@ -97,7 +97,7 @@ public class SPXmlParser extends AbstractParser {
break; break;
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader); EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader);
String endElementName = StaxParserUtil.getEndElementName(endElement); String endElementName = StaxParserUtil.getElementName(endElement);
if (endElementName.equals(ConfigXmlConstants.SP_ELEMENT)) if (endElementName.equals(ConfigXmlConstants.SP_ELEMENT))
break; break;
else else
@ -106,7 +106,7 @@ public class SPXmlParser extends AbstractParser {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(ConfigXmlConstants.KEYS_ELEMENT)) { if (tag.equals(ConfigXmlConstants.KEYS_ELEMENT)) {
KeysXmlParser parser = new KeysXmlParser(); KeysXmlParser parser = new KeysXmlParser();
List<Key> keys = (List<Key>) parser.parse(xmlEventReader); List<Key> keys = (List<Key>) parser.parse(xmlEventReader);
@ -148,7 +148,7 @@ public class SPXmlParser extends AbstractParser {
break; break;
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader); EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader);
String endElementName = StaxParserUtil.getEndElementName(endElement); String endElementName = StaxParserUtil.getElementName(endElement);
if (endElementName.equals(ConfigXmlConstants.ROLE_IDENTIFIERS_ELEMENT)) if (endElementName.equals(ConfigXmlConstants.ROLE_IDENTIFIERS_ELEMENT))
break; break;
else else
@ -157,7 +157,7 @@ public class SPXmlParser extends AbstractParser {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(ConfigXmlConstants.ATTRIBUTE_ELEMENT)) { if (tag.equals(ConfigXmlConstants.ATTRIBUTE_ELEMENT)) {
StartElement element = StaxParserUtil.getNextStartElement(xmlEventReader); StartElement element = StaxParserUtil.getNextStartElement(xmlEventReader);
String attributeValue = getAttributeValue(element, ConfigXmlConstants.NAME_ATTR); String attributeValue = getAttributeValue(element, ConfigXmlConstants.NAME_ATTR);
@ -174,8 +174,4 @@ public class SPXmlParser extends AbstractParser {
sp.setRoleAttributes(roleAttributes); sp.setRoleAttributes(roleAttributes);
} }
@Override
public boolean supports(QName qname) {
return false;
}
} }

View file

@ -16,65 +16,309 @@
*/ */
package org.keycloak.saml.common.constants; package org.keycloak.saml.common.constants;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.*;
/** /**
* SAML Constants * SAML Constants
* *
* @author Anil.Saldhana@redhat.com
* @since Dec 10, 2008 * @since Dec 10, 2008
*/ */
public enum JBossSAMLConstants { public enum JBossSAMLConstants {
ADDRESS("Address"), ADVICE("Advice"), ADDITIONAL_METADATA_LOCATION("AdditionalMetadataLocation"), AFFILIATION_DESCRIPTOR( // saml-schema-protocol-2.0.xsd
"AffiliationDescriptor"), ALLOW_CREATE("AllowCreate"), ARTIFACT("Artifact"), ARTIFACT_RESOLVE("ArtifactResolve"), ARTIFACT_RESPONSE( ARTIFACT(PROTOCOL_NSURI, "Artifact"),
"ArtifactResponse"), ARTIFACT_RESOLUTION_SERVICE("ArtifactResolutionService"), ASSERTION("Assertion"), ASSERTION_CONSUMER_SERVICE( ARTIFACT_RESOLVE(PROTOCOL_NSURI, "ArtifactResolve"),
"AssertionConsumerService"), ASSERTION_CONSUMER_SERVICE_URL("AssertionConsumerServiceURL"), ASSERTION_CONSUMER_SERVICE_INDEX( ARTIFACT_RESPONSE(PROTOCOL_NSURI, "ArtifactResponse"),
"AssertionConsumerServiceIndex"), ASSERTION_ID_REQUEST_SERVICE("AssertionIDRequestService"), ATTRIBUTE("Attribute"), ATTRIBUTE_QUERY( ASSERTION_ID_REQUEST(PROTOCOL_NSURI, "AssertionIDRequest"),
"AttributeQuery"), ATTRIBUTE_AUTHORITY_DESCRIPTOR("AttributeAuthorityDescriptor"), ATTRIBUTE_CONSUMING_SERVICE( ATTRIBUTE_QUERY(PROTOCOL_NSURI, "AttributeQuery"),
"AttributeConsumingService"), ATTRIBUTE_CONSUMING_SERVICE_INDEX("AttributeConsumingServiceIndex"), ATTRIBUTE_PROFILE("AttributeProfile"), ATTRIBUTE_SERVICE( AUTHN_QUERY(PROTOCOL_NSURI, "AuthnQuery"),
"AttributeService"), ATTRIBUTE_STATEMENT("AttributeStatement"), ATTRIBUTE_VALUE("AttributeValue"), AUDIENCE( AUTHN_REQUEST(PROTOCOL_NSURI, "AuthnRequest"),
"Audience"), AUDIENCE_RESTRICTION("AudienceRestriction"), AUTHN_CONTEXT("AuthnContext"), AUTHENTICATING_AUTHORITY( AUTHZ_DECISION_QUERY(PROTOCOL_NSURI, "AuthzDecisionQuery"),
"AuthenticatingAuthority"), AUTHN_AUTHORITY_DESCRIPTOR("AuthnAuthorityDescriptor"), AUTHN_CONTEXT_CLASS_REF( EXTENSIONS__PROTOCOL(PROTOCOL_NSURI, "Extensions"),
"AuthnContextClassRef"), AUTHN_CONTEXT_DECLARATION("AuthnContextDecl"), AUTHN_CONTEXT_DECLARATION_REF( GET_COMPLETE(PROTOCOL_NSURI, "GetComplete"),
"AuthnContextDeclRef"), AUTHN_INSTANT("AuthnInstant"), AUTHN_REQUEST("AuthnRequest"), AUTHN_STATEMENT( IDP_ENTRY(PROTOCOL_NSURI, "IDPEntry"),
"AuthnStatement"), AUTHN_REQUESTS_SIGNED("AuthnRequestsSigned"), BASEID("BaseID"), BINDING("Binding"), CACHE_DURATION( IDP_LIST(PROTOCOL_NSURI, "IDPList"),
"cacheDuration"), COMPANY("Company"), CONDITIONS("Conditions"), COMPARISON("Comparison"), CONSENT("Consent"), CONTACT_PERSON("ContactPerson"), CONTACT_TYPE( LOGOUT_REQUEST(PROTOCOL_NSURI, "LogoutRequest"),
"contactType"), DESTINATION("Destination"), DNS_NAME("DNSName"), EMAIL_ADDRESS("EmailAddress"), ENCODING("Encoding"), ENCRYPTED_ASSERTION( LOGOUT_RESPONSE(PROTOCOL_NSURI, "LogoutResponse"),
"EncryptedAssertion"), ENCRYPTED_ID("EncryptedID"), ENTITY_ID("entityID"), ENTITY_DESCRIPTOR("EntityDescriptor"), ENTITIES_DESCRIPTOR( MANAGE_NAMEID_REQUEST(PROTOCOL_NSURI, "ManageNameIDRequest"),
"EntitiesDescriptor"), EXTENSIONS("Extensions"), FORMAT("Format"), FRIENDLY_NAME("FriendlyName"), FORCE_AUTHN( MANAGE_NAMEID_RESPONSE(PROTOCOL_NSURI, "ManageNameIDResponse"),
"ForceAuthn"), GIVEN_NAME("GivenName"), ID("ID"), IDP_SSO_DESCRIPTOR("IDPSSODescriptor"), INDEX("index"), INPUT_CONTEXT_ONLY( NAMEID_MAPPING_REQUEST(PROTOCOL_NSURI, "NameIDMappingRequest"),
"InputContextOnly"), IN_RESPONSE_TO("InResponseTo"), ISDEFAULT("isDefault"), IS_REQUIRED("isRequired"), IS_PASSIVE( NAMEID_MAPPING_RESPONSE(PROTOCOL_NSURI, "NameIDMappingResponse"),
"IsPassive"), ISSUE_INSTANT("IssueInstant"), ISSUER("Issuer"), KEY_DESCRIPTOR("KeyDescriptor"), KEY_INFO("KeyInfo"), ENCRYPTION_METHOD("EncryptionMethod"), LANG( NAMEID_POLICY(PROTOCOL_NSURI, "NameIDPolicy"),
"lang"), LANG_EN("en"), LOCATION("Location"), LOGOUT_REQUEST("LogoutRequest"), LOGOUT_RESPONSE("LogoutResponse"), MANAGE_NAMEID_SERVICE( NEW_ENCRYPTEDID(PROTOCOL_NSURI, "NewEncryptedID"),
"ManageNameIDService"), METADATA_MIME("application/samlmetadata+xml"), METHOD("Method"), NAME("Name"), NAME_FORMAT( NEWID(PROTOCOL_NSURI, "NewID"),
"NameFormat"), NAMEID("NameID"), NAMEID_FORMAT("NameIDFormat"), NAMEID_MAPPING_SERVICE("NameIDMappingService"), NAMEID_POLICY( REQUESTED_AUTHN_CONTEXT(PROTOCOL_NSURI, "RequestedAuthnContext"),
"NameIDPolicy"), NAME_QUALIFIER("NameQualifier"), NOT_BEFORE("NotBefore"), NOT_ON_OR_AFTER("NotOnOrAfter"), ORGANIZATION( REQUESTERID(PROTOCOL_NSURI, "RequesterID"),
"Organization"), ORGANIZATION_NAME("OrganizationName"), ORGANIZATION_DISPLAY_NAME("OrganizationDisplayName"), ORGANIZATION_URL( RESPONSE__PROTOCOL(PROTOCOL_NSURI, "Response"),
"OrganizationURL"), ORGANIZATION_URL_ALT( SCOPING(PROTOCOL_NSURI, "Scoping"),
"OrganizationUrl"), PDP_DESCRIPTOR("PDPDescriptor"), PROTOCOL_BINDING("ProtocolBinding"), PROTOCOL_SUPPORT_ENUMERATION( SESSION_INDEX(PROTOCOL_NSURI, "SessionIndex"),
"protocolSupportEnumeration"), PROVIDER_NAME("ProviderName"), REQUESTED_AUTHN_CONTEXT("RequestedAuthnContext"), REASON( STATUS_CODE(PROTOCOL_NSURI, "StatusCode"),
"Reason"), RECIPIENT("Recipient"), REQUEST("Request"), REQUESTED_ATTRIBUTE("RequestedAttribute"), REQUEST_ABSTRACT( STATUS_DETAIL(PROTOCOL_NSURI, "StatusDetail"),
"RequestAbstract"), RESPONSE("Response"), RESPONSE_LOCATION("ResponseLocation"), RETURN_CONTEXT("ReturnContext"), SCOPING("Scoping"), SESSION_INDEX( STATUS_MESSAGE(PROTOCOL_NSURI, "StatusMessage"),
"SessionIndex"), SERVICE_NAME("ServiceName"), SERVICE_DESCRIPTION("ServiceDescription"), SP_PROVIDED_ID( STATUS(PROTOCOL_NSURI, "Status"),
"SPProvidedID"), SP_NAME_QUALIFIER("SPNameQualifier"), SP_SSO_DESCRIPTOR("SPSSODescriptor"), SIGNATURE("Signature"), SIGNATURE_SHA1_WITH_DSA( SUBJECT_QUERY(PROTOCOL_NSURI, "SubjectQuery"),
"http://www.w3.org/2000/09/xmldsig#dsa-sha1"), SIGNATURE_SHA1_WITH_RSA("http://www.w3.org/2000/09/xmldsig#rsa-sha1"), SINGLE_SIGNON_SERVICE( TERMINATE(PROTOCOL_NSURI, "Terminate"),
"SingleSignOnService"), SINGLE_LOGOUT_SERVICE("SingleLogoutService"), STATEMENT("Statement"), STATUS("Status"), STATUS_CODE(
"StatusCode"), STATUS_DETAIL("StatusDetail"), STATUS_MESSAGE("StatusMessage"), STATUS_RESPONSE_TYPE(
"StatusResponseType"), SUBJECT("Subject"), SUBJECT_CONFIRMATION("SubjectConfirmation"), SUBJECT_CONFIRMATION_DATA(
"SubjectConfirmationData"), SUBJECT_LOCALITY("SubjectLocality"), SURNAME("SurName"), TELEPHONE_NUMBER(
"TelephoneNumber"), TYPE("type"), USE("use"), VALUE("Value"), VALID_UNTIL("validUntil"), VERSION("Version"), VERSION_2_0(
"2.0"), WANT_AUTHN_REQUESTS_SIGNED("WantAuthnRequestsSigned"), WANT_ASSERTIONS_SIGNED("WantAssertionsSigned"), XACML_AUTHZ_DECISION_QUERY(
"XACMLAuthzDecisionQuery"), XACML_AUTHZ_DECISION_QUERY_TYPE("XACMLAuthzDecisionQueryType"), XACML_AUTHZ_DECISION_STATEMENT_TYPE(
"XACMLAuthzDecisionStatementType"), HTTP_POST_BINDING("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"), ONE_TIME_USE ("OneTimeUse"),
UNSOLICITED_RESPONSE_TARGET("TARGET"), UNSOLICITED_RESPONSE_SAML_VERSION("SAML_VERSION"), UNSOLICITED_RESPONSE_SAML_BINDING("SAML_BINDING"),
ROLE_DESCRIPTOR("RoleDescriptor"),
REQUEST_AUTHENTICATED("RequestAuthenticated");
private String name; // saml-schema-assertion-2.0.xsd
ACTION(ASSERTION_NSURI, "Action"),
ADVICE(ASSERTION_NSURI, "Advice"),
ASSERTION(ASSERTION_NSURI, "Assertion"),
ASSERTION_ID_REF(ASSERTION_NSURI, "AssertionIDRef"),
ASSERTION_URI_REF(ASSERTION_NSURI, "AssertionURIRef"),
ATTRIBUTE(ASSERTION_NSURI, "Attribute"),
ATTRIBUTE_STATEMENT(ASSERTION_NSURI, "AttributeStatement"),
ATTRIBUTE_VALUE(ASSERTION_NSURI, "AttributeValue"),
AUDIENCE(ASSERTION_NSURI, "Audience"),
AUDIENCE_RESTRICTION(ASSERTION_NSURI, "AudienceRestriction"),
AUTHENTICATING_AUTHORITY(ASSERTION_NSURI, "AuthenticatingAuthority"),
AUTHN_CONTEXT(ASSERTION_NSURI, "AuthnContext"),
AUTHN_CONTEXT_CLASS_REF(ASSERTION_NSURI, "AuthnContextClassRef"),
AUTHN_CONTEXT_DECL(ASSERTION_NSURI, "AuthnContextDecl"),
AUTHN_CONTEXT_DECL_REF(ASSERTION_NSURI, "AuthnContextDeclRef"),
AUTHN_STATEMENT(ASSERTION_NSURI, "AuthnStatement"),
AUTHZ_DECISION_STATEMENT(ASSERTION_NSURI, "AuthzDecisionStatement"),
BASEID(ASSERTION_NSURI, "BaseID"),
CONDITION(ASSERTION_NSURI, "Condition"),
CONDITIONS(ASSERTION_NSURI, "Conditions"),
ENCRYPTED_ASSERTION(ASSERTION_NSURI, "EncryptedAssertion"),
ENCRYPTED_ATTRIBUTE(ASSERTION_NSURI, "EncryptedAttribute"),
ENCRYPTED_ID(ASSERTION_NSURI, "EncryptedID"),
EVIDENCE(ASSERTION_NSURI, "Evidence"),
ISSUER(ASSERTION_NSURI, "Issuer"),
NAMEID(ASSERTION_NSURI, "NameID"),
ONE_TIME_USE(ASSERTION_NSURI, "OneTimeUse"),
PROXY_RESTRICTION(ASSERTION_NSURI, "ProxyRestriction"),
STATEMENT(ASSERTION_NSURI, "Statement"),
SUBJECT_CONFIRMATION_DATA(ASSERTION_NSURI, "SubjectConfirmationData"),
SUBJECT_CONFIRMATION(ASSERTION_NSURI, "SubjectConfirmation"),
SUBJECT_LOCALITY(ASSERTION_NSURI, "SubjectLocality"),
SUBJECT(ASSERTION_NSURI, "Subject"),
private JBossSAMLConstants(String val) { // saml-schema-metadata-2.0.xsd
this.name = val; ADDITIONAL_METADATA_LOCATION(METADATA_NSURI, "AdditionalMetadataLocation"),
AFFILIATE_MEMBER(METADATA_NSURI, "AffiliateMember"),
AFFILIATION_DESCRIPTOR(METADATA_NSURI, "AffiliationDescriptor"),
ARTIFACT_RESOLUTION_SERVICE(METADATA_NSURI, "ArtifactResolutionService"),
ASSERTION_CONSUMER_SERVICE(METADATA_NSURI, "AssertionConsumerService"),
ASSERTION_ID_REQUEST_SERVICE(METADATA_NSURI, "AssertionIDRequestService"),
ATTRIBUTE_AUTHORITY_DESCRIPTOR(METADATA_NSURI, "AttributeAuthorityDescriptor"),
ATTRIBUTE_CONSUMING_SERVICE(METADATA_NSURI, "AttributeConsumingService"),
ATTRIBUTE_PROFILE(METADATA_NSURI, "AttributeProfile"),
ATTRIBUTE_SERVICE(METADATA_NSURI, "AttributeService"),
AUTHN_AUTHORITY_DESCRIPTOR(METADATA_NSURI, "AuthnAuthorityDescriptor"),
AUTHN_QUERY_SERVICE(METADATA_NSURI, "AuthnQueryService"),
AUTHZ_SERVICE(METADATA_NSURI, "AuthzService"),
COMPANY(METADATA_NSURI, "Company"),
CONTACT_PERSON(METADATA_NSURI, "ContactPerson"),
EMAIL_ADDRESS(METADATA_NSURI, "EmailAddress"),
ENCRYPTION_METHOD(METADATA_NSURI, "EncryptionMethod"),
ENTITIES_DESCRIPTOR(METADATA_NSURI, "EntitiesDescriptor"),
ENTITY_DESCRIPTOR(METADATA_NSURI, "EntityDescriptor"),
EXTENSIONS__METADATA(METADATA_NSURI, "Extensions"),
GIVEN_NAME(METADATA_NSURI, "GivenName"),
IDP_SSO_DESCRIPTOR(METADATA_NSURI, "IDPSSODescriptor"),
KEY_DESCRIPTOR(METADATA_NSURI, "KeyDescriptor"),
MANAGE_NAMEID_SERVICE(METADATA_NSURI, "ManageNameIDService"),
NAMEID_FORMAT(METADATA_NSURI, "NameIDFormat"),
NAMEID_MAPPING_SERVICE(METADATA_NSURI, "NameIDMappingService"),
ORGANIZATION_DISPLAY_NAME(METADATA_NSURI, "OrganizationDisplayName"),
ORGANIZATION_NAME(METADATA_NSURI, "OrganizationName"),
ORGANIZATION(METADATA_NSURI, "Organization"),
ORGANIZATION_URL(METADATA_NSURI, "OrganizationURL"),
ORGANIZATION_URL_ALT(METADATA_NSURI, "OrganizationUrl"), // non-standard: KEYCLOAK-4040
PDP_DESCRIPTOR(METADATA_NSURI, "PDPDescriptor"),
REQUESTED_ATTRIBUTE(METADATA_NSURI, "RequestedAttribute"),
ROLE_DESCRIPTOR(METADATA_NSURI, "RoleDescriptor"),
SERVICE_DESCRIPTION(METADATA_NSURI, "ServiceDescription"),
SERVICE_NAME(METADATA_NSURI, "ServiceName"),
SINGLE_LOGOUT_SERVICE(METADATA_NSURI, "SingleLogoutService"),
SINGLE_SIGNON_SERVICE(METADATA_NSURI, "SingleSignOnService"),
SP_SSO_DESCRIPTOR(METADATA_NSURI, "SPSSODescriptor"),
SURNAME(METADATA_NSURI, "SurName"),
TELEPHONE_NUMBER(METADATA_NSURI, "TelephoneNumber"),
// saml-schema-ecp-2.0.xsd
RELAY_STATE(ECP_PROFILE, "RelayState"),
REQUEST(ECP_PROFILE, "Request"),
RESPONSE__ECP(ECP_PROFILE, "Response"),
SIGNATURE(XMLDSIG_NSURI, "Signature"),
DSA_KEY_VALUE(XMLDSIG_NSURI, "DSAKeyValue"),
KEY_INFO(XMLDSIG_NSURI, "KeyInfo"),
KEY_VALUE(XMLDSIG_NSURI, "KeyValue"),
RSA_KEY_VALUE(XMLDSIG_NSURI, "RSAKeyValue"),
X509_CERT(XMLDSIG_NSURI, "X509Certificate"),
X509_DATA(XMLDSIG_NSURI, "X509Data"),
// Attribute names and other constants
ADDRESS("Address"),
ALLOW_CREATE("AllowCreate"),
ASSERTION_CONSUMER_SERVICE_URL("AssertionConsumerServiceURL"),
ASSERTION_CONSUMER_SERVICE_INDEX("AssertionConsumerServiceIndex"),
ATTRIBUTE_CONSUMING_SERVICE_INDEX("AttributeConsumingServiceIndex"),
AUTHN_INSTANT("AuthnInstant"),
AUTHN_REQUESTS_SIGNED("AuthnRequestsSigned"),
BINDING("Binding"),
CACHE_DURATION("cacheDuration"),
COMPARISON("Comparison"),
CONSENT("Consent"),
CONTACT_TYPE("contactType"),
DESTINATION("Destination"),
DNS_NAME("DNSName"),
ENCODING("Encoding"),
ENCRYPTED_KEY("EncryptedKey"),
ENTITY_ID("entityID"),
FORMAT("Format"),
FRIENDLY_NAME("FriendlyName"),
FORCE_AUTHN("ForceAuthn"),
ID("ID"),
INDEX("index"),
INPUT_CONTEXT_ONLY("InputContextOnly"),
IN_RESPONSE_TO("InResponseTo"),
ISDEFAULT("isDefault"),
IS_REQUIRED("isRequired"),
IS_PASSIVE("IsPassive"),
ISSUE_INSTANT("IssueInstant"),
LOCATION("Location"),
METHOD("Method"),
NAME("Name"),
NAME_FORMAT("NameFormat"),
NAME_QUALIFIER("NameQualifier"),
NOT_BEFORE("NotBefore"),
NOT_ON_OR_AFTER("NotOnOrAfter"),
PROTOCOL_BINDING("ProtocolBinding"),
PROTOCOL_SUPPORT_ENUMERATION("protocolSupportEnumeration"),
PROVIDER_NAME("ProviderName"),
REASON("Reason"),
RECIPIENT("Recipient"),
REQUEST_ABSTRACT("RequestAbstract"),
RESPONSE_LOCATION("ResponseLocation"),
RETURN_CONTEXT("ReturnContext"),
SP_PROVIDED_ID("SPProvidedID"),
SP_NAME_QUALIFIER("SPNameQualifier"),
STATUS_RESPONSE_TYPE("StatusResponseType"),
TYPE("type"),
USE("use"),
VALUE("Value"),
VALID_UNTIL("validUntil"),
VERSION("Version"),
WANT_AUTHN_REQUESTS_SIGNED("WantAuthnRequestsSigned"),
WANT_ASSERTIONS_SIGNED("WantAssertionsSigned"),
XACML_AUTHZ_DECISION_QUERY("XACMLAuthzDecisionQuery"),
XACML_AUTHZ_DECISION_QUERY_TYPE("XACMLAuthzDecisionQueryType"),
XACML_AUTHZ_DECISION_STATEMENT_TYPE("XACMLAuthzDecisionStatementType"),
REQUEST_AUTHENTICATED("RequestAuthenticated"),
UNSOLICITED_RESPONSE_TARGET("TARGET"),
UNSOLICITED_RESPONSE_SAML_VERSION("SAML_VERSION"),
UNSOLICITED_RESPONSE_SAML_BINDING("SAML_BINDING"),
LANG("lang"),
LANG_EN("en"),
METADATA_MIME("application/samlmetadata+xml"),
SIGNATURE_SHA1_WITH_DSA("http://www.w3.org/2000/09/xmldsig#dsa-sha1"),
SIGNATURE_SHA1_WITH_RSA("http://www.w3.org/2000/09/xmldsig#rsa-sha1"),
VERSION_2_0("2.0"),
/** @deprecated Use namespace-aware variant instead */
RESPONSE("Response"),
/** @deprecated Use namespace-aware variant instead */
EXTENSIONS("Extensions"),
UNKNOWN_VALUE(null)
;
private final QName asQName;
private final JBossSAMLURIConstants nsUri;
private static class ReverseLookup {
// Private class to make sure JBossSAMLURIConstants is fully initialized
private static final Map<QName, JBossSAMLConstants> QNAME_CONSTANTS;
private static final Map<String, JBossSAMLConstants> CONSTANTS;
static {
HashMap<QName, JBossSAMLConstants> q = new HashMap<>(JBossSAMLConstants.values().length);
HashMap<String, JBossSAMLConstants> m = new HashMap<>(JBossSAMLConstants.values().length);
JBossSAMLConstants old;
for (JBossSAMLConstants c : JBossSAMLConstants.values()) {
if ((old = q.put(c.getAsQName(), c)) != null) {
throw new IllegalStateException("Same name " + c.getAsQName() + " used for two distinct constants: " + c + ", " + old);
}
String key = c.get();
if ((old = m.put(key, c)) != null) {
// System.out.println("WARNING: " + old);
if (old != null && c.getAsQName().equals(old.getAsQName())) {
throw new IllegalStateException("Same name " + key + " used for two distinct constants: " + c + ", " + old);
}
m.put(key, null);
}
}
QNAME_CONSTANTS = Collections.unmodifiableMap(q);
CONSTANTS = Collections.unmodifiableMap(m);
}
public JBossSAMLConstants from(String key) {
return CONSTANTS.get(key);
}
public JBossSAMLConstants from(QName key) {
return QNAME_CONSTANTS.get(key);
}
}
private static final ReverseLookup REVERSE_LOOKUP = new ReverseLookup();
private JBossSAMLConstants(String name) {
this.asQName = name == null ? null : new QName(name);
this.nsUri = null;
}
private JBossSAMLConstants(JBossSAMLURIConstants namespaceUri, String name) {
this.nsUri = namespaceUri;
this.asQName = name == null ? null : new QName(namespaceUri.get(), name);
} }
public String get() { public String get() {
return this.name; return this.asQName == null ? null : this.asQName.getLocalPart();
}
public QName getAsQName() {
return asQName;
}
public JBossSAMLURIConstants getNsUri() {
return nsUri;
}
/**
* Returns an enum constant based if known for the given {@code key}, or the {@code defaultValue} otherwise.
* @param key
* @return
*/
public static JBossSAMLConstants from(String key, JBossSAMLConstants defaultValue) {
final JBossSAMLConstants res = REVERSE_LOOKUP.from(key);
return res == null ? defaultValue : res;
}
/**
* Returns an enum constant based if known for the given {@code key}, or the {@code UNKNOWN_VALUE} otherwise.
* @param key
* @return
*/
public static JBossSAMLConstants from(String key) {
return from(key, UNKNOWN_VALUE);
}
/**
* Returns an enum constant based if known for the given {@code name} (namespace-aware), or the {@code UNKNOWN_VALUE} otherwise.
* @param key
* @return
*/
public static JBossSAMLConstants from(QName name) {
final JBossSAMLConstants res = REVERSE_LOOKUP.from(name);
return res == null ? UNKNOWN_VALUE : res;
} }
} }

View file

@ -16,6 +16,11 @@
*/ */
package org.keycloak.saml.common.constants; package org.keycloak.saml.common.constants;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/** /**
* Define the constants based on URI * Define the constants based on URI
* *
@ -23,60 +28,58 @@ package org.keycloak.saml.common.constants;
* @since Dec 10, 2008 * @since Dec 10, 2008
*/ */
public enum JBossSAMLURIConstants { public enum JBossSAMLURIConstants {
AC_PASSWORD_PROTECTED_TRANSPORT("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"), AC_PASSWORD( AC_PASSWORD_PROTECTED_TRANSPORT("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"),
"urn:oasis:names:tc:SAML:2.0:ac:classes:Password"), AC_TLS_CLIENT( AC_PASSWORD("urn:oasis:names:tc:SAML:2.0:ac:classes:Password"),
"urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient"), AC_PREVIOUS_SESSION( AC_TLS_CLIENT("urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient"),
"urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession"), AC_UNSPECIFIED( AC_PREVIOUS_SESSION("urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession"),
"urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified"), AC_IP( AC_UNSPECIFIED("urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified"),
"urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol"), AC_IP("urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol"),
ASSERTION_NSURI("urn:oasis:names:tc:SAML:2.0:assertion"), ATTRIBUTE_FORMAT_BASIC( ASSERTION_NSURI("urn:oasis:names:tc:SAML:2.0:assertion"),
"urn:oasis:names:tc:SAML:2.0:attrname-format:basic"), ATTRIBUTE_FORMAT_URI( ATTRIBUTE_FORMAT_BASIC("urn:oasis:names:tc:SAML:2.0:attrname-format:basic"),
"urn:oasis:names:tc:SAML:2.0:attrname-format:uri"), ATTRIBUTE_FORMAT_URI("urn:oasis:names:tc:SAML:2.0:attrname-format:uri"),
BEARER("urn:oasis:names:tc:SAML:2.0:cm:bearer"), CLAIMS_EMAIL_ADDRESS_2005("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"),
CLAIMS_EMAIL_ADDRESS("http://schemas.xmlsoap.org/claims/EmailAddress"),
CLAIMS_EMAIL_ADDRESS_2005("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"), CLAIMS_EMAIL_ADDRESS( CLAIMS_GIVEN_NAME("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"),
"http://schemas.xmlsoap.org/claims/EmailAddress"), CLAIMS_GIVEN_NAME( CLAIMS_NAME("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"),
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"), CLAIMS_NAME( CLAIMS_USER_PRINCIPAL_NAME_2005("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"),
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"), CLAIMS_USER_PRINCIPAL_NAME_2005( CLAIMS_USER_PRINCIPAL_NAME("http://schemas.xmlsoap.org/claims/UPN"),
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"), CLAIMS_USER_PRINCIPAL_NAME( CLAIMS_COMMON_NAME("http://schemas.xmlsoap.org/claims/CommonName"),
"http://schemas.xmlsoap.org/claims/UPN"), CLAIMS_COMMON_NAME("http://schemas.xmlsoap.org/claims/CommonName"), CLAIMS_GROUP( CLAIMS_GROUP("http://schemas.xmlsoap.org/claims/Group"),
"http://schemas.xmlsoap.org/claims/Group"), CLAIMS_ROLE( CLAIMS_ROLE("http://schemas.microsoft.com/ws/2008/06/identity/claims/role"),
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role"), CLAIMS_SURNAME( CLAIMS_SURNAME("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"),
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"), CLAIMS_PRIVATE_ID( CLAIMS_PRIVATE_ID("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier"),
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier"), CLAIMS_NAME_IDENTIFIER( CLAIMS_NAME_IDENTIFIER("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"),
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"), CLAIMS_AUTHENTICATION_METHOD( CLAIMS_AUTHENTICATION_METHOD("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod"),
"http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod"), CLAIMS_DENY_ONLY_GROUP_SID( CLAIMS_DENY_ONLY_GROUP_SID("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid"),
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid"), CLAIMS_DENY_ONLY_PRIMARY_SID( CLAIMS_DENY_ONLY_PRIMARY_SID("http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid"),
"http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid"), CLAIMS_DENY_ONLY_PRIMARY_GROUP_SID( CLAIMS_DENY_ONLY_PRIMARY_GROUP_SID("http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid"),
"http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid"), CLAIMS_GROUP_SID( CLAIMS_GROUP_SID("http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid"),
"http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid"), CLAIMS_PRIMARY_GROUP_SID( CLAIMS_PRIMARY_GROUP_SID("http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid"),
"http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid"), CLAIMS_PRIMARY_SID( CLAIMS_PRIMARY_SID("http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"),
"http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"), CLAIMS_WINDOWS_ACCOUNT_NAME( CLAIMS_WINDOWS_ACCOUNT_NAME("http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"),
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"), CLAIMS_PUID( CLAIMS_PUID("http://schemas.xmlsoap.org/claims/PUID"),
"http://schemas.xmlsoap.org/claims/PUID"),
HOLDER_OF_KEY("urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"), HOLDER_OF_KEY("urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"),
METADATA_NSURI("urn:oasis:names:tc:SAML:2.0:metadata"), METADATA_HTTP_REDIRECT_BINDING( METADATA_NSURI("urn:oasis:names:tc:SAML:2.0:metadata"),
"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"),
NAMEID_FORMAT_TRANSIENT("urn:oasis:names:tc:SAML:2.0:nameid-format:transient"), NAMEID_FORMAT_PERSISTENT( NAMEID_FORMAT_TRANSIENT("urn:oasis:names:tc:SAML:2.0:nameid-format:transient"),
"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"), NAMEID_FORMAT_UNSPECIFIED( NAMEID_FORMAT_PERSISTENT("urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"),
"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"), NAMEID_FORMAT_EMAIL( NAMEID_FORMAT_UNSPECIFIED("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"),
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"), NAMEID_FORMAT_X509SUBJECTNAME( NAMEID_FORMAT_EMAIL("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"),
"urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName"), NAMEID_FORMAT_WINDOWS_DOMAIN_NAME( NAMEID_FORMAT_X509SUBJECTNAME("urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName"),
"urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName"), NAMEID_FORMAT_KERBEROS( NAMEID_FORMAT_WINDOWS_DOMAIN_NAME("urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName"),
"urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos"), NAMEID_FORMAT_ENTITY( NAMEID_FORMAT_KERBEROS("urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos"),
"urn:oasis:names:tc:SAML:2.0:nameid-format:entity"), NAMEID_FORMAT_ENTITY("urn:oasis:names:tc:SAML:2.0:nameid-format:entity"),
PROTOCOL_NSURI("urn:oasis:names:tc:SAML:2.0:protocol"), PROTOCOL_NSURI("urn:oasis:names:tc:SAML:2.0:protocol"),
ECP_PROFILE("urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp"), ECP_PROFILE("urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp"),
PAOS_BINDING("urn:liberty:paos:2003-08"), PAOS_BINDING("urn:liberty:paos:2003-08"),
SIGNATURE_DSA_SHA1("http://www.w3.org/2000/09/xmldsig#dsa-sha1"), SIGNATURE_RSA_SHA1( SIGNATURE_DSA_SHA1("http://www.w3.org/2000/09/xmldsig#dsa-sha1"),
"http://www.w3.org/2000/09/xmldsig#rsa-sha1"), SIGNATURE_RSA_SHA1("http://www.w3.org/2000/09/xmldsig#rsa-sha1"),
SAML_HTTP_POST_BINDING("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"), SAML_HTTP_POST_BINDING("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"),
SAML_HTTP_REDIRECT_BINDING("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"), SAML_HTTP_REDIRECT_BINDING("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"),
@ -87,46 +90,90 @@ public enum JBossSAMLURIConstants {
SUBJECT_CONFIRMATION_BEARER("urn:oasis:names:tc:SAML:2.0:cm:bearer"), SUBJECT_CONFIRMATION_BEARER("urn:oasis:names:tc:SAML:2.0:cm:bearer"),
STATUS_AUTHNFAILED("urn:oasis:names:tc:SAML:2.0:status:AuthnFailed"), STATUS_INVALID_ATTRNAMEVAL( STATUS_AUTHNFAILED("urn:oasis:names:tc:SAML:2.0:status:AuthnFailed"),
"urn:oasis:names:tc:SAML:2.0:status:InvalidAttrnameOrValue"), STATUS_INVALID_NAMEIDPOLICY( STATUS_INVALID_ATTRNAMEVAL("urn:oasis:names:tc:SAML:2.0:status:InvalidAttrnameOrValue"),
"urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy"), STATUS_NOAUTHN_CTX( STATUS_INVALID_NAMEIDPOLICY("urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy"),
"urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext"), STATUS_NO_AVAILABLE_IDP( STATUS_NOAUTHN_CTX("urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext"),
"urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP"), STATUS_NO_PASSIVE( STATUS_NO_AVAILABLE_IDP("urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP"),
"urn:oasis:names:tc:SAML:2.0:status:NoPassive"), STATUS_NO_SUPPORTED_IDP( STATUS_NO_PASSIVE("urn:oasis:names:tc:SAML:2.0:status:NoPassive"),
"urn:oasis:names:tc:SAML:2.0:status:NoSupportedIDP"), STATUS_PARTIAL_LOGOUT( STATUS_NO_SUPPORTED_IDP("urn:oasis:names:tc:SAML:2.0:status:NoSupportedIDP"),
"urn:oasis:names:tc:SAML:2.0:status:PartialLogout"), STATUS_PROXYCOUNT_EXCEEDED( STATUS_PARTIAL_LOGOUT("urn:oasis:names:tc:SAML:2.0:status:PartialLogout"),
"urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded"), STATUS_REQUEST_DENIED( STATUS_PROXYCOUNT_EXCEEDED("urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded"),
"urn:oasis:names:tc:SAML:2.0:status:RequestDenied"), STATUS_REQUEST_UNSUPPORTED( STATUS_REQUEST_DENIED("urn:oasis:names:tc:SAML:2.0:status:RequestDenied"),
"urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported"), STATUS_REQUEST_VERSION_DEPRECATED( STATUS_REQUEST_UNSUPPORTED("urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported"),
"urn:oasis:names:tc:SAML:2.0:status:RequestVersionDeprecated"), STATUS_REQUEST_VERSION_2HIGH( STATUS_REQUEST_VERSION_DEPRECATED("urn:oasis:names:tc:SAML:2.0:status:RequestVersionDeprecated"),
"urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooHigh"), STATUS_REQUEST_VERSION_2LOW( STATUS_REQUEST_VERSION_2HIGH("urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooHigh"),
"urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooLow"), STATUS_RESOURCE_NOT_RECOGNIZED( STATUS_REQUEST_VERSION_2LOW("urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooLow"),
"urn:oasis:names:tc:SAML:2.0:status:ResourceNotRecognized"), STATUS_2MANY_RESPONSES( STATUS_RESOURCE_NOT_RECOGNIZED("urn:oasis:names:tc:SAML:2.0:status:ResourceNotRecognized"),
"urn:oasis:names:tc:SAML:2.0:status:TooManyResponses"), STATUS_UNKNOWN_ATTR_PROFILE( STATUS_2MANY_RESPONSES("urn:oasis:names:tc:SAML:2.0:status:TooManyResponses"),
"urn:oasis:names:tc:SAML:2.0:status:UnknownAttributeProfile"), STATUS_UNKNOWN_PRINCIPAL( STATUS_UNKNOWN_ATTR_PROFILE("urn:oasis:names:tc:SAML:2.0:status:UnknownAttributeProfile"),
"urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal"), STATUS_UNSUPPORTED_BINDING( STATUS_UNKNOWN_PRINCIPAL("urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal"),
"urn:oasis:names:tc:SAML:2.0:status:UnsupportedBinding"), STATUS_UNSUPPORTED_BINDING("urn:oasis:names:tc:SAML:2.0:status:UnsupportedBinding"),
STATUS_REQUESTOR("urn:oasis:names:tc:SAML:2.0:status:Requestor"), STATUS_RESPONDER( STATUS_REQUESTOR("urn:oasis:names:tc:SAML:2.0:status:Requestor"),
"urn:oasis:names:tc:SAML:2.0:status:Responder"), STATUS_SUCCESS("urn:oasis:names:tc:SAML:2.0:status:Success"), STATUS_VERSION_MISMATCH( STATUS_RESPONDER("urn:oasis:names:tc:SAML:2.0:status:Responder"),
"urn:oasis:names:tc:SAML:2.0:status:VersionMismatch"), STATUS_SUCCESS("urn:oasis:names:tc:SAML:2.0:status:Success"),
STATUS_VERSION_MISMATCH("urn:oasis:names:tc:SAML:2.0:status:VersionMismatch"),
TRANSFORM_ENVELOPED_SIGNATURE("http://www.w3.org/2000/09/xmldsig#enveloped-signature"), TRANSFORM_C14N_EXCL_OMIT_COMMENTS( TRANSFORM_ENVELOPED_SIGNATURE("http://www.w3.org/2000/09/xmldsig#enveloped-signature"),
"http://www.w3.org/2001/10/xml-exc-c14n#WithComments"), TRANSFORM_C14N_EXCL_OMIT_COMMENTS("http://www.w3.org/2001/10/xml-exc-c14n#WithComments"),
XSI_PREFIX("xsi"), X500_PREFIX("x500"), X500_NSURI("urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"), XACML_NSURI( XSI_PREFIX("xsi"),
"urn:oasis:names:tc:xacml:2.0:context:schema:os"), XACML_SAML_NSURI("urn:oasis:xacml:2.0:saml:assertion:schema:os"), XACML_SAML_PROTO_NSURI( X500_PREFIX("x500"),
"urn:oasis:xacml:2.0:saml:protocol:schema:os"), XML("http://www.w3.org/XML/1998/namespace"), XMLSCHEMA_NSURI( X500_NSURI("urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"),
"http://www.w3.org/2001/XMLSchema"), XMLDSIG_NSURI("http://www.w3.org/2000/09/xmldsig#"), XMLENC_NSURI( XACML_NSURI("urn:oasis:names:tc:xacml:2.0:context:schema:os"),
"http://www.w3.org/2001/04/xmlenc#"), XSI_NSURI("http://www.w3.org/2001/XMLSchema-instance"); XACML_SAML_NSURI("urn:oasis:xacml:2.0:saml:assertion:schema:os"),
XACML_SAML_PROTO_NSURI("urn:oasis:xacml:2.0:saml:protocol:schema:os"),
XML("http://www.w3.org/XML/1998/namespace"),
XMLSCHEMA_NSURI("http://www.w3.org/2001/XMLSchema"),
XMLDSIG_NSURI("http://www.w3.org/2000/09/xmldsig#"),
XMLENC_NSURI("http://www.w3.org/2001/04/xmlenc#"),
XSI_NSURI("http://www.w3.org/2001/XMLSchema-instance"),
;
private String uri = null; private final String uriStr;
private final URI uri;
private static class ReverseLookup {
// Private class to make sure JBossSAMLURIConstants is fully initialized
private static final Map<String, JBossSAMLURIConstants> CONSTANTS;
static {
HashMap<String, JBossSAMLURIConstants> m = new HashMap<>(JBossSAMLURIConstants.values().length);
JBossSAMLURIConstants old;
for (JBossSAMLURIConstants c : JBossSAMLURIConstants.values()) {
if ((old = m.put(c.get(), c)) != null) {
throw new IllegalStateException("Same name " + c.get() + " used for two constants: " + c + ", " + old);
}
}
CONSTANTS = Collections.unmodifiableMap(m);
}
public JBossSAMLURIConstants from(String key) {
return CONSTANTS.get(key);
}
}
private static final ReverseLookup REVERSE_LOOKUP = new ReverseLookup();
private JBossSAMLURIConstants(String uristr) { private JBossSAMLURIConstants(String uristr) {
this.uri = uristr; this.uriStr = uristr;
this.uri = URI.create(uristr);
} }
public String get() { public String get() {
return this.uriStr;
}
public URI getUri() {
return this.uri; return this.uri;
} }
/**
* Returns an enum constant based if known for the given {@code key}, or {@code null} otherwise.
* @param key
* @return
*/
public static JBossSAMLURIConstants from(String key) {
return REVERSE_LOOKUP.from(key);
}
} }

View file

@ -61,8 +61,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hamcrest</groupId> <groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId> <artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>

View file

@ -30,7 +30,6 @@ import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import java.net.URI;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.keycloak.dom.saml.v2.protocol.ExtensionsType; import org.keycloak.dom.saml.v2.protocol.ExtensionsType;
@ -73,7 +72,7 @@ public class SAML2LogoutResponseBuilder implements SamlProtocolExtensionsAwareBu
// Status // Status
StatusType statusType = new StatusType(); StatusType statusType = new StatusType();
StatusCodeType statusCodeType = new StatusCodeType(); StatusCodeType statusCodeType = new StatusCodeType();
statusCodeType.setValue(URI.create(JBossSAMLURIConstants.STATUS_SUCCESS.get())); statusCodeType.setValue(JBossSAMLURIConstants.STATUS_SUCCESS.getUri());
statusType.setStatusCode(statusCodeType); statusType.setStatusCode(statusCodeType);
statusResponse.setStatus(statusType); statusResponse.setStatus(statusType);

View file

@ -345,8 +345,8 @@ public class DefaultPicketLinkLogger implements PicketLinkLogger {
*@see org.picketlink.identity.federation.PicketLinkLogger#parserUnknownEndElement(java.lang.String) *@see org.picketlink.identity.federation.PicketLinkLogger#parserUnknownEndElement(java.lang.String)
*/ */
@Override @Override
public RuntimeException parserUnknownEndElement(String endElementName) { public RuntimeException parserUnknownEndElement(String endElementName, Location location) {
return new RuntimeException(ErrorCodes.UNKNOWN_END_ELEMENT + endElementName); return new RuntimeException(ErrorCodes.UNKNOWN_END_ELEMENT + endElementName + "::location=" + location);
} }
/* /*
@ -447,7 +447,7 @@ public class DefaultPicketLinkLogger implements PicketLinkLogger {
*/ */
@Override @Override
public RuntimeException parserExpectedTag(String tag, String foundElementTag) { public RuntimeException parserExpectedTag(String tag, String foundElementTag) {
return new RuntimeException(ErrorCodes.EXPECTED_TAG + tag + ">. Found <" + foundElementTag + ">"); return new RuntimeException(ErrorCodes.EXPECTED_TAG + tag + ". Found <" + foundElementTag + ">");
} }
@Override @Override

View file

@ -225,7 +225,7 @@ public interface PicketLinkLogger {
* *
* @return * @return
*/ */
RuntimeException parserUnknownEndElement(String endElementName); RuntimeException parserUnknownEndElement(String endElementName, Location location);
/** /**
* @param tag * @param tag

View file

@ -33,6 +33,9 @@ import javax.xml.stream.events.Characters;
import javax.xml.stream.events.XMLEvent; import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.util.EventReaderDelegate; import javax.xml.stream.util.EventReaderDelegate;
import java.io.InputStream; import java.io.InputStream;
import java.util.regex.Pattern;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.transform.Source; import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.Node; import org.w3c.dom.Node;
@ -43,7 +46,7 @@ import org.w3c.dom.Node;
* @author Anil.Saldhana@redhat.com * @author Anil.Saldhana@redhat.com
* @since Oct 12, 2010 * @since Oct 12, 2010
*/ */
public abstract class AbstractParser implements ParserNamespaceSupport { public abstract class AbstractParser implements StaxParser {
protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
@ -78,15 +81,15 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
/** /**
* Parse an InputStream for payload * Parse an InputStream for payload
* *
* @param configStream * @param stream
* *
* @return * @return
* *
* @throws {@link IllegalArgumentException} * @throws {@link IllegalArgumentException}
* @throws {@link IllegalArgumentException} when the configStream is null * @throws {@link IllegalArgumentException} when the configStream is null
*/ */
public Object parse(InputStream configStream) throws ParsingException { public Object parse(InputStream stream) throws ParsingException {
XMLEventReader xmlEventReader = createEventReader(configStream); XMLEventReader xmlEventReader = createEventReader(stream);
return parse(xmlEventReader); return parse(xmlEventReader);
} }
@ -99,19 +102,13 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
return parse(new DOMSource(node)); return parse(new DOMSource(node));
} }
public XMLEventReader createEventReader(InputStream configStream) throws ParsingException { public static XMLEventReader createEventReader(InputStream configStream) throws ParsingException {
if (configStream == null) if (configStream == null)
throw logger.nullArgumentError("InputStream"); throw logger.nullArgumentError("InputStream");
XMLEventReader xmlEventReader = StaxParserUtil.getXMLEventReader(configStream); XMLEventReader xmlEventReader = StaxParserUtil.getXMLEventReader(configStream);
try { return filterWhitespaces(xmlEventReader);
xmlEventReader = filterWhitespaces(xmlEventReader);
} catch (XMLStreamException e) {
throw logger.parserException(e);
}
return xmlEventReader;
} }
public XMLEventReader createEventReader(Source source) throws ParsingException { public XMLEventReader createEventReader(Source source) throws ParsingException {
@ -120,36 +117,39 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
XMLEventReader xmlEventReader = StaxParserUtil.getXMLEventReader(source); XMLEventReader xmlEventReader = StaxParserUtil.getXMLEventReader(source);
try { return filterWhitespaces(xmlEventReader);
xmlEventReader = filterWhitespaces(xmlEventReader);
} catch (XMLStreamException e) {
throw logger.parserException(e);
}
return xmlEventReader;
} }
protected XMLEventReader filterWhitespaces(XMLEventReader xmlEventReader) throws XMLStreamException { private static final Pattern WHITESPACE_ONLY = Pattern.compile("\\s*");
/**
* Creates a derived {@link XMLEventReader} that ignores all events except for: {@link StartElement},
* {@link EndElement}, and non-empty and non-whitespace-only {@link Characters}.
*
* @param xmlEventReader Original {@link XMLEventReader}
* @return Derived {@link XMLEventReader}
* @throws XMLStreamException
*/
private static XMLEventReader filterWhitespaces(XMLEventReader xmlEventReader) throws ParsingException {
XMLInputFactory xmlInputFactory = XML_INPUT_FACTORY.get(); XMLInputFactory xmlInputFactory = XML_INPUT_FACTORY.get();
xmlEventReader = xmlInputFactory.createFilteredReader(xmlEventReader, new EventFilter() { try {
public boolean accept(XMLEvent xmlEvent) { xmlEventReader = xmlInputFactory.createFilteredReader(xmlEventReader, new EventFilter() {
// We are going to disregard characters that are new line and whitespace @Override
if (xmlEvent.isCharacters()) { public boolean accept(XMLEvent xmlEvent) {
Characters chars = xmlEvent.asCharacters(); // We are going to disregard characters that are new line and whitespace
String data = chars.getData(); if (xmlEvent.isCharacters()) {
data = valid(data) ? data.trim() : null; Characters chars = xmlEvent.asCharacters();
return valid(data); String data = chars.getData();
} else { return data != null && ! WHITESPACE_ONLY.matcher(data).matches();
return xmlEvent.isStartElement() || xmlEvent.isEndElement(); } else {
return xmlEvent.isStartElement() || xmlEvent.isEndElement();
}
} }
} });
} catch (XMLStreamException ex) {
private boolean valid(String str) { throw logger.parserException(ex);
return str != null && ! str.isEmpty(); }
}
});
// Handle IBM JDK bug with Stax parsing when EventReader presented // Handle IBM JDK bug with Stax parsing when EventReader presented
if (Environment.IS_IBM_JAVA) { if (Environment.IS_IBM_JAVA) {

View file

@ -0,0 +1,151 @@
/*
* 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.common.parsers;
import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import java.util.Objects;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
/**
* Simple support for STaX type of parsing. Parses single element and allows processing its direct children.
*
* @param <T> Java class that will be result of parsing this element
* @param <E> Type containing all tokens that can be found in subelements of the element parsed by this parser, usually an enum
* @author hmlnarik
*/
public abstract class AbstractStaxParser<T, E> implements StaxParser {
protected static final PicketLinkLogger LOGGER = PicketLinkLoggerFactory.getLogger();
private final QName expectedStartElement;
private final E unknownElement;
public AbstractStaxParser(QName expectedStartElement, E unknownElement) {
this.unknownElement = unknownElement;
this.expectedStartElement = expectedStartElement;
}
@Override
public T parse(XMLEventReader xmlEventReader) throws ParsingException {
// STATE: should be before the expected start element
// Get the start element and validate it is the expected one
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, expectedStartElement);
T target = instantiateElement(xmlEventReader, startElement);
// STATE: Start element has been read.
QName currentSubelement = null;
while (xmlEventReader.hasNext()) {
// STATE: the only end element that can be found at this phase must correspond to the expected start element
XMLEvent xmlEvent = StaxParserUtil.peekNextTag(xmlEventReader);
if (xmlEvent == null) {
break;
}
if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) xmlEvent;
final QName qName = endElement.getName();
// If leftover from processed subelement, just consume.
if (Objects.equals(qName, currentSubelement)) {
StaxParserUtil.advance(xmlEventReader);
currentSubelement = null;
continue;
}
// If end element corresponding to this start element, stop processing.
if (Objects.equals(qName, expectedStartElement)) {
// consume the end element and finish parsing of this tag
StaxParserUtil.advance(xmlEventReader);
break;
}
// No other case is valid
String elementName = StaxParserUtil.getElementName(endElement);
throw LOGGER.parserUnknownEndElement(elementName, xmlEvent.getLocation());
}
startElement = (StartElement) xmlEvent;
currentSubelement = startElement.getName();
E token = getElementFromName(currentSubelement);
if (token == null) {
token = unknownElement;
}
processSubElement(xmlEventReader, target, token, startElement);
// If the XMLEventReader has not advanced inside processSubElement (hence using "==" and not "equals"), advance it.
if (StaxParserUtil.peek(xmlEventReader) == startElement) {
StaxParserUtil.bypassElementBlock(xmlEventReader);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Element %s bypassed", currentSubelement));
}
}
// In case of recursive nesting the same element, the corresponding end element MUST be handled
// in the {@code processSubElement} method and MUST NOT be consumed here.
if (Objects.equals(expectedStartElement, currentSubelement) || isUnknownElement(token)) {
currentSubelement = null;
}
}
return target;
}
protected boolean isUnknownElement(E token) {
return token == null || Objects.equals(token, unknownElement);
}
protected abstract E getElementFromName(QName name);
/**
* Instantiates the target Java class representing the current element.<br>
* <b>Precondition:</b> Current event is the {@link StartElement}<br>
* <b>Postcondition:</b> Current event is the {@link StartElement} or the {@link EndElement} corresponding to the {@link StartElement}
* @param xmlEventReader
* @param element The XML event that was just read from the {@code xmlEventReader}
* @return
* @throws ParsingException
*/
protected abstract T instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException;
/**
* Processes the subelement of the element processed in {@link #instantiateElement} method.<br>
* <b>Precondition:</b> Current event: Last before the {@link StartElement} corresponding to the processed subelement, i.e.
* event obtained by {@link XMLEventReader#next()} is the {@link StartElement} of the subelement being processed<br>
* <b>Postcondition:</b> Event obtained by {@link XMLEventReader#next()} is either
* the same {@link StartElement} (i.e. no change in position which causes this subelement to be skipped),
* the corresponding {@link EndElement}, or the event after the corresponding {@link EndElement}.
* <p>
* Note that in case of recursive nesting the same element, the corresponding end element MUST be consumed in this method.
* @param xmlEventReader
* @param target Target object (the one created by the {@link #instantiateElement} method.
* @param element The constant corresponding to the current start element.
* @param elementDetail The XML event that was just read from the {@code xmlEventReader}
* @return
* @throws ParsingException
*/
protected abstract void processSubElement(XMLEventReader xmlEventReader, T target, E element, StartElement elementDetail) throws ParsingException;
}

View file

@ -0,0 +1,64 @@
/*
* 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.common.parsers;
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;
import java.util.LinkedList;
import java.util.List;
import javax.xml.namespace.QName;
/**
* Parses any DOM tree to a list of DOM representations.
*/
public class AnyDomParser extends AbstractStaxParser<List<Element>, AnyDomParser.Dom> {
public static enum Dom { ANY_DOM };
public AnyDomParser(QName name) {
super(name, Dom.ANY_DOM);
}
public static AnyDomParser getInstance(QName name) {
return new AnyDomParser(name);
}
@Override
protected List<Element> instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new LinkedList<>();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, List<Element> target, Dom element, StartElement elementDetail) throws ParsingException {
target.add(StaxParserUtil.getDOMElement(xmlEventReader));
}
@Override
protected boolean isUnknownElement(Dom token) {
return true;
}
@Override
protected Dom getElementFromName(QName name) {
return Dom.ANY_DOM;
}
}

View file

@ -18,22 +18,12 @@ package org.keycloak.saml.common.parsers;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLEventReader;
/** /**
* <p> * Interface to indicate the parser.
* Interface to indicate the parser supports a particular namespace.
* </p>
*
* <p>
* This class needs to be moved to the security common project.
* </p>
*
* @author Anil.Saldhana@redhat.com
* @since Feb 5, 2010
*/ */
public interface ParserNamespaceSupport { public interface StaxParser {
/** /**
* Parse the event stream * Parse the event stream
* *
@ -42,12 +32,4 @@ public interface ParserNamespaceSupport {
* @throws ParsingException * @throws ParsingException
*/ */
Object parse(XMLEventReader xmlEventReader) throws ParsingException; Object parse(XMLEventReader xmlEventReader) throws ParsingException;
/**
* Returns whether the parser supports parsing a particular namespace
*
* @param qname
* @return
*/
boolean supports(QName qname);
} }

View file

@ -20,12 +20,13 @@ import org.keycloak.saml.common.ErrorCodes;
import org.keycloak.saml.common.PicketLinkLogger; import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.GeneralConstants; 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.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.processing.core.parsers.util.HasQName;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@ -49,8 +50,10 @@ import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory; import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator; import javax.xml.validation.Validator;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import javax.xml.datatype.XMLGregorianCalendar;
/** /**
* Utility for the stax based parser * Utility for the stax based parser
@ -103,8 +106,12 @@ public class StaxParserUtil {
* *
* @throws org.keycloak.saml.common.exceptions.ParsingException * @throws org.keycloak.saml.common.exceptions.ParsingException
*/ */
public static void bypassElementBlock(XMLEventReader xmlEventReader, JBossSAMLConstants tag) throws ParsingException { public static void bypassElementBlock(XMLEventReader xmlEventReader, QName tag) throws ParsingException {
bypassElementBlock(xmlEventReader, tag == null ? null : tag.get()); XMLEvent xmlEvent = bypassElementBlock(xmlEventReader);
if (! (xmlEvent instanceof EndElement) || ! Objects.equals(((EndElement) xmlEvent).getName(), tag)) {
throw logger.parserExpectedEndTag(tag.getLocalPart());
}
} }
/** /**
@ -173,8 +180,13 @@ public class StaxParserUtil {
* @return * @return
*/ */
public static String getAttributeValue(Attribute attribute) { public static String getAttributeValue(Attribute attribute) {
String str = trim(attribute.getValue()); if (attribute == null) {
return str; return null;
}
final String value = attribute.getValue();
return value == null ? null : trim(value);
} }
/** /**
@ -185,12 +197,90 @@ public class StaxParserUtil {
* *
* @return * @return
*/ */
@Deprecated
public static String getAttributeValue(StartElement startElement, String tag) { public static String getAttributeValue(StartElement startElement, String tag) {
String result = null; return getAttributeValue(startElement, new QName(tag));
Attribute attr = startElement.getAttributeByName(new QName(tag)); }
if (attr != null)
result = getAttributeValue(attr); /**
return result; * Get the Attribute value
*
* @param startElement
* @param tag localpart of the qname of the attribute
*
* @return
*/
public static String getAttributeValue(StartElement startElement, HasQName attrName) {
return getAttributeValue(startElement, attrName.getQName());
}
/**
* Get the Attribute value
*
* @param startElement
* @param tag localpart of the qname of the attribute
*
* @return
*/
public static String getAttributeValue(StartElement startElement, QName attrQName) {
Attribute attr = startElement.getAttributeByName(attrQName);
return getAttributeValue(attr);
}
/**
* Get the Attribute value
*
* @param startElement
* @param tag localpart of the qname of the attribute
*
* @return
*/
public static URI getUriAttributeValue(StartElement startElement, HasQName attrName) {
Attribute attr = startElement.getAttributeByName(attrName.getQName());
String value = getAttributeValue(attr);
return value == null ? null : URI.create(value);
}
/**
* Get the Attribute value
*
* @param startElement
* @param tag localpart of the qname of the attribute
*
* @return
*/
public static XMLGregorianCalendar getXmlTimeAttributeValue(StartElement startElement, HasQName attrName) throws ParsingException {
Attribute attr = startElement.getAttributeByName(attrName.getQName());
String value = getAttributeValue(attr);
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 Integer getIntegerAttributeValue(StartElement startElement, HasQName attrName) {
Attribute attr = startElement.getAttributeByName(attrName.getQName());
String value = getAttributeValue(attr);
return value == null ? null : Integer.valueOf(value);
}
/**
* Get the Attribute value
*
* @param startElement
* @param tag localpart of the qname of the attribute
*
* @return
*/
public static Boolean getBooleanAttributeValue(StartElement startElement, HasQName attrName) {
Attribute attr = startElement.getAttributeByName(attrName.getQName());
String value = getAttributeValue(attr);
return value == null ? null : Boolean.valueOf(value);
} }
/** /**
@ -201,6 +291,7 @@ public class StaxParserUtil {
* *
* @return false if attribute not set * @return false if attribute not set
*/ */
@Deprecated
public static boolean getBooleanAttributeValue(StartElement startElement, String tag) { public static boolean getBooleanAttributeValue(StartElement startElement, String tag) {
return getBooleanAttributeValue(startElement, tag, false); return getBooleanAttributeValue(startElement, tag, false);
} }
@ -213,6 +304,7 @@ public class StaxParserUtil {
* *
* @return false if attribute not set * @return false if attribute not set
*/ */
@Deprecated
public static boolean getBooleanAttributeValue(StartElement startElement, String tag, boolean defaultValue) { public static boolean getBooleanAttributeValue(StartElement startElement, String tag, boolean defaultValue) {
String result = null; String result = null;
Attribute attr = startElement.getAttributeByName(new QName(tag)); Attribute attr = startElement.getAttributeByName(new QName(tag));
@ -222,6 +314,16 @@ public class StaxParserUtil {
return Boolean.valueOf(result); return Boolean.valueOf(result);
} }
public static String getRequiredAttributeValue(StartElement startElement, HasQName attrName) throws ParsingException {
final QName qName = attrName.getQName();
Attribute attr = startElement.getAttributeByName(qName);
if (attr == null)
throw logger.parserRequiredAttribute(qName.getLocalPart());
return StaxParserUtil.getAttributeValue(attr);
}
private static final String JDK_TRANSFORMER_PROPERTY = "picketlink.jdk.transformer";
/** /**
* Given that the {@code XMLEventReader} is in {@code XMLStreamConstants.START_ELEMENT} mode, we parse into a DOM * Given that the {@code XMLEventReader} is in {@code XMLStreamConstants.START_ELEMENT} mode, we parse into a DOM
* Element * Element
@ -233,9 +335,7 @@ public class StaxParserUtil {
* @throws ParsingException * @throws ParsingException
*/ */
public static Element getDOMElement(XMLEventReader xmlEventReader) throws ParsingException { public static Element getDOMElement(XMLEventReader xmlEventReader) throws ParsingException {
Transformer transformer = null; Transformer transformer;
final String JDK_TRANSFORMER_PROPERTY = "picketlink.jdk.transformer";
boolean useJDKTransformer = Boolean.parseBoolean(SecurityActions.getSystemProperty(JDK_TRANSFORMER_PROPERTY, "false")); boolean useJDKTransformer = Boolean.parseBoolean(SecurityActions.getSystemProperty(JDK_TRANSFORMER_PROPERTY, "false"));
@ -263,7 +363,9 @@ public class StaxParserUtil {
} }
/** /**
* Get the element text. * Get the element text. Following {@link XMLEventReader#getElementText()}:
* Precondition: the current event is START_ELEMENT.
* Postcondition: The current event is the corresponding END_ELEMENT.
* *
* @param xmlEventReader * @param xmlEventReader
* *
@ -411,7 +513,7 @@ public class StaxParserUtil {
* *
* @return * @return
*/ */
public static String getStartElementName(StartElement startElement) { public static String getElementName(StartElement startElement) {
return trim(startElement.getName().getLocalPart()); return trim(startElement.getName().getLocalPart());
} }
@ -422,10 +524,12 @@ public class StaxParserUtil {
* *
* @return * @return
*/ */
public static String getEndElementName(EndElement endElement) { public static String getElementName(EndElement endElement) {
return trim(endElement.getName().getLocalPart()); return trim(endElement.getName().getLocalPart());
} }
private static final QName XSI_TYPE = new QName(JBossSAMLURIConstants.XSI_NSURI.get(), "type", JBossSAMLURIConstants.XSI_PREFIX.get());
/** /**
* Given a start element, obtain the xsi:type defined * Given a start element, obtain the xsi:type defined
* *
@ -436,8 +540,7 @@ public class StaxParserUtil {
* @throws RuntimeException if xsi:type is missing * @throws RuntimeException if xsi:type is missing
*/ */
public static String getXSITypeValue(StartElement startElement) { public static String getXSITypeValue(StartElement startElement) {
Attribute xsiType = startElement.getAttributeByName(new QName(JBossSAMLURIConstants.XSI_NSURI.get(), Attribute xsiType = startElement.getAttributeByName(XSI_TYPE);
JBossSAMLConstants.TYPE.get()));
if (xsiType == null) if (xsiType == null)
throw logger.parserExpectedXSI(ErrorCodes.EXPECTED_XSI); throw logger.parserExpectedXSI(ErrorCodes.EXPECTED_XSI);
return StaxParserUtil.getAttributeValue(xsiType); return StaxParserUtil.getAttributeValue(xsiType);
@ -466,7 +569,7 @@ public class StaxParserUtil {
* @return boolean if the tags match * @return boolean if the tags match
*/ */
public static boolean matches(StartElement startElement, String tag) { public static boolean matches(StartElement startElement, String tag) {
String elementTag = getStartElementName(startElement); String elementTag = StaxParserUtil.getElementName(startElement);
return tag.equals(elementTag); return tag.equals(elementTag);
} }
@ -479,7 +582,7 @@ public class StaxParserUtil {
* @return boolean if the tags match * @return boolean if the tags match
*/ */
public static boolean matches(EndElement endElement, String tag) { public static boolean matches(EndElement endElement, String tag) {
String elementTag = getEndElementName(endElement); String elementTag = getElementName(endElement);
return tag.equals(elementTag); return tag.equals(elementTag);
} }
@ -500,6 +603,23 @@ public class StaxParserUtil {
} }
} }
/**
* Consume the next event
*
* @param xmlEventReader
*
* @return
*
* @throws ParsingException
*/
public static XMLEvent advance(XMLEventReader xmlEventReader) throws ParsingException {
try {
return xmlEventReader.nextEvent();
} catch (XMLStreamException e) {
throw logger.parserException(e);
}
}
/** /**
* Peek the next {@code StartElement } * Peek the next {@code StartElement }
* *
@ -511,14 +631,32 @@ public class StaxParserUtil {
*/ */
public static StartElement peekNextStartElement(XMLEventReader xmlEventReader) throws ParsingException { public static StartElement peekNextStartElement(XMLEventReader xmlEventReader) throws ParsingException {
try { try {
while (true) { XMLEvent xmlEvent = xmlEventReader.peek();
XMLEvent xmlEvent = xmlEventReader.peek(); while (xmlEvent != null && ! xmlEvent.isStartElement()) {
xmlEventReader.nextEvent();
if (xmlEvent == null || xmlEvent.isStartElement()) xmlEvent = xmlEventReader.peek();
return (StartElement) xmlEvent;
else
xmlEvent = xmlEventReader.nextEvent();
} }
return (StartElement) xmlEvent;
} catch (XMLStreamException e) {
throw logger.parserException(e);
}
}
/**
* Peek the next {@link StartElement} or {@link EndElement}.
*
* @param xmlEventReader
* @return
* @throws ParsingException
*/
public static XMLEvent peekNextTag(XMLEventReader xmlEventReader) throws ParsingException {
try {
XMLEvent xmlEvent = xmlEventReader.peek();
while (xmlEvent != null && ! xmlEvent.isStartElement() && ! xmlEvent.isEndElement()) {
xmlEventReader.nextEvent();
xmlEvent = xmlEventReader.peek();
}
return xmlEvent;
} catch (XMLStreamException e) { } catch (XMLStreamException e) {
throw logger.parserException(e); throw logger.parserException(e);
} }
@ -571,12 +709,28 @@ public class StaxParserUtil {
* *
* @throws RuntimeException mismatch * @throws RuntimeException mismatch
*/ */
@Deprecated
public static void validate(StartElement startElement, String tag) { public static void validate(StartElement startElement, String tag) {
String foundElementTag = getStartElementName(startElement); String foundElementTag = StaxParserUtil.getElementName(startElement);
if (!tag.equals(foundElementTag)) if (!tag.equals(foundElementTag))
throw logger.parserExpectedTag(tag, foundElementTag); throw logger.parserExpectedTag(tag, foundElementTag);
} }
/**
* Validate that the start element has the expected tag
*
* @param startElement
* @param tag
*
* @throws RuntimeException mismatch
*/
public static void validate(StartElement startElement, QName tag) {
if (! Objects.equals(startElement.getName(), tag)) {
String foundElementTag = StaxParserUtil.getElementName(startElement);
throw logger.parserExpectedTag(tag.getLocalPart(), foundElementTag);
}
}
/** /**
* Validate that the end element has the expected tag * Validate that the end element has the expected tag
* *
@ -586,7 +740,7 @@ public class StaxParserUtil {
* @throws RuntimeException mismatch * @throws RuntimeException mismatch
*/ */
public static void validate(EndElement endElement, String tag) { public static void validate(EndElement endElement, String tag) {
String elementTag = getEndElementName(endElement); String elementTag = getElementName(endElement);
if (!tag.equals(elementTag)) if (!tag.equals(elementTag))
throw new RuntimeException(logger.parserExpectedEndTag("</" + tag + ">. Found </" + elementTag + ">")); throw new RuntimeException(logger.parserExpectedEndTag("</" + tag + ">. Found </" + elementTag + ">"));
} }

View file

@ -227,20 +227,26 @@ public class TransformerUtil {
throw new TransformerException(ErrorCodes.WRITER_SHOULD_START_ELEMENT); throw new TransformerException(ErrorCodes.WRITER_SHOULD_START_ELEMENT);
StartElement rootElement = (StartElement) xmlEvent; StartElement rootElement = (StartElement) xmlEvent;
rootTag = StaxParserUtil.getStartElementName(rootElement); rootTag = StaxParserUtil.getElementName(rootElement);
Element docRoot = handleStartElement(xmlEventReader, rootElement, new CustomHolder(doc, false)); CustomHolder holder = new CustomHolder(doc, false);
Element docRoot = handleStartElement(xmlEventReader, rootElement, holder);
Node parent = doc.importNode(docRoot, true); Node parent = doc.importNode(docRoot, true);
doc.appendChild(parent); doc.appendChild(parent);
stack.push(parent); stack.push(parent);
if (holder.encounteredTextNode) {
// Handling text node skips over the corresponding end element, see {@link XMLEventReader#getElementText()}
return;
}
while (xmlEventReader.hasNext()) { while (xmlEventReader.hasNext()) {
xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader); xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader);
int type = xmlEvent.getEventType(); int type = xmlEvent.getEventType();
switch (type) { switch (type) {
case XMLEvent.START_ELEMENT: case XMLEvent.START_ELEMENT:
StartElement startElement = (StartElement) xmlEvent; StartElement startElement = (StartElement) xmlEvent;
CustomHolder holder = new CustomHolder(doc, false); holder = new CustomHolder(doc, false);
Element docStartElement = handleStartElement(xmlEventReader, startElement, holder); Element docStartElement = handleStartElement(xmlEventReader, startElement, holder);
Node el = doc.importNode(docStartElement, true); Node el = doc.importNode(docStartElement, true);
@ -261,7 +267,7 @@ public class TransformerUtil {
break; break;
case XMLEvent.END_ELEMENT: case XMLEvent.END_ELEMENT:
EndElement endElement = (EndElement) xmlEvent; EndElement endElement = (EndElement) xmlEvent;
String endTag = StaxParserUtil.getEndElementName(endElement); String endTag = StaxParserUtil.getElementName(endElement);
if (rootTag.equals(endTag)) if (rootTag.equals(endTag))
return; // We are done with the dom parsing return; // We are done with the dom parsing
else { else {
@ -334,7 +340,7 @@ public class TransformerUtil {
String prefix = elementName.getPrefix(); String prefix = elementName.getPrefix();
String localPart = elementName.getLocalPart(); String localPart = elementName.getLocalPart();
String qual = prefix != null && prefix != "" ? prefix + ":" + localPart : localPart; String qual = (prefix != null && ! prefix.isEmpty()) ? prefix + ":" + localPart : localPart;
Element el = doc.createElementNS(ns, qual); Element el = doc.createElementNS(ns, qual);
@ -356,7 +362,7 @@ public class TransformerUtil {
ns = attrName.getNamespaceURI(); ns = attrName.getNamespaceURI();
prefix = attrName.getPrefix(); prefix = attrName.getPrefix();
localPart = attrName.getLocalPart(); localPart = attrName.getLocalPart();
qual = prefix != null && prefix != "" ? prefix + ":" + localPart : localPart; qual = (prefix != null && ! prefix.isEmpty()) ? prefix + ":" + localPart : localPart;
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Creating an Attribute Namespace=" + ns + ":" + qual); logger.trace("Creating an Attribute Namespace=" + ns + ":" + qual);
@ -373,8 +379,8 @@ public class TransformerUtil {
QName name = namespace.getName(); QName name = namespace.getName();
localPart = name.getLocalPart(); localPart = name.getLocalPart();
prefix = name.getPrefix(); prefix = name.getPrefix();
if (prefix != null && prefix != "") if (prefix != null && ! prefix.isEmpty())
qual = (localPart != null && localPart != "") ? prefix + ":" + localPart : prefix; qual = (localPart != null && ! localPart.isEmpty()) ? prefix + ":" + localPart : prefix;
if (qual.equals("xmlns")) if (qual.equals("xmlns"))
continue; continue;
@ -423,8 +429,8 @@ public class TransformerUtil {
QName name = namespace.getName(); QName name = namespace.getName();
localPart = name.getLocalPart(); localPart = name.getLocalPart();
prefix = name.getPrefix(); prefix = name.getPrefix();
if (prefix != null && prefix != "") if (prefix != null && ! prefix.isEmpty())
qual = (localPart != null && localPart != "") ? prefix + ":" + localPart : prefix; qual = (localPart != null && ! localPart.isEmpty()) ? prefix + ":" + localPart : prefix;
if (qual != null && qual.equals("xmlns")) if (qual != null && qual.equals("xmlns"))
return namespace.getNamespaceURI(); return namespace.getNamespaceURI();

View file

@ -26,7 +26,6 @@ import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.saml.common.PicketLinkLogger; import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.GeneralConstants; 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.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
@ -94,7 +93,7 @@ public class SAML2Request {
AuthnRequestType authnRequest = new AuthnRequestType(id, issueInstant); AuthnRequestType authnRequest = new AuthnRequestType(id, issueInstant);
authnRequest.setAssertionConsumerServiceURL(URI.create(assertionConsumerURL)); authnRequest.setAssertionConsumerServiceURL(URI.create(assertionConsumerURL));
authnRequest.setProtocolBinding(URI.create(JBossSAMLConstants.HTTP_POST_BINDING.get())); authnRequest.setProtocolBinding(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.getUri());
if (destination != null) { if (destination != null) {
authnRequest.setDestination(URI.create(destination)); authnRequest.setDestination(URI.create(destination));
} }
@ -163,7 +162,7 @@ public class SAML2Request {
Document samlDocument = DocumentUtil.getDocument(is); Document samlDocument = DocumentUtil.getDocument(is);
SAMLParser samlParser = new SAMLParser(); SAMLParser samlParser = SAMLParser.getInstance();
JAXPValidationUtil.checkSchemaValidation(samlDocument); JAXPValidationUtil.checkSchemaValidation(samlDocument);
SAML2Object requestType = (SAML2Object) samlParser.parse(samlDocument); SAML2Object requestType = (SAML2Object) samlParser.parse(samlDocument);
@ -189,7 +188,7 @@ public class SAML2Request {
Document samlDocument = DocumentUtil.getDocument(is); Document samlDocument = DocumentUtil.getDocument(is);
SAMLParser samlParser = new SAMLParser(); SAMLParser samlParser = SAMLParser.getInstance();
JAXPValidationUtil.checkSchemaValidation(samlDocument); JAXPValidationUtil.checkSchemaValidation(samlDocument);
RequestAbstractType requestType = (RequestAbstractType) samlParser.parse(samlDocument); RequestAbstractType requestType = (RequestAbstractType) samlParser.parse(samlDocument);
@ -216,7 +215,7 @@ public class SAML2Request {
Document samlDocument = DocumentUtil.getDocument(is); Document samlDocument = DocumentUtil.getDocument(is);
SAMLParser samlParser = new SAMLParser(); SAMLParser samlParser = SAMLParser.getInstance();
JAXPValidationUtil.checkSchemaValidation(samlDocument); JAXPValidationUtil.checkSchemaValidation(samlDocument);
AuthnRequestType requestType = (AuthnRequestType) samlParser.parse(samlDocument); AuthnRequestType requestType = (AuthnRequestType) samlParser.parse(samlDocument);

View file

@ -85,9 +85,9 @@ import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_
public class SAML2Response { public class SAML2Response {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
private long ASSERTION_VALIDITY = 5000; // 5secs in milis private final long ASSERTION_VALIDITY = 5000; // 5secs in milis
private long CLOCK_SKEW = 2000; // 2secs private final long CLOCK_SKEW = 2000; // 2secs
private SAMLDocumentHolder samlDocumentHolder = null; private SAMLDocumentHolder samlDocumentHolder = null;
@ -118,7 +118,7 @@ public class SAML2Response {
act.addAuthenticatingAuthority(URI.create(authContextDeclRef)); act.addAuthenticatingAuthority(URI.create(authContextDeclRef));
AuthnContextType.AuthnContextTypeSequence sequence = act.new AuthnContextTypeSequence(); AuthnContextType.AuthnContextTypeSequence sequence = act.new AuthnContextTypeSequence();
sequence.setClassRef(new AuthnContextClassRefType(URI.create(JBossSAMLURIConstants.AC_PASSWORD.get()))); sequence.setClassRef(new AuthnContextClassRefType(JBossSAMLURIConstants.AC_PASSWORD.getUri()));
act.setSequence(sequence); act.setSequence(sequence);
authnStatement.setAuthnContext(act); authnStatement.setAuthnContext(act);
@ -264,7 +264,7 @@ public class SAML2Response {
subjectType.addConfirmation(subjectConfirmation); subjectType.addConfirmation(subjectConfirmation);
AssertionType assertionType = null; AssertionType assertionType;
NameIDType issuerID = issuerInfo.getIssuer(); NameIDType issuerID = issuerInfo.getIssuer();
try { try {
issueInstant = XMLTimeUtil.getIssueInstant(); issueInstant = XMLTimeUtil.getIssueInstant();
@ -373,7 +373,7 @@ public class SAML2Response {
throw logger.nullArgumentError("InputStream"); throw logger.nullArgumentError("InputStream");
Document samlDocument = DocumentUtil.getDocument(is); Document samlDocument = DocumentUtil.getDocument(is);
SAMLParser samlParser = new SAMLParser(); SAMLParser samlParser = SAMLParser.getInstance();
JAXPValidationUtil.checkSchemaValidation(samlDocument); JAXPValidationUtil.checkSchemaValidation(samlDocument);
return (EncryptedAssertionType) samlParser.parse(samlDocument); return (EncryptedAssertionType) samlParser.parse(samlDocument);
@ -396,7 +396,7 @@ public class SAML2Response {
throw logger.nullArgumentError("InputStream"); throw logger.nullArgumentError("InputStream");
Document samlDocument = DocumentUtil.getDocument(is); Document samlDocument = DocumentUtil.getDocument(is);
SAMLParser samlParser = new SAMLParser(); SAMLParser samlParser = SAMLParser.getInstance();
JAXPValidationUtil.checkSchemaValidation(samlDocument); JAXPValidationUtil.checkSchemaValidation(samlDocument);
return (AssertionType) samlParser.parse(samlDocument); return (AssertionType) samlParser.parse(samlDocument);
} }
@ -426,7 +426,7 @@ public class SAML2Response {
Document samlResponseDocument = DocumentUtil.getDocument(is); Document samlResponseDocument = DocumentUtil.getDocument(is);
SAMLParser samlParser = new SAMLParser(); SAMLParser samlParser = SAMLParser.getInstance();
JAXPValidationUtil.checkSchemaValidation(samlResponseDocument); JAXPValidationUtil.checkSchemaValidation(samlResponseDocument);
ResponseType responseType = (ResponseType) samlParser.parse(samlResponseDocument); ResponseType responseType = (ResponseType) samlParser.parse(samlResponseDocument);
@ -457,7 +457,7 @@ public class SAML2Response {
logger.trace("SAML Response Document: " + DocumentUtil.asString(samlResponseDocument)); logger.trace("SAML Response Document: " + DocumentUtil.asString(samlResponseDocument));
} }
SAMLParser samlParser = new SAMLParser(); SAMLParser samlParser = SAMLParser.getInstance();
JAXPValidationUtil.checkSchemaValidation(samlResponseDocument); JAXPValidationUtil.checkSchemaValidation(samlResponseDocument);
SAML2Object responseType = (SAML2Object) samlParser.parse(samlResponseDocument); SAML2Object responseType = (SAML2Object) samlParser.parse(samlResponseDocument);

View file

@ -30,7 +30,6 @@ import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.common.parsers.ParserNamespaceSupport;
import org.keycloak.saml.common.util.DocumentUtil; import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.common.util.StringUtil; import org.keycloak.saml.common.util.StringUtil;
@ -46,6 +45,7 @@ import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement; import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement; import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent; import javax.xml.stream.events.XMLEvent;
import org.keycloak.saml.common.parsers.StaxParser;
/** /**
* Parse the saml assertion * Parse the saml assertion
@ -53,7 +53,7 @@ import javax.xml.stream.events.XMLEvent;
* @author Anil.Saldhana@redhat.com * @author Anil.Saldhana@redhat.com
* @since Oct 12, 2010 * @since Oct 12, 2010
*/ */
public class SAML11AssertionParser implements ParserNamespaceSupport { public class SAML11AssertionParser implements StaxParser {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
@ -90,11 +90,11 @@ public class SAML11AssertionParser implements ParserNamespaceSupport {
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader); xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader);
EndElement endElement = (EndElement) xmlEvent; EndElement endElement = (EndElement) xmlEvent;
String endElementTag = StaxParserUtil.getEndElementName(endElement); String endElementTag = StaxParserUtil.getElementName(endElement);
if (endElementTag.equals(JBossSAMLConstants.ASSERTION.get())) if (endElementTag.equals(JBossSAMLConstants.ASSERTION.get()))
break; break;
else else
throw logger.parserUnknownEndElement(endElementTag); throw logger.parserUnknownEndElement(endElementTag, xmlEvent.getLocation());
} }
StartElement peekedElement = null; StartElement peekedElement = null;
@ -107,7 +107,7 @@ public class SAML11AssertionParser implements ParserNamespaceSupport {
if (peekedElement == null) if (peekedElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(peekedElement); String tag = StaxParserUtil.getElementName(peekedElement);
if (tag.equals(JBossSAMLConstants.SIGNATURE.get())) { if (tag.equals(JBossSAMLConstants.SIGNATURE.get())) {
assertion.setSignature(StaxParserUtil.getDOMElement(xmlEventReader)); assertion.setSignature(StaxParserUtil.getDOMElement(xmlEventReader));
@ -144,16 +144,6 @@ public class SAML11AssertionParser implements ParserNamespaceSupport {
return assertion; return assertion;
} }
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
String nsURI = qname.getNamespaceURI();
String localPart = qname.getLocalPart();
return nsURI.equals(JBossSAMLURIConstants.ASSERTION_NSURI.get())
&& localPart.equals(JBossSAMLConstants.ASSERTION.get());
}
private SAML11AssertionType parseBaseAttributes(StartElement nextElement) throws ParsingException { private SAML11AssertionType parseBaseAttributes(StartElement nextElement) throws ParsingException {
Attribute idAttribute = nextElement.getAttributeByName(new QName(SAML11Constants.ASSERTIONID)); Attribute idAttribute = nextElement.getAttributeByName(new QName(SAML11Constants.ASSERTIONID));

View file

@ -25,7 +25,6 @@ import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.JBossSAMLConstants; import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAML11ParserUtil; import org.keycloak.saml.processing.core.parsers.util.SAML11ParserUtil;
import org.keycloak.saml.processing.core.saml.v1.SAML11Constants; import org.keycloak.saml.processing.core.saml.v1.SAML11Constants;
@ -36,6 +35,7 @@ import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.Attribute; import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement; import javax.xml.stream.events.StartElement;
import org.keycloak.saml.common.parsers.StaxParser;
/** /**
* Parse the SAML2 AuthnRequest * Parse the SAML2 AuthnRequest
@ -43,7 +43,7 @@ import javax.xml.stream.events.StartElement;
* @author Anil.Saldhana@redhat.com * @author Anil.Saldhana@redhat.com
* @since June 24, 2011 * @since June 24, 2011
*/ */
public class SAML11RequestParser implements ParserNamespaceSupport { public class SAML11RequestParser implements StaxParser {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
@ -77,7 +77,7 @@ public class SAML11RequestParser implements ParserNamespaceSupport {
if (startElement == null) if (startElement == null)
break; break;
String elementName = StaxParserUtil.getStartElementName(startElement); String elementName = StaxParserUtil.getElementName(startElement);
if (SAML11Constants.ATTRIBUTE_QUERY.equals(elementName)) { if (SAML11Constants.ATTRIBUTE_QUERY.equals(elementName)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader); startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
@ -106,10 +106,4 @@ public class SAML11RequestParser implements ParserNamespaceSupport {
return request; return request;
} }
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
return JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(qname.getNamespaceURI());
}
} }

View file

@ -25,7 +25,6 @@ import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory; import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.JBossSAMLConstants; import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.saml.v1.SAML11Constants; import org.keycloak.saml.processing.core.saml.v1.SAML11Constants;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
@ -38,6 +37,7 @@ import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement; import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement; import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent; import javax.xml.stream.events.XMLEvent;
import org.keycloak.saml.common.parsers.StaxParser;
/** /**
* Parse the SAML 11 Response * Parse the SAML 11 Response
@ -45,11 +45,11 @@ import javax.xml.stream.events.XMLEvent;
* @author Anil.Saldhana@redhat.com * @author Anil.Saldhana@redhat.com
* @since 23 June 2011 * @since 23 June 2011
*/ */
public class SAML11ResponseParser implements ParserNamespaceSupport { public class SAML11ResponseParser implements StaxParser {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
private final String RESPONSE = JBossSAMLConstants.RESPONSE.get(); private final String RESPONSE = JBossSAMLConstants.RESPONSE__PROTOCOL.get();
/** /**
* @see {@link ParserNamespaceSupport#parse(XMLEventReader)} * @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
@ -76,7 +76,7 @@ public class SAML11ResponseParser implements ParserNamespaceSupport {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String elementName = StaxParserUtil.getStartElementName(startElement); String elementName = StaxParserUtil.getElementName(startElement);
if (JBossSAMLConstants.SIGNATURE.get().equals(elementName)) { if (JBossSAMLConstants.SIGNATURE.get().equals(elementName)) {
Element sig = StaxParserUtil.getDOMElement(xmlEventReader); Element sig = StaxParserUtil.getDOMElement(xmlEventReader);
response.setSignature(sig); response.setSignature(sig);
@ -172,17 +172,11 @@ public class SAML11ResponseParser implements ParserNamespaceSupport {
if (StaxParserUtil.matches(endElement, STATUS)) if (StaxParserUtil.matches(endElement, STATUS))
break; break;
else else
throw logger.parserUnknownEndElement(StaxParserUtil.getEndElementName(endElement)); throw logger.parserUnknownEndElement(StaxParserUtil.getElementName(endElement), xmlEvent.getLocation());
} else } else
break; break;
} }
return status; return status;
} }
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
return SAML11Constants.PROTOCOL_11_NSURI.equals(qname.getNamespaceURI()) && RESPONSE.equals(qname.getLocalPart());
}
} }

View file

@ -25,7 +25,6 @@ import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.JBossSAMLConstants; import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAML11ParserUtil; import org.keycloak.saml.processing.core.parsers.util.SAML11ParserUtil;
import org.keycloak.saml.processing.core.saml.v1.SAML11Constants; import org.keycloak.saml.processing.core.saml.v1.SAML11Constants;
@ -37,6 +36,7 @@ import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement; import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent; import javax.xml.stream.events.XMLEvent;
import java.net.URI; import java.net.URI;
import org.keycloak.saml.common.parsers.StaxParser;
/** /**
* Parse the saml subject * Parse the saml subject
@ -44,7 +44,7 @@ import java.net.URI;
* @author Anil.Saldhana@redhat.com * @author Anil.Saldhana@redhat.com
* @since Oct 12, 2010 * @since Oct 12, 2010
*/ */
public class SAML11SubjectParser implements ParserNamespaceSupport { public class SAML11SubjectParser implements StaxParser {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
@ -65,14 +65,14 @@ public class SAML11SubjectParser implements ParserNamespaceSupport {
endElement = StaxParserUtil.getNextEndElement(xmlEventReader); endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
break; break;
} else } else
throw logger.parserUnknownEndElement(StaxParserUtil.getEndElementName(endElement)); throw logger.parserUnknownEndElement(StaxParserUtil.getElementName(endElement), xmlEvent.getLocation());
} }
StartElement peekedElement = StaxParserUtil.peekNextStartElement(xmlEventReader); StartElement peekedElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (peekedElement == null) if (peekedElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(peekedElement); String tag = StaxParserUtil.getElementName(peekedElement);
if (SAML11Constants.NAME_IDENTIFIER.equalsIgnoreCase(tag)) { if (SAML11Constants.NAME_IDENTIFIER.equalsIgnoreCase(tag)) {
peekedElement = StaxParserUtil.getNextStartElement(xmlEventReader); peekedElement = StaxParserUtil.getNextStartElement(xmlEventReader);
@ -100,14 +100,5 @@ public class SAML11SubjectParser implements ParserNamespaceSupport {
return subject; return subject;
} }
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
String nsURI = qname.getNamespaceURI();
String localPart = qname.getLocalPart();
return nsURI.equals(JBossSAMLURIConstants.ASSERTION_NSURI.get()) && localPart.equals(JBossSAMLConstants.SUBJECT.get());
}
} }

View file

@ -1,91 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.protocol.ArtifactResolveType;
import org.keycloak.saml.common.ErrorCodes;
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.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
/**
* Parse the {@link ArtifactResolveType}
*
* @author Anil.Saldhana@redhat.com
* @since Jul 1, 2011
*/
public class SAMLArtifactResolveParser extends SAMLRequestAbstractParser implements ParserNamespaceSupport {
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
// Get the startelement
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.ARTIFACT_RESOLVE.get());
ArtifactResolveType artifactResolve = parseBaseAttributes(startElement);
while (xmlEventReader.hasNext()) {
// Let us peek at the next start element
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
super.parseCommonElements(startElement, xmlEventReader, artifactResolve);
String elementName = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.ARTIFACT.get().equals(elementName)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
artifactResolve.setArtifact(StaxParserUtil.getElementText(xmlEventReader));
} else if (JBossSAMLConstants.ISSUER.get().equals(elementName)) {
continue;
} else if (JBossSAMLConstants.SIGNATURE.get().equals(elementName)) {
continue;
} else if (JBossSAMLConstants.EXTENSIONS.get().equals(elementName)) {
continue;
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_START_ELEMENT + elementName + "::location="
+ startElement.getLocation());
}
return artifactResolve;
}
public boolean supports(QName qname) {
return JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(qname.getNamespaceURI());
}
/**
* Parse the attributes at the authnrequesttype element
*
* @param startElement
*
* @return
*
* @throws ParsingException
*/
private ArtifactResolveType parseBaseAttributes(StartElement startElement) throws ParsingException {
super.parseRequiredAttributes(startElement);
ArtifactResolveType authnRequest = new ArtifactResolveType(id, issueInstant);
// Let us get the attributes
super.parseBaseAttributes(startElement, authnRequest);
return authnRequest;
}
}

View file

@ -1,113 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.protocol.ArtifactResponseType;
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
import org.keycloak.saml.common.ErrorCodes;
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.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
/**
* Parse the SAML Response
*
* @author Anil.Saldhana@redhat.com
* @since July 1, 2011
*/
public class SAMLArtifactResponseParser extends SAMLStatusResponseTypeParser implements ParserNamespaceSupport {
private final String ARTIFACT_RESPONSE = JBossSAMLConstants.ARTIFACT_RESPONSE.get();
/**
* @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
*/
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
// Get the startelement
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, ARTIFACT_RESPONSE);
ArtifactResponseType response = (ArtifactResponseType) parseBaseAttributes(startElement);
while (xmlEventReader.hasNext()) {
// Let us peek at the next start element
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
String elementName = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.ISSUER.get().equals(elementName)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
NameIDType issuer = new NameIDType();
issuer.setValue(StaxParserUtil.getElementText(xmlEventReader));
response.setIssuer(issuer);
} else if (JBossSAMLConstants.SIGNATURE.get().equals(elementName)) {
Element sig = StaxParserUtil.getDOMElement(xmlEventReader);
response.setSignature(sig);
} else if (JBossSAMLConstants.EXTENSIONS.get().equals(elementName)) {
SAMLExtensionsParser extensionsParser = new SAMLExtensionsParser();
response.setExtensions(extensionsParser.parse(xmlEventReader));
} else if (JBossSAMLConstants.AUTHN_REQUEST.get().equals(elementName)) {
SAMLAuthNRequestParser authnParser = new SAMLAuthNRequestParser();
AuthnRequestType authn = (AuthnRequestType) authnParser.parse(xmlEventReader);
response.setAny(authn);
} else if (JBossSAMLConstants.RESPONSE.get().equals(elementName)) {
SAMLResponseParser authnParser = new SAMLResponseParser();
ResponseType authn = (ResponseType) authnParser.parse(xmlEventReader);
response.setAny(authn);
} else if (JBossSAMLConstants.STATUS.get().equals(elementName)) {
response.setStatus(parseStatus(xmlEventReader));
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_START_ELEMENT + elementName + "::location="
+ startElement.getLocation());
}
return response;
}
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
return JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(qname.getNamespaceURI())
&& ARTIFACT_RESPONSE.equals(qname.getLocalPart());
}
/**
* Parse the attributes at the response element
*
* @param startElement
*
* @return
*
* @throws ParsingException
*/
protected StatusResponseType parseBaseAttributes(StartElement startElement) throws ParsingException {
ArtifactResponseType response = new ArtifactResponseType(super.parseBaseAttributes(startElement));
return response;
}
}

View file

@ -1,184 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
import org.keycloak.dom.saml.v2.assertion.ConditionsType;
import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.saml.common.ErrorCodes;
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.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.common.parsers.ParserNamespaceSupport;
import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import org.w3c.dom.Element;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
/**
* Parse the saml assertion
*
* @author Anil.Saldhana@redhat.com
* @since Oct 12, 2010
*/
public class SAMLAssertionParser implements ParserNamespaceSupport {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
private final String ASSERTION = JBossSAMLConstants.ASSERTION.get();
public AssertionType fromElement(Element element) throws ConfigurationException, ProcessingException, ParsingException {
XMLEventReader xmlEventReader = StaxParserUtil.getXMLEventReader(DocumentUtil.getNodeAsStream(element));
return (AssertionType) parse(xmlEventReader);
}
/**
* @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
*/
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
StartElement startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
String startElementName = StaxParserUtil.getStartElementName(startElement);
if (startElementName.equals(JBossSAMLConstants.ENCRYPTED_ASSERTION.get())) {
Element domElement = StaxParserUtil.getDOMElement(xmlEventReader);
EncryptedAssertionType encryptedAssertion = new EncryptedAssertionType();
encryptedAssertion.setEncryptedElement(domElement);
return encryptedAssertion;
}
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
// Special case: Encrypted Assertion
StaxParserUtil.validate(startElement, ASSERTION);
AssertionType assertion = parseBaseAttributes(startElement);
// Peek at the next event
while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent == null)
break;
if (xmlEvent instanceof EndElement) {
xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader);
EndElement endElement = (EndElement) xmlEvent;
String endElementTag = StaxParserUtil.getEndElementName(endElement);
if (endElementTag.equals(JBossSAMLConstants.ASSERTION.get()))
break;
else
throw new RuntimeException(ErrorCodes.UNKNOWN_END_ELEMENT + endElementTag);
}
StartElement peekedElement = null;
if (xmlEvent instanceof StartElement) {
peekedElement = (StartElement) xmlEvent;
} else {
peekedElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
}
if (peekedElement == null)
break;
String tag = StaxParserUtil.getStartElementName(peekedElement);
if (tag.equals(JBossSAMLConstants.SIGNATURE.get())) {
assertion.setSignature(StaxParserUtil.getDOMElement(xmlEventReader));
continue;
}
if (JBossSAMLConstants.ISSUER.get().equalsIgnoreCase(tag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String issuerValue = StaxParserUtil.getElementText(xmlEventReader);
NameIDType issuer = new NameIDType();
issuer.setValue(issuerValue);
assertion.setIssuer(issuer);
} else if (JBossSAMLConstants.SUBJECT.get().equalsIgnoreCase(tag)) {
SAMLSubjectParser subjectParser = new SAMLSubjectParser();
assertion.setSubject((SubjectType) subjectParser.parse(xmlEventReader));
} else if (JBossSAMLConstants.CONDITIONS.get().equalsIgnoreCase(tag)) {
SAMLConditionsParser conditionsParser = new SAMLConditionsParser();
ConditionsType conditions = (ConditionsType) conditionsParser.parse(xmlEventReader);
assertion.setConditions(conditions);
} else if (JBossSAMLConstants.ADVICE.get().equalsIgnoreCase(tag)) {
StaxParserUtil.bypassElementBlock(xmlEventReader);
logger.debug("SAML Advice tag is ignored");
} else if (JBossSAMLConstants.AUTHN_STATEMENT.get().equalsIgnoreCase(tag)) {
AuthnStatementType authnStatementType = SAMLParserUtil.parseAuthnStatement(xmlEventReader);
assertion.addStatement(authnStatementType);
} else if (JBossSAMLConstants.ATTRIBUTE_STATEMENT.get().equalsIgnoreCase(tag)) {
AttributeStatementType attributeStatementType = SAMLParserUtil.parseAttributeStatement(xmlEventReader);
assertion.addStatement(attributeStatementType);
} else if (JBossSAMLConstants.STATEMENT.get().equalsIgnoreCase(tag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String xsiTypeValue = StaxParserUtil.getXSITypeValue(startElement);
throw new RuntimeException(ErrorCodes.UNKNOWN_XSI + xsiTypeValue);
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_TAG + tag + "::location=" + peekedElement.getLocation());
}
return assertion;
}
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
String nsURI = qname.getNamespaceURI();
String localPart = qname.getLocalPart();
return nsURI.equals(JBossSAMLURIConstants.ASSERTION_NSURI.get())
&& localPart.equals(JBossSAMLConstants.ASSERTION.get());
}
private AssertionType parseBaseAttributes(StartElement nextElement) throws ParsingException {
String id = StaxParserUtil.getAttributeValue(nextElement, JBossSAMLConstants.ID.get());
if (id == null) {
throw logger.parserRequiredAttribute(JBossSAMLConstants.ID.get());
}
String version = StaxParserUtil.getAttributeValue(nextElement, JBossSAMLConstants.VERSION.get());
if (!JBossSAMLConstants.VERSION_2_0.get().equals(version)) {
throw logger.parserException(new RuntimeException(
String.format("Assertion %s required to be \"%s\"", JBossSAMLConstants.VERSION.get(), JBossSAMLConstants.VERSION_2_0.get())));
}
String issueInstantString = StaxParserUtil.getAttributeValue(nextElement, JBossSAMLConstants.ISSUE_INSTANT.get());
if (issueInstantString == null) {
throw logger.parserRequiredAttribute(JBossSAMLConstants.ISSUE_INSTANT.get());
}
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(issueInstantString);
return new AssertionType(id, issueInstant);
}
}

View file

@ -1,93 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.protocol.AttributeQueryType;
import org.keycloak.saml.common.ErrorCodes;
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.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
/**
* Parse the {@link org.keycloak.dom.saml.v2.protocol.ArtifactResolveType}
*
* @author Anil.Saldhana@redhat.com
* @since Jul 1, 2011
*/
public class SAMLAttributeQueryParser extends SAMLRequestAbstractParser implements ParserNamespaceSupport {
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
// Get the startelement
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.ATTRIBUTE_QUERY.get());
AttributeQueryType attributeQuery = parseBaseAttributes(startElement);
while (xmlEventReader.hasNext()) {
// Let us peek at the next start element
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
super.parseCommonElements(startElement, xmlEventReader, attributeQuery);
String elementName = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.SUBJECT.get().equals(elementName)) {
attributeQuery.setSubject(getSubject(xmlEventReader));
} else if (JBossSAMLConstants.ATTRIBUTE.get().equals(elementName)) {
attributeQuery.add(SAMLParserUtil.parseAttribute(xmlEventReader));
} else if (JBossSAMLConstants.ISSUER.get().equals(elementName)) {
continue;
} else if (JBossSAMLConstants.SIGNATURE.get().equals(elementName)) {
continue;
} else if (JBossSAMLConstants.EXTENSIONS.get().equals(elementName)) {
continue;
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_START_ELEMENT + elementName + "::location="
+ startElement.getLocation());
}
return attributeQuery;
}
public boolean supports(QName qname) {
return JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(qname.getNamespaceURI());
}
/**
* Parse the attributes at the authnrequesttype element
*
* @param startElement
*
* @return
*
* @throws ParsingException
*/
private AttributeQueryType parseBaseAttributes(StartElement startElement) throws ParsingException {
super.parseRequiredAttributes(startElement);
AttributeQueryType authnRequest = new AttributeQueryType(id, issueInstant);
// Let us get the attributes
super.parseBaseAttributes(startElement, authnRequest);
return authnRequest;
}
}

View file

@ -1,215 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.assertion.ConditionsType;
import org.keycloak.dom.saml.v2.protocol.AuthnContextComparisonType;
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
import org.keycloak.dom.saml.v2.protocol.NameIDPolicyType;
import org.keycloak.dom.saml.v2.protocol.RequestedAuthnContextType;
import org.keycloak.saml.common.ErrorCodes;
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.ParserNamespaceSupport;
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.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import java.net.URI;
/**
* Parse the SAML2 AuthnRequest
*
* @author Anil.Saldhana@redhat.com
* @since Nov 2, 2010
*/
public class SAMLAuthNRequestParser extends SAMLRequestAbstractParser implements ParserNamespaceSupport {
/**
* @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
*/
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
// Get the startelement
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.AUTHN_REQUEST.get());
AuthnRequestType authnRequest = parseBaseAttributes(startElement);
while (xmlEventReader.hasNext()) {
// Let us peek at the next start element
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
super.parseCommonElements(startElement, xmlEventReader, authnRequest);
String elementName = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.NAMEID_POLICY.get().equals(elementName)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
authnRequest.setNameIDPolicy(getNameIDPolicy(startElement));
} else if (JBossSAMLConstants.SUBJECT.get().equals(elementName)) {
authnRequest.setSubject(getSubject(xmlEventReader));
} else if (JBossSAMLConstants.CONDITIONS.get().equals(elementName)) {
authnRequest.setConditions((ConditionsType) (new SAMLConditionsParser()).parse(xmlEventReader));
} else if (JBossSAMLConstants.REQUESTED_AUTHN_CONTEXT.get().equals(elementName)) {
authnRequest.setRequestedAuthnContext(getRequestedAuthnContextType(xmlEventReader));
} else if (JBossSAMLConstants.ISSUER.get().equals(elementName)) {
continue;
} else if (JBossSAMLConstants.SIGNATURE.get().equals(elementName)) {
continue;
} else if (JBossSAMLConstants.EXTENSIONS.get().equals(elementName)) {
continue;
} else if (JBossSAMLConstants.SCOPING.get().equals(elementName)) {
StaxParserUtil.bypassElementBlock(xmlEventReader, JBossSAMLConstants.SCOPING);
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_START_ELEMENT + elementName + "::location="
+ startElement.getLocation());
}
return authnRequest;
}
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
return JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(qname.getNamespaceURI());
}
/**
* Parse the attributes at the authnrequesttype element
*
* @param startElement
*
* @return
*
* @throws ParsingException
*/
private AuthnRequestType parseBaseAttributes(StartElement startElement) throws ParsingException {
super.parseRequiredAttributes(startElement);
AuthnRequestType authnRequest = new AuthnRequestType(id, issueInstant);
// Let us get the attributes
super.parseBaseAttributes(startElement, authnRequest);
Attribute assertionConsumerServiceURL = startElement.getAttributeByName(new QName(
JBossSAMLConstants.ASSERTION_CONSUMER_SERVICE_URL.get()));
if (assertionConsumerServiceURL != null) {
String uri = StaxParserUtil.getAttributeValue(assertionConsumerServiceURL);
authnRequest.setAssertionConsumerServiceURL(URI.create(uri));
}
Attribute assertionConsumerServiceIndex = startElement.getAttributeByName(new QName(
JBossSAMLConstants.ASSERTION_CONSUMER_SERVICE_INDEX.get()));
if (assertionConsumerServiceIndex != null)
authnRequest.setAssertionConsumerServiceIndex(Integer.parseInt(StaxParserUtil
.getAttributeValue(assertionConsumerServiceIndex)));
Attribute protocolBinding = startElement.getAttributeByName(new QName(JBossSAMLConstants.PROTOCOL_BINDING.get()));
if (protocolBinding != null)
authnRequest.setProtocolBinding(URI.create(StaxParserUtil.getAttributeValue(protocolBinding)));
Attribute providerName = startElement.getAttributeByName(new QName(JBossSAMLConstants.PROVIDER_NAME.get()));
if (providerName != null)
authnRequest.setProviderName(StaxParserUtil.getAttributeValue(providerName));
Attribute forceAuthn = startElement.getAttributeByName(new QName(JBossSAMLConstants.FORCE_AUTHN.get()));
if (forceAuthn != null) {
authnRequest.setForceAuthn(Boolean.parseBoolean(StaxParserUtil.getAttributeValue(forceAuthn)));
}
Attribute isPassive = startElement.getAttributeByName(new QName(JBossSAMLConstants.IS_PASSIVE.get()));
if (isPassive != null) {
authnRequest.setIsPassive(Boolean.parseBoolean(StaxParserUtil.getAttributeValue(isPassive)));
}
Attribute attributeConsumingServiceIndex = startElement.getAttributeByName(new QName(
JBossSAMLConstants.ATTRIBUTE_CONSUMING_SERVICE_INDEX.get()));
if (attributeConsumingServiceIndex != null)
authnRequest.setAttributeConsumingServiceIndex(Integer.parseInt(StaxParserUtil
.getAttributeValue(attributeConsumingServiceIndex)));
return authnRequest;
}
/**
* Get the NameIDPolicy
*
* @param startElement
*
* @return
*/
private NameIDPolicyType getNameIDPolicy(StartElement startElement) {
NameIDPolicyType nameIDPolicy = new NameIDPolicyType();
Attribute format = startElement.getAttributeByName(new QName(JBossSAMLConstants.FORMAT.get()));
if (format != null)
nameIDPolicy.setFormat(URI.create(StaxParserUtil.getAttributeValue(format)));
Attribute allowCreate = startElement.getAttributeByName(new QName(JBossSAMLConstants.ALLOW_CREATE.get()));
if (allowCreate != null)
nameIDPolicy.setAllowCreate(Boolean.parseBoolean(StaxParserUtil.getAttributeValue(allowCreate)));
return nameIDPolicy;
}
private RequestedAuthnContextType getRequestedAuthnContextType(XMLEventReader xmlEventReader) throws ParsingException {
RequestedAuthnContextType ract = new RequestedAuthnContextType();
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.REQUESTED_AUTHN_CONTEXT.get());
Attribute comparison = startElement.getAttributeByName(new QName(JBossSAMLConstants.COMPARISON.get()));
if (comparison != null) {
ract.setComparison(AuthnContextComparisonType.fromValue(comparison.getValue()));
}
while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
EndElement nextEndElement = (EndElement) xmlEvent;
if (StaxParserUtil.matches(nextEndElement, JBossSAMLConstants.REQUESTED_AUTHN_CONTEXT.get())) {
nextEndElement = StaxParserUtil.getNextEndElement(xmlEventReader);
break;
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_END_ELEMENT
+ StaxParserUtil.getEndElementName(nextEndElement));
}
String tag = null;
if (xmlEvent instanceof StartElement) {
StartElement peekedElement = (StartElement) xmlEvent;
tag = StaxParserUtil.getStartElementName(peekedElement);
}
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String elName = StaxParserUtil.getStartElementName(startElement);
if (elName.equals(JBossSAMLConstants.AUTHN_CONTEXT_CLASS_REF.get())) {
String value = StaxParserUtil.getElementText(xmlEventReader);
ract.addAuthnContextClassRef(value);
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_TAG + elName);
}
return ract;
}
}

View file

@ -1,173 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType;
import org.keycloak.dom.saml.v2.assertion.ConditionsType;
import org.keycloak.dom.saml.v2.assertion.OneTimeUseType;
import org.keycloak.saml.common.ErrorCodes;
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.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
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.net.URI;
/**
* Parse the <conditions> in the saml assertion
*
* @author Anil.Saldhana@redhat.com
* @since Oct 14, 2010
*/
public class SAMLConditionsParser implements ParserNamespaceSupport {
/**
* @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
*/
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
// We are entering this method with <conditions> as the next start element
// and we have to exit after seeing the </conditions> end tag
StartElement conditionsElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(conditionsElement, JBossSAMLConstants.CONDITIONS.get());
ConditionsType conditions = new ConditionsType();
String assertionNS = JBossSAMLURIConstants.ASSERTION_NSURI.get();
QName notBeforeQName = new QName("", JBossSAMLConstants.NOT_BEFORE.get());
QName notBeforeQNameWithNS = new QName(assertionNS, JBossSAMLConstants.NOT_BEFORE.get());
QName notAfterQName = new QName("", JBossSAMLConstants.NOT_ON_OR_AFTER.get());
QName notAfterQNameWithNS = new QName(assertionNS, JBossSAMLConstants.NOT_ON_OR_AFTER.get());
Attribute notBeforeAttribute = conditionsElement.getAttributeByName(notBeforeQName);
if (notBeforeAttribute == null)
notBeforeAttribute = conditionsElement.getAttributeByName(notBeforeQNameWithNS);
Attribute notAfterAttribute = conditionsElement.getAttributeByName(notAfterQName);
if (notAfterAttribute == null)
notAfterAttribute = conditionsElement.getAttributeByName(notAfterQNameWithNS);
if (notBeforeAttribute != null) {
String notBeforeValue = StaxParserUtil.getAttributeValue(notBeforeAttribute);
conditions.setNotBefore(XMLTimeUtil.parse(notBeforeValue));
}
if (notAfterAttribute != null) {
String notAfterValue = StaxParserUtil.getAttributeValue(notAfterAttribute);
conditions.setNotOnOrAfter(XMLTimeUtil.parse(notAfterValue));
}
// Let us find additional elements
while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
EndElement nextEndElement = (EndElement) xmlEvent;
if (StaxParserUtil.matches(nextEndElement, JBossSAMLConstants.CONDITIONS.get())) {
nextEndElement = StaxParserUtil.getNextEndElement(xmlEventReader);
break;
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_END_ELEMENT
+ StaxParserUtil.getEndElementName(nextEndElement));
}
String tag = null;
if (xmlEvent instanceof StartElement) {
StartElement peekedElement = (StartElement) xmlEvent;
tag = StaxParserUtil.getStartElementName(peekedElement);
}
if (JBossSAMLConstants.AUDIENCE_RESTRICTION.get().equals(tag)) {
AudienceRestrictionType audienceRestriction = getAudienceRestriction(xmlEventReader);
conditions.addCondition(audienceRestriction);
} else if (JBossSAMLConstants.ONE_TIME_USE.get().equals(tag)) {
// just parses the onetimeuse tag. until now PL has no support for onetimeuse conditions.
StaxParserUtil.getNextStartElement(xmlEventReader);
OneTimeUseType oneTimeUseCondition = new OneTimeUseType();
conditions.addCondition(oneTimeUseCondition);
// Get the end tag
EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader);
StaxParserUtil.matches(endElement, JBossSAMLConstants.ONE_TIME_USE.get());
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_TAG + tag + "::location=" + xmlEvent.getLocation());
}
return conditions;
}
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
String nsURI = qname.getNamespaceURI();
String localPart = qname.getLocalPart();
return nsURI.equals(JBossSAMLURIConstants.ASSERTION_NSURI.get())
&& localPart.equals(JBossSAMLConstants.CONDITIONS.get());
}
/**
* Parse the <audiencerestriction/> element
*
* @param xmlEventReader
*
* @return
*
* @throws ParsingException
*/
private AudienceRestrictionType getAudienceRestriction(XMLEventReader xmlEventReader) throws ParsingException {
StartElement audienceRestElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.matches(audienceRestElement, JBossSAMLConstants.AUDIENCE_RESTRICTION.get());
AudienceRestrictionType audience = new AudienceRestrictionType();
while (xmlEventReader.hasNext()) {
StartElement audienceElement = StaxParserUtil.getNextStartElement(xmlEventReader);
if (!StaxParserUtil.matches(audienceElement, JBossSAMLConstants.AUDIENCE.get()))
break;
if (!StaxParserUtil.hasTextAhead(xmlEventReader))
throw new ParsingException(ErrorCodes.EXPECTED_TAG + "audienceValue");
String audienceValue = StaxParserUtil.getElementText(xmlEventReader);
audience.addAudience(URI.create(audienceValue));
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) xmlEvent;
if (StaxParserUtil.matches(endElement, JBossSAMLConstants.AUDIENCE_RESTRICTION.get())) {
StaxParserUtil.getNextEvent(xmlEventReader); // Just get the end element
break;
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_END_ELEMENT + StaxParserUtil.getEndElementName(endElement));
}
}
return audience;
}
}

View file

@ -1,82 +0,0 @@
/*
* 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;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import org.keycloak.dom.saml.v2.protocol.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.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil;
/**
* Parses &lt;samlp:Extensions&gt; SAML2 element into series of DOM nodes.
*
* @author hmlnarik
*/
public class SAMLExtensionsParser implements ParserNamespaceSupport {
private static final String EXTENSIONS = JBossSAMLConstants.EXTENSIONS.get();
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
@Override
public ExtensionsType parse(XMLEventReader xmlEventReader) throws ParsingException {
// Get the startelement
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, EXTENSIONS);
ExtensionsType extensions = new ExtensionsType();
while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) xmlEvent;
if (StaxParserUtil.matches(endElement, EXTENSIONS)) {
endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
break;
} else
throw logger.parserUnknownEndElement(StaxParserUtil.getEndElementName(endElement));
}
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
extensions.addExtension(StaxParserUtil.getDOMElement(xmlEventReader));
}
return extensions;
}
@Override
public boolean supports(QName qname) {
String nsURI = qname.getNamespaceURI();
String localPart = qname.getLocalPart();
return nsURI.equals(JBossSAMLURIConstants.PROTOCOL_NSURI.get())
&& localPart.equals(JBossSAMLConstants.EXTENSIONS.get());
}
}

View file

@ -16,113 +16,118 @@
*/ */
package org.keycloak.saml.processing.core.parsers.saml; package org.keycloak.saml.processing.core.parsers.saml;
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;
import org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLArtifactResolveParser;
import org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLArtifactResponseParser;
import org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLResponseParser;
import org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLAuthNRequestParser;
import org.keycloak.saml.common.ErrorCodes; import org.keycloak.saml.common.ErrorCodes;
import org.keycloak.saml.common.constants.JBossSAMLConstants; 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.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.AbstractParser; import org.keycloak.saml.common.parsers.AbstractParser;
import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionParser;
import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLEntitiesDescriptorParser; import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLEntitiesDescriptorParser;
import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLEntityDescriptorParser; import org.keycloak.saml.processing.core.parsers.saml.metadata.SAMLEntityDescriptorParser;
import org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLProtocolQNames;
import org.keycloak.saml.processing.core.saml.v1.SAML11Constants; import org.keycloak.saml.processing.core.saml.v1.SAML11Constants;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement; import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent; import javax.xml.stream.events.XMLEvent;
import org.keycloak.saml.common.parsers.StaxParser;
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionQNames;
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAuthnStatementParser;
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLEncryptedAssertionParser;
import java.io.InputStream;
/** /**
* Parse SAML payload * Parse SAML payload
* *
* @author Anil.Saldhana@redhat.com
* @since Oct 12, 2010 * @since Oct 12, 2010
*/ */
public class SAMLParser extends AbstractParser { 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();
private static final QName SAML_11_ASSERTION = new QName(SAML11Constants.ASSERTION_11_NSURI, JBossSAMLConstants.ASSERTION.get());
private static final QName SAML_11_ENCRYPTED_ASSERTION = new QName(SAML11Constants.ASSERTION_11_NSURI, JBossSAMLConstants.ENCRYPTED_ASSERTION.get());
private static final QName SAML_11_RESPONSE = new QName(SAML11Constants.ASSERTION_11_NSURI, JBossSAMLConstants.RESPONSE__PROTOCOL.get());
private static final QName SAML_11_REQUEST = new QName(SAML11Constants.ASSERTION_11_NSURI, JBossSAMLConstants.REQUEST.get());
// Since we have to support JDK 7, no lambdas are available
private interface ParserFactory {
public StaxParser create();
}
private static final Map<QName, ParserFactory> PARSERS = new HashMap<QName, ParserFactory>();
static {
PARSERS.put(SAML_11_ASSERTION, new ParserFactory() { @Override public StaxParser create() { return new SAML11AssertionParser(); }});
PARSERS.put(SAML_11_ENCRYPTED_ASSERTION, new ParserFactory() { @Override public StaxParser create() { return new SAML11AssertionParser(); }});
PARSERS.put(SAML_11_RESPONSE, new ParserFactory() { @Override public StaxParser create() { return SAML_11_RESPONSE_PARSER; }});
PARSERS.put(SAML_11_REQUEST, new ParserFactory() { @Override public StaxParser create() { return SAML_11_REQUEST_PARSER; }});
PARSERS.put(SAMLProtocolQNames.AUTHN_REQUEST.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLAuthNRequestParser.getInstance(); }});
PARSERS.put(SAMLProtocolQNames.RESPONSE.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLResponseParser.getInstance(); }});
PARSERS.put(SAMLProtocolQNames.LOGOUT_REQUEST.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLSloRequestParser.getInstance(); }});
PARSERS.put(SAMLProtocolQNames.LOGOUT_RESPONSE.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLSloResponseParser.getInstance(); }});
PARSERS.put(SAMLProtocolQNames.ARTIFACT_RESOLVE.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLArtifactResolveParser.getInstance(); }});
PARSERS.put(SAMLProtocolQNames.ARTIFACT_RESPONSE.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLArtifactResponseParser.getInstance(); }});
PARSERS.put(SAMLProtocolQNames.ASSERTION.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLAssertionParser.getInstance(); }});
PARSERS.put(SAMLProtocolQNames.ENCRYPTED_ASSERTION.getQName(),new ParserFactory() { @Override public StaxParser create() { return SAMLEncryptedAssertionParser.getInstance(); }});
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(SAMLProtocolQNames.ATTRIBUTE_QUERY.getQName(), new ParserFactory() { @Override public StaxParser create() { return SAMLAttributeQueryParser.getInstance(); }});
}
private static final SAMLParser INSTANCE = new SAMLParser();
public static SAMLParser getInstance() {
return INSTANCE;
}
protected SAMLParser() {
}
/** /**
* @see {@link org.keycloak.saml.common.parsers.ParserNamespaceSupport#parse(XMLEventReader)} * @see {@link org.keycloak.saml.common.parsers.ParserNamespaceSupport#parse(XMLEventReader)}
*/ */
@Override
public Object parse(XMLEventReader xmlEventReader) throws ParsingException { public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
while (xmlEventReader.hasNext()) { while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader); XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof StartElement) { if (xmlEvent instanceof StartElement) {
StartElement startElement = (StartElement) xmlEvent; StartElement startElement = (StartElement) xmlEvent;
QName startElementName = startElement.getName(); final QName name = startElement.getName();
String nsURI = startElementName.getNamespaceURI();
String localPart = startElementName.getLocalPart(); ParserFactory pf = PARSERS.get(name);
if (pf == null) {
throw logger.parserException(new RuntimeException(ErrorCodes.UNKNOWN_START_ELEMENT + name + "::location="
+ startElement.getLocation()));
}
String elementName = StaxParserUtil.getStartElementName(startElement); return pf.create().parse(xmlEventReader);
if (elementName.equalsIgnoreCase(JBossSAMLConstants.ASSERTION.get())
|| elementName.equals(JBossSAMLConstants.ENCRYPTED_ASSERTION.get())) {
if (nsURI.equals(SAML11Constants.ASSERTION_11_NSURI)) {
SAML11AssertionParser saml11AssertionParser = new SAML11AssertionParser();
return saml11AssertionParser.parse(xmlEventReader);
}
SAMLAssertionParser assertionParser = new SAMLAssertionParser();
return assertionParser.parse(xmlEventReader);
} else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
&& JBossSAMLConstants.AUTHN_REQUEST.get().equals(startElementName.getLocalPart())) {
SAMLAuthNRequestParser authNRequestParser = new SAMLAuthNRequestParser();
return authNRequestParser.parse(xmlEventReader);
} else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
&& JBossSAMLConstants.LOGOUT_REQUEST.get().equals(startElementName.getLocalPart())) {
SAMLSloRequestParser sloParser = new SAMLSloRequestParser();
return sloParser.parse(xmlEventReader);
} else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
&& JBossSAMLConstants.LOGOUT_RESPONSE.get().equals(startElementName.getLocalPart())) {
SAMLSloResponseParser sloParser = new SAMLSloResponseParser();
return sloParser.parse(xmlEventReader);
} else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
&& JBossSAMLConstants.RESPONSE.get().equals(startElementName.getLocalPart())) {
SAMLResponseParser responseParser = new SAMLResponseParser();
return responseParser.parse(xmlEventReader);
} else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
&& JBossSAMLConstants.REQUEST_ABSTRACT.get().equals(startElementName.getLocalPart())) {
String xsiTypeValue = StaxParserUtil.getXSITypeValue(startElement);
throw new RuntimeException(ErrorCodes.UNKNOWN_XSI + xsiTypeValue);
} else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
&& JBossSAMLConstants.ARTIFACT_RESOLVE.get().equals(startElementName.getLocalPart())) {
SAMLArtifactResolveParser artifactResolverParser = new SAMLArtifactResolveParser();
return artifactResolverParser.parse(xmlEventReader);
} else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
&& JBossSAMLConstants.ARTIFACT_RESPONSE.get().equals(startElementName.getLocalPart())) {
SAMLArtifactResponseParser responseParser = new SAMLArtifactResponseParser();
return responseParser.parse(xmlEventReader);
} else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
&& JBossSAMLConstants.ATTRIBUTE_QUERY.get().equals(startElementName.getLocalPart())) {
SAMLAttributeQueryParser responseParser = new SAMLAttributeQueryParser();
return responseParser.parse(xmlEventReader);
} else if (JBossSAMLConstants.ENTITY_DESCRIPTOR.get().equals(localPart)) {
SAMLEntityDescriptorParser entityDescriptorParser = new SAMLEntityDescriptorParser();
return entityDescriptorParser.parse(xmlEventReader);
} else if (JBossSAMLConstants.ENTITIES_DESCRIPTOR.get().equals(localPart)) {
SAMLEntitiesDescriptorParser entityDescriptorParser = new SAMLEntitiesDescriptorParser();
return entityDescriptorParser.parse(xmlEventReader);
} else if (SAML11Constants.PROTOCOL_11_NSURI.equals(nsURI)
&& JBossSAMLConstants.RESPONSE.get().equals(startElementName.getLocalPart())) {
SAML11ResponseParser responseParser = new SAML11ResponseParser();
return responseParser.parse(xmlEventReader);
} else if (SAML11Constants.PROTOCOL_11_NSURI.equals(nsURI)
&& SAML11Constants.REQUEST.equals(startElementName.getLocalPart())) {
SAML11RequestParser reqParser = new SAML11RequestParser();
return reqParser.parse(xmlEventReader);
} else
throw new RuntimeException(ErrorCodes.UNKNOWN_START_ELEMENT + elementName + "::location="
+ startElement.getLocation());
} else {
StaxParserUtil.getNextEvent(xmlEventReader);
} }
StaxParserUtil.getNextEvent(xmlEventReader);
} }
throw new RuntimeException(ErrorCodes.FAILED_PARSING + "SAML Parsing has failed"); throw new RuntimeException(ErrorCodes.FAILED_PARSING + "SAML Parsing has failed");
} }
/**
* @see {@link org.keycloak.saml.common.parsers.ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
return JBossSAMLURIConstants.ASSERTION_NSURI.get().equals(qname.getNamespaceURI());
}
} }

View file

@ -1,110 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import java.net.URI;
/**
* Base Class for SAML Request Parsing
*
* @author Anil.Saldhana@redhat.com
* @since Nov 2, 2010
*/
public abstract class SAMLRequestAbstractParser {
protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
protected String id;
protected String version;
protected XMLGregorianCalendar issueInstant;
protected void parseRequiredAttributes(StartElement startElement) throws ParsingException {
Attribute idAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.ID.get()));
if (idAttr == null)
throw logger.parserRequiredAttribute("ID");
id = StaxParserUtil.getAttributeValue(idAttr);
Attribute versionAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.VERSION.get()));
if (versionAttr == null)
throw logger.parserRequiredAttribute("Version");
version = StaxParserUtil.getAttributeValue(versionAttr);
Attribute issueInstantAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.ISSUE_INSTANT.get()));
if (issueInstantAttr == null)
throw logger.parserRequiredAttribute("IssueInstant");
issueInstant = XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(issueInstantAttr));
}
/**
* Parse the attributes that are common to all SAML Request Types
*
* @param startElement
* @param request
*
* @throws ParsingException
*/
protected void parseBaseAttributes(StartElement startElement, RequestAbstractType request) throws ParsingException {
Attribute destinationAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.DESTINATION.get()));
if (destinationAttr != null)
request.setDestination(URI.create(StaxParserUtil.getAttributeValue(destinationAttr)));
Attribute consent = startElement.getAttributeByName(new QName(JBossSAMLConstants.CONSENT.get()));
if (consent != null)
request.setConsent(StaxParserUtil.getAttributeValue(consent));
}
protected void parseCommonElements(StartElement startElement, XMLEventReader xmlEventReader, RequestAbstractType request)
throws ParsingException {
if (startElement == null)
throw logger.parserNullStartElement();
String elementName = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.ISSUER.get().equals(elementName)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
NameIDType issuer = new NameIDType();
issuer.setValue(StaxParserUtil.getElementText(xmlEventReader));
request.setIssuer(issuer);
} else if (JBossSAMLConstants.SIGNATURE.get().equals(elementName)) {
request.setSignature(StaxParserUtil.getDOMElement(xmlEventReader));
} else if (JBossSAMLConstants.EXTENSIONS.get().equals(elementName)) {
request.setExtensions(new SAMLExtensionsParser().parse(xmlEventReader));
}
}
protected SubjectType getSubject(XMLEventReader xmlEventReader) throws ParsingException {
SAMLSubjectParser subjectParser = new SAMLSubjectParser();
return (SubjectType) subjectParser.parse(xmlEventReader);
}
}

View file

@ -1,110 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.dom.saml.v2.protocol.ResponseType.RTChoiceType;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
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.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.w3c.dom.Element;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
/**
* Parse the SAML Response
*
* @author Anil.Saldhana@redhat.com
* @since Nov 2, 2010
*/
public class SAMLResponseParser extends SAMLStatusResponseTypeParser implements ParserNamespaceSupport {
private final String RESPONSE = JBossSAMLConstants.RESPONSE.get();
/**
* @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
*/
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
// Get the startelement
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, RESPONSE);
ResponseType response = (ResponseType) parseBaseAttributes(startElement);
while (xmlEventReader.hasNext()) {
// Let us peek at the next start element
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
String elementName = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.ISSUER.get().equals(elementName)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
NameIDType issuer = new NameIDType();
issuer.setValue(StaxParserUtil.getElementText(xmlEventReader));
response.setIssuer(issuer);
} else if (JBossSAMLConstants.SIGNATURE.get().equals(elementName)) {
Element sig = StaxParserUtil.getDOMElement(xmlEventReader);
response.setSignature(sig);
} else if (JBossSAMLConstants.ASSERTION.get().equals(elementName)) {
SAMLAssertionParser assertionParser = new SAMLAssertionParser();
response.addAssertion(new RTChoiceType((AssertionType) assertionParser.parse(xmlEventReader)));
} else if (JBossSAMLConstants.EXTENSIONS.get().equals(elementName)) {
SAMLExtensionsParser extensionsParser = new SAMLExtensionsParser();
response.setExtensions(extensionsParser.parse(xmlEventReader));
} else if (JBossSAMLConstants.STATUS.get().equals(elementName)) {
response.setStatus(parseStatus(xmlEventReader));
} else if (JBossSAMLConstants.ENCRYPTED_ASSERTION.get().equals(elementName)) {
Element encryptedAssertion = StaxParserUtil.getDOMElement(xmlEventReader);
response.addAssertion(new RTChoiceType(new EncryptedAssertionType(encryptedAssertion)));
} else
throw logger.parserUnknownTag(elementName, startElement.getLocation());
}
return response;
}
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
return JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(qname.getNamespaceURI())
&& RESPONSE.equals(qname.getLocalPart());
}
/**
* Parse the attributes at the response element
*
* @param startElement
*
* @return
*
* @throws org.keycloak.saml.common.exceptions.ConfigurationException
*/
protected StatusResponseType parseBaseAttributes(StartElement startElement) throws ParsingException {
ResponseType response = new ResponseType(super.parseBaseAttributes(startElement));
return response;
}
}

View file

@ -1,117 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_NSURI;
/**
* Parse the Single Log Out requests
*
* @author Anil.Saldhana@redhat.com
* @since Nov 3, 2010
*/
public class SAMLSloRequestParser extends SAMLRequestAbstractParser implements ParserNamespaceSupport {
/**
* @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
*/
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
// Get the startelement
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.LOGOUT_REQUEST.get());
LogoutRequestType logoutRequest = parseBaseAttributes(startElement);
while (xmlEventReader.hasNext()) {
// Let us peek at the next start element
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
String elementName = StaxParserUtil.getStartElementName(startElement);
parseCommonElements(startElement, xmlEventReader, logoutRequest);
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
elementName = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.SESSION_INDEX.get().equals(elementName)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
logoutRequest.addSessionIndex(StaxParserUtil.getElementText(xmlEventReader));
} else if (JBossSAMLConstants.NAMEID.get().equals(elementName)) {
NameIDType nameID = SAMLParserUtil.parseNameIDType(xmlEventReader);
logoutRequest.setNameID(nameID);
} else if (JBossSAMLConstants.ISSUER.get().equals(elementName)) {
continue;
} else if (JBossSAMLConstants.SIGNATURE.get().equals(elementName)) {
continue;
} else if (JBossSAMLConstants.EXTENSIONS.get().equals(elementName)) {
continue;
} else
throw logger.parserUnknownTag(elementName, startElement.getLocation());
}
return logoutRequest;
}
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
return PROTOCOL_NSURI.get().equals(qname.getNamespaceURI())
&& JBossSAMLConstants.LOGOUT_REQUEST.get().equals(qname.getLocalPart());
}
/**
* Parse the attributes at the log out request element
*
* @param startElement
*
* @return
*
* @throws ParsingException
*/
private LogoutRequestType parseBaseAttributes(StartElement startElement) throws ParsingException {
super.parseRequiredAttributes(startElement);
LogoutRequestType logoutRequest = new LogoutRequestType(id, issueInstant);
// Let us get the attributes
super.parseBaseAttributes(startElement, logoutRequest);
Attribute reason = startElement.getAttributeByName(new QName(JBossSAMLConstants.REASON.get()));
if (reason != null)
logoutRequest.setReason(StaxParserUtil.getAttributeValue(reason));
Attribute notOnOrAfter = startElement.getAttributeByName(new QName(JBossSAMLConstants.NOT_ON_OR_AFTER.get()));
if (notOnOrAfter != null)
logoutRequest.setNotOnOrAfter(XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(notOnOrAfter)));
return logoutRequest;
}
}

View file

@ -1,79 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
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.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import static org.keycloak.saml.common.constants.JBossSAMLConstants.LOGOUT_RESPONSE;
/**
* Parse the SLO Response
*
* @author Anil.Saldhana@redhat.com
* @since Nov 3, 2010
*/
public class SAMLSloResponseParser extends SAMLStatusResponseTypeParser implements ParserNamespaceSupport {
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
// Get the startelement
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, LOGOUT_RESPONSE.get());
StatusResponseType response = parseBaseAttributes(startElement);
while (xmlEventReader.hasNext()) {
// Let us peek at the next start element
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
String elementName = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.ISSUER.get().equals(elementName)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
NameIDType issuer = new NameIDType();
issuer.setValue(StaxParserUtil.getElementText(xmlEventReader));
response.setIssuer(issuer);
} else if (JBossSAMLConstants.SIGNATURE.get().equals(elementName)) {
StaxParserUtil.bypassElementBlock(xmlEventReader, JBossSAMLConstants.SIGNATURE);
} else if (JBossSAMLConstants.EXTENSIONS.get().equals(elementName)) {
SAMLExtensionsParser extensionsParser = new SAMLExtensionsParser();
response.setExtensions(extensionsParser.parse(xmlEventReader));
} else if (JBossSAMLConstants.STATUS.get().equals(elementName)) {
response.setStatus(parseStatus(xmlEventReader));
}
}
return response;
}
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
return JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(qname.getNamespaceURI())
&& LOGOUT_RESPONSE.get().equals(qname.getLocalPart());
}
}

View file

@ -1,186 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.protocol.StatusCodeType;
import org.keycloak.dom.saml.v2.protocol.StatusDetailType;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
import org.keycloak.dom.saml.v2.protocol.StatusType;
import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.common.util.StringUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import org.w3c.dom.Element;
import javax.xml.datatype.XMLGregorianCalendar;
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.net.URI;
/**
* Base Class for all Response Type parsing for SAML2
*
* @author Anil.Saldhana@redhat.com
* @since Nov 2, 2010
*/
public abstract class SAMLStatusResponseTypeParser {
protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
/**
* Parse the attributes that are common to all SAML Response Types
*
* @param startElement
* @param response
*
* @throws org.keycloak.saml.common.exceptions.ParsingException
*/
protected StatusResponseType parseBaseAttributes(StartElement startElement) throws ParsingException {
Attribute idAttr = startElement.getAttributeByName(new QName(JBossSAMLConstants.ID.get()));
if (idAttr == null)
throw logger.parserRequiredAttribute("ID");
String id = StaxParserUtil.getAttributeValue(idAttr);
Attribute version = startElement.getAttributeByName(new QName(JBossSAMLConstants.VERSION.get()));
if (version == null)
throw logger.parserRequiredAttribute("Version");
StringUtil.match(JBossSAMLConstants.VERSION_2_0.get(), StaxParserUtil.getAttributeValue(version));
Attribute issueInstant = startElement.getAttributeByName(new QName(JBossSAMLConstants.ISSUE_INSTANT.get()));
if (issueInstant == null)
throw logger.parserRequiredAttribute("IssueInstant");
XMLGregorianCalendar issueInstantVal = XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(issueInstant));
StatusResponseType response = new StatusResponseType(id, issueInstantVal);
Attribute destination = startElement.getAttributeByName(new QName(JBossSAMLConstants.DESTINATION.get()));
if (destination != null)
response.setDestination(StaxParserUtil.getAttributeValue(destination));
Attribute consent = startElement.getAttributeByName(new QName(JBossSAMLConstants.CONSENT.get()));
if (consent != null)
response.setConsent(StaxParserUtil.getAttributeValue(consent));
Attribute inResponseTo = startElement.getAttributeByName(new QName(JBossSAMLConstants.IN_RESPONSE_TO.get()));
if (inResponseTo != null)
response.setInResponseTo(StaxParserUtil.getAttributeValue(inResponseTo));
return response;
}
/**
* Parse the status element
*
* @param xmlEventReader
*
* @return
*
* @throws ParsingException
*/
protected StatusType parseStatus(XMLEventReader xmlEventReader) throws ParsingException {
// Get the Start Element
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String STATUS = JBossSAMLConstants.STATUS.get();
StaxParserUtil.validate(startElement, STATUS);
StatusType status = new StatusType();
while (xmlEventReader.hasNext()) {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
QName startElementName = startElement.getName();
String elementTag = startElementName.getLocalPart();
StatusCodeType statusCode = new StatusCodeType();
if (JBossSAMLConstants.STATUS_CODE.get().equals(elementTag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
if (startElement == null)
break;
Attribute valueAttr = startElement.getAttributeByName(new QName("Value"));
if (valueAttr != null) {
statusCode.setValue(URI.create(StaxParserUtil.getAttributeValue(valueAttr)));
}
status.setStatusCode(statusCode);
// Peek at the next start element to see if it is status code
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) {
// Go to Status code end element.
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
if (endElement != null) {
StaxParserUtil.validate(endElement, JBossSAMLConstants.STATUS_CODE.get());
}
continue;
}
elementTag = startElement.getName().getLocalPart();
if (JBossSAMLConstants.STATUS_CODE.get().equals(elementTag)) {
StatusCodeType subStatusCodeType = new StatusCodeType();
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
Attribute subValueAttr = startElement.getAttributeByName(new QName("Value"));
if (subValueAttr != null) {
subStatusCodeType.setValue(URI.create(StaxParserUtil.getAttributeValue(subValueAttr)));
}
statusCode.setStatusCode(subStatusCodeType);
// Go to Status code end element.
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
StaxParserUtil.validate(endElement, JBossSAMLConstants.STATUS_CODE.get());
continue;
}
}
if (JBossSAMLConstants.STATUS_MESSAGE.get().equals(elementTag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
if (startElement == null)
break;
status.setStatusMessage(StaxParserUtil.getElementText(xmlEventReader));
}
if (JBossSAMLConstants.STATUS_DETAIL.get().equals(elementTag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
if (startElement == null)
break;
Element domElement = StaxParserUtil.getDOMElement(xmlEventReader);
StatusDetailType statusDetailType = new StatusDetailType();
statusDetailType.addStatusDetail(domElement);
status.setStatusDetail(statusDetailType);
}
// Get the next end element
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
if (StaxParserUtil.matches(endElement, STATUS))
break;
else
throw logger.parserUnknownEndElement(StaxParserUtil.getEndElementName(endElement));
} else
break;
}
return status;
}
}

View file

@ -1,205 +0,0 @@
/*
* 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;
import org.keycloak.dom.saml.v2.assertion.EncryptedElementType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationDataType;
import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType;
import org.keycloak.saml.common.ErrorCodes;
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.constants.WSTrustConstants;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.ParserNamespaceSupport;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
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;
/**
* Parse the saml subject
*
* @author Anil.Saldhana@redhat.com
* @since Oct 12, 2010
*/
public class SAMLSubjectParser implements ParserNamespaceSupport {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
/**
* @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
*/
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
StaxParserUtil.getNextEvent(xmlEventReader);
SubjectType subject = new SubjectType();
// Peek at the next event
while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) xmlEvent;
if (StaxParserUtil.matches(endElement, JBossSAMLConstants.SUBJECT.get())) {
endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
break;
} else
throw logger.parserUnknownEndElement(StaxParserUtil.getEndElementName(endElement));
}
StartElement peekedElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (peekedElement == null)
break;
String tag = StaxParserUtil.getStartElementName(peekedElement);
if (JBossSAMLConstants.NAMEID.get().equalsIgnoreCase(tag)) {
NameIDType nameID = SAMLParserUtil.parseNameIDType(xmlEventReader);
SubjectType.STSubType subType = new SubjectType.STSubType();
subType.addBaseID(nameID);
subject.setSubType(subType);
} else if (JBossSAMLConstants.BASEID.get().equalsIgnoreCase(tag)) {
throw new ParsingException(ErrorCodes.UNSUPPORTED_TYPE + JBossSAMLConstants.BASEID.get());
} else if (JBossSAMLConstants.ENCRYPTED_ID.get().equals(tag)) {
Element domElement = StaxParserUtil.getDOMElement(xmlEventReader);
SubjectType.STSubType subType = new SubjectType.STSubType();
subType.setEncryptedID(new EncryptedElementType(domElement));
subject.setSubType(subType);
} else if (JBossSAMLConstants.SUBJECT_CONFIRMATION.get().equalsIgnoreCase(tag)) {
StartElement subjectConfirmationElement = StaxParserUtil.getNextStartElement(xmlEventReader);
Attribute method = subjectConfirmationElement.getAttributeByName(new QName(JBossSAMLConstants.METHOD.get()));
SubjectConfirmationType subjectConfirmationType = new SubjectConfirmationType();
if (method != null) {
subjectConfirmationType.setMethod(StaxParserUtil.getAttributeValue(method));
}
// There may be additional things under subject confirmation
xmlEvent = StaxParserUtil.peek(xmlEventReader);
while (xmlEventReader.hasNext()) {
xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
EndElement endElement = (EndElement) xmlEvent;
if (StaxParserUtil.matches(endElement, JBossSAMLConstants.SUBJECT_CONFIRMATION.get())) {
StaxParserUtil.getNextEndElement(xmlEventReader);
break;
} else
throw logger.parserUnknownEndElement(StaxParserUtil.getEndElementName(endElement));
}
peekedElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (peekedElement == null)
break;
String startTag = StaxParserUtil.getStartElementName(peekedElement);
if (startTag.equals(JBossSAMLConstants.NAMEID.get())) {
NameIDType nameID = SAMLParserUtil.parseNameIDType(xmlEventReader);
subjectConfirmationType.setNameID(nameID);
} else if (JBossSAMLConstants.BASEID.get().equalsIgnoreCase(tag)) {
throw logger.unsupportedType(JBossSAMLConstants.BASEID.get());
} else if (JBossSAMLConstants.ENCRYPTED_ID.get().equals(tag)) {
Element domElement = StaxParserUtil.getDOMElement(xmlEventReader);
subjectConfirmationType.setEncryptedID(new EncryptedElementType(domElement));
} else if (startTag.equals(JBossSAMLConstants.SUBJECT_CONFIRMATION_DATA.get())) {
SubjectConfirmationDataType subjectConfirmationData = parseSubjectConfirmationData(xmlEventReader);
subjectConfirmationType.setSubjectConfirmationData(subjectConfirmationData);
}
}
subject.addConfirmation(subjectConfirmationType);
} else
throw logger.parserUnknownTag(tag, peekedElement.getLocation());
}
return subject;
}
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
public boolean supports(QName qname) {
String nsURI = qname.getNamespaceURI();
String localPart = qname.getLocalPart();
return nsURI.equals(JBossSAMLURIConstants.ASSERTION_NSURI.get()) && localPart.equals(JBossSAMLConstants.SUBJECT.get());
}
private SubjectConfirmationDataType parseSubjectConfirmationData(XMLEventReader xmlEventReader) throws ParsingException {
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.SUBJECT_CONFIRMATION_DATA.get());
SubjectConfirmationDataType subjectConfirmationData = new SubjectConfirmationDataType();
Attribute inResponseTo = startElement.getAttributeByName(new QName(JBossSAMLConstants.IN_RESPONSE_TO.get()));
if (inResponseTo != null) {
subjectConfirmationData.setInResponseTo(StaxParserUtil.getAttributeValue(inResponseTo));
}
Attribute notBefore = startElement.getAttributeByName(new QName(JBossSAMLConstants.NOT_BEFORE.get()));
if (notBefore != null) {
subjectConfirmationData.setNotBefore(XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(notBefore)));
}
Attribute notOnOrAfter = startElement.getAttributeByName(new QName(JBossSAMLConstants.NOT_ON_OR_AFTER.get()));
if (notOnOrAfter != null) {
subjectConfirmationData.setNotOnOrAfter(XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(notOnOrAfter)));
}
Attribute recipient = startElement.getAttributeByName(new QName(JBossSAMLConstants.RECIPIENT.get()));
if (recipient != null) {
subjectConfirmationData.setRecipient(StaxParserUtil.getAttributeValue(recipient));
}
Attribute address = startElement.getAttributeByName(new QName(JBossSAMLConstants.ADDRESS.get()));
if (address != null) {
subjectConfirmationData.setAddress(StaxParserUtil.getAttributeValue(address));
}
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (!(xmlEvent instanceof EndElement)) {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
String tag = StaxParserUtil.getStartElementName(startElement);
if (tag.equals(WSTrustConstants.XMLDSig.KEYINFO)) {
KeyInfoType keyInfo = SAMLParserUtil.parseKeyInfo(xmlEventReader);
subjectConfirmationData.setAnyType(keyInfo);
} else if (tag.equals(WSTrustConstants.XMLEnc.ENCRYPTED_KEY)) {
subjectConfirmationData.setAnyType(StaxParserUtil.getDOMElement(xmlEventReader));
} else
throw logger.parserUnknownTag(tag, startElement.getLocation());
}
// Get the end tag
EndElement endElement = (EndElement) StaxParserUtil.getNextEvent(xmlEventReader);
StaxParserUtil.matches(endElement, JBossSAMLConstants.SUBJECT_CONFIRMATION_DATA.get());
return subjectConfirmationData;
}
}

View file

@ -0,0 +1,40 @@
/*
* 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.assertion;
import org.keycloak.saml.common.parsers.AbstractStaxParser;
import org.keycloak.saml.processing.core.parsers.util.QNameEnumLookup;
import javax.xml.namespace.QName;
/**
*
* @author hmlnarik
*/
public abstract class AbstractStaxSamlAssertionParser<T> extends AbstractStaxParser<T, SAMLAssertionQNames> {
protected static final QNameEnumLookup<SAMLAssertionQNames> LOOKUP = new QNameEnumLookup(SAMLAssertionQNames.values());
public AbstractStaxSamlAssertionParser(SAMLAssertionQNames expectedStartElement) {
super(expectedStartElement.getQName(), SAMLAssertionQNames.UNKNOWN_ELEMENT);
}
@Override
protected SAMLAssertionQNames getElementFromName(QName name) {
return LOOKUP.from(name);
}
}

View file

@ -0,0 +1,103 @@
/*
* 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.assertion;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.saml.common.ErrorCodes;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
/**
* Parse the saml assertion
*
* @since Oct 12, 2010
*/
public class SAMLAssertionParser extends AbstractStaxSamlAssertionParser<AssertionType> {
private static final String VERSION_2_0 = "2.0";
private static final SAMLAssertionParser INSTANCE = new SAMLAssertionParser();
private SAMLAssertionParser() {
super(SAMLAssertionQNames.ASSERTION);
}
public static SAMLAssertionParser getInstance() {
return INSTANCE;
}
@Override
protected AssertionType instantiateElement(XMLEventReader xmlEventReader, StartElement nextElement) throws ParsingException {
SAMLParserUtil.validateAttributeValue(nextElement, SAMLAssertionQNames.ATTR_VERSION, VERSION_2_0);
String id = StaxParserUtil.getRequiredAttributeValue(nextElement, SAMLAssertionQNames.ATTR_ID);
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getRequiredAttributeValue(nextElement, SAMLAssertionQNames.ATTR_ISSUE_INSTANT));
return new AssertionType(id, issueInstant);
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, AssertionType target, SAMLAssertionQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case ISSUER:
target.setIssuer(SAMLParserUtil.parseNameIDType(xmlEventReader));
break;
case SIGNATURE:
target.setSignature(StaxParserUtil.getDOMElement(xmlEventReader));
break;
case SUBJECT:
target.setSubject(SAMLSubjectParser.getInstance().parse(xmlEventReader));
break;
case CONDITIONS:
target.setConditions(SAMLConditionsParser.getInstance().parse(xmlEventReader));
break;
case ADVICE:
StaxParserUtil.bypassElementBlock(xmlEventReader);
// Ignored
break;
case STATEMENT:
elementDetail = StaxParserUtil.getNextStartElement(xmlEventReader);
String xsiTypeValue = StaxParserUtil.getXSITypeValue(elementDetail);
throw new RuntimeException(ErrorCodes.UNKNOWN_XSI + xsiTypeValue);
case AUTHN_STATEMENT:
target.addStatement(SAMLAuthnStatementParser.getInstance().parse(xmlEventReader));
break;
case AUTHZ_DECISION_STATEMENT:
StaxParserUtil.bypassElementBlock(xmlEventReader);
// Ignored
break;
case ATTRIBUTE_STATEMENT:
target.addStatement(SAMLAttributeStatementParser.getInstance().parse(xmlEventReader));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,116 @@
/*
* 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.assertion;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.processing.core.parsers.saml.xmldsig.XmlDSigQNames;
import org.keycloak.saml.processing.core.parsers.util.HasQName;
import javax.xml.namespace.QName;
/**
* Elements and attribute names from saml-schema-assertion-2.0.xsd
* @author hmlnarik
*/
public enum SAMLAssertionQNames implements HasQName {
ACTION("Action"),
ADVICE("Advice"),
ASSERTION("Assertion"),
ASSERTION_ID_REF("AssertionIDRef"),
ASSERTION_URI_REF("AssertionURIRef"),
ATTRIBUTE("Attribute"),
ATTRIBUTE_STATEMENT("AttributeStatement"),
ATTRIBUTE_VALUE("AttributeValue"),
AUDIENCE("Audience"),
AUDIENCE_RESTRICTION("AudienceRestriction"),
AUTHENTICATING_AUTHORITY("AuthenticatingAuthority"),
AUTHN_CONTEXT("AuthnContext"),
AUTHN_CONTEXT_CLASS_REF("AuthnContextClassRef"),
AUTHN_CONTEXT_DECL("AuthnContextDecl"),
AUTHN_CONTEXT_DECL_REF("AuthnContextDeclRef"),
AUTHN_STATEMENT("AuthnStatement"),
AUTHZ_DECISION_STATEMENT("AuthzDecisionStatement"),
BASEID("BaseID"),
CONDITION("Condition"),
CONDITIONS("Conditions"),
ENCRYPTED_ASSERTION("EncryptedAssertion"),
ENCRYPTED_ATTRIBUTE("EncryptedAttribute"),
ENCRYPTED_ID("EncryptedID"),
EVIDENCE("Evidence"),
ISSUER("Issuer"),
NAMEID("NameID"),
ONE_TIME_USE("OneTimeUse"),
PROXY_RESTRICTION("ProxyRestriction"),
STATEMENT("Statement"),
SUBJECT_CONFIRMATION_DATA("SubjectConfirmationData"),
SUBJECT_CONFIRMATION("SubjectConfirmation"),
SUBJECT_LOCALITY("SubjectLocality"),
SUBJECT("Subject"),
// Attribute names
ATTR_ADDRESS(null, "Address"),
ATTR_AUTHN_INSTANT(null, "AuthnInstant"),
ATTR_DNS_NAME(null, "DNSName"),
ATTR_FORMAT(null, "Format"),
ATTR_FRIENDLY_NAME(null, "FriendlyName"),
ATTR_ID(null, "ID"),
ATTR_IN_RESPONSE_TO(null, "InResponseTo"),
ATTR_ISSUE_INSTANT(null, "IssueInstant"),
ATTR_METHOD(null, "Method"),
ATTR_NAME(null, "Name"),
ATTR_NAME_FORMAT(null, "NameFormat"),
ATTR_NAME_QUALIFIER(null, "NameQualifier"),
ATTR_NOT_BEFORE(null, "NotBefore"),
ATTR_NOT_ON_OR_AFTER(null, "NotOnOrAfter"),
ATTR_RECIPIENT(null, "Recipient"),
ATTR_SESSION_INDEX(null, "SessionIndex"),
ATTR_SP_PROVIDED_ID(null, "SPProvidedID"),
ATTR_SP_NAME_QUALIFIER(null, "SPNameQualifier"),
ATTR_VERSION(null, "Version"),
// Elements from other namespaces that can be direct subelements of this namespace's elements
KEY_INFO(XmlDSigQNames.KEY_INFO),
SIGNATURE(XmlDSigQNames.SIGNATURE),
ATTR_X500_ENCODING(JBossSAMLURIConstants.X500_NSURI, "Encoding"),
UNKNOWN_ELEMENT("")
;
private final QName qName;
private SAMLAssertionQNames(String localName) {
this(JBossSAMLURIConstants.ASSERTION_NSURI, localName);
}
private SAMLAssertionQNames(HasQName source) {
this.qName = source.getQName();
}
private SAMLAssertionQNames(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);
}
}

View file

@ -0,0 +1,69 @@
/*
* 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.assertion;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
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;
/**
* Parse the <conditions> in the saml assertion
*
* @since Oct 14, 2010
*/
public class SAMLAttributeParser extends AbstractStaxSamlAssertionParser<AttributeType> {
private static final SAMLAttributeParser INSTANCE = new SAMLAttributeParser();
private SAMLAttributeParser() {
super(SAMLAssertionQNames.ATTRIBUTE);
}
public static SAMLAttributeParser getInstance() {
return INSTANCE;
}
@Override
protected AttributeType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
String name = StaxParserUtil.getRequiredAttributeValue(element, SAMLAssertionQNames.ATTR_NAME);
final AttributeType attribute = new AttributeType(name);
attribute.setFriendlyName(StaxParserUtil.getAttributeValue(element, SAMLAssertionQNames.ATTR_FRIENDLY_NAME));
attribute.setNameFormat(StaxParserUtil.getAttributeValue(element, SAMLAssertionQNames.ATTR_NAME_FORMAT));
final String x500Encoding = StaxParserUtil.getAttributeValue(element, SAMLAssertionQNames.ATTR_X500_ENCODING);
if (x500Encoding != null) {
attribute.getOtherAttributes().put(SAMLAssertionQNames.ATTR_X500_ENCODING.getQName(), x500Encoding);
}
return attribute;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, AttributeType target, SAMLAssertionQNames 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());
}
}
}

View file

@ -0,0 +1,59 @@
/*
* 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.assertion;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType.ASTChoiceType;
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;
/**
* Parse the <conditions> in the saml assertion
*
* @since Oct 14, 2010
*/
public class SAMLAttributeStatementParser extends AbstractStaxSamlAssertionParser<AttributeStatementType> {
private static final SAMLAttributeStatementParser INSTANCE = new SAMLAttributeStatementParser();
private SAMLAttributeStatementParser() {
super(SAMLAssertionQNames.ATTRIBUTE_STATEMENT);
}
public static SAMLAttributeStatementParser getInstance() {
return INSTANCE;
}
@Override
protected AttributeStatementType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new AttributeStatementType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, AttributeStatementType target, SAMLAssertionQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case ATTRIBUTE:
target.addAttribute(new ASTChoiceType(SAMLAttributeParser.getInstance().parse(xmlEventReader)));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,138 @@
/*
* 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.assertion;
import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.StaxParser;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import java.io.StringWriter;
import java.util.Objects;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
/**
*
*/
public class SAMLAttributeValueParser implements StaxParser {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
private static final SAMLAttributeValueParser INSTANCE = new SAMLAttributeValueParser();
private static final QName NIL = new QName(JBossSAMLURIConstants.XSI_NSURI.get(), "nil", JBossSAMLURIConstants.XSI_PREFIX.get());
private static final QName XSI_TYPE = new QName(JBossSAMLURIConstants.XSI_NSURI.get(), "type", JBossSAMLURIConstants.XSI_PREFIX.get());
public static SAMLAttributeValueParser getInstance() {
return INSTANCE;
}
@Override
public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
StartElement element = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(element, SAMLAssertionQNames.ATTRIBUTE_VALUE.getQName());
Attribute nil = element.getAttributeByName(NIL);
if (nil != null) {
String nilValue = StaxParserUtil.getAttributeValue(nil);
if (nilValue != null && (nilValue.equalsIgnoreCase("true") || nilValue.equals("1"))) {
String elementText = StaxParserUtil.getElementText(xmlEventReader);
if (elementText == null || elementText.isEmpty()) {
return null;
} else {
throw logger.nullValueError("nil attribute is not in SAML20 format");
}
} else {
throw logger.parserRequiredAttribute(JBossSAMLURIConstants.XSI_PREFIX.get() + ":nil");
}
}
Attribute type = element.getAttributeByName(XSI_TYPE);
if (type == null) {
if (StaxParserUtil.hasTextAhead(xmlEventReader)) {
return StaxParserUtil.getElementText(xmlEventReader);
}
// Else we may have Child Element
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof StartElement) {
element = (StartElement) xmlEvent;
final QName qName = element.getName();
if (Objects.equals(qName, SAMLAssertionQNames.NAMEID.getQName())) {
return SAMLParserUtil.parseNameIDType(xmlEventReader);
}
} else if (xmlEvent instanceof EndElement) {
return "";
}
// when no type attribute assigned -> assume anyType
return parseAnyTypeAsString(xmlEventReader);
}
// RK Added an additional type check for base64Binary type as calheers is passing this type
String typeValue = StaxParserUtil.getAttributeValue(type);
if (typeValue.contains(":string")) {
return StaxParserUtil.getElementText(xmlEventReader);
} else if (typeValue.contains(":anyType")) {
return parseAnyTypeAsString(xmlEventReader);
} else if(typeValue.contains(":base64Binary")){
return StaxParserUtil.getElementText(xmlEventReader);
} else if(typeValue.contains(":boolean")){
return StaxParserUtil.getElementText(xmlEventReader);
}
throw logger.parserUnknownXSI(typeValue);
}
public static String parseAnyTypeAsString(XMLEventReader xmlEventReader) throws ParsingException {
try {
XMLEvent event = xmlEventReader.peek();
if (event.isStartElement()) {
event = xmlEventReader.nextTag();
StringWriter sw = new StringWriter();
XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(sw);
//QName tagName = event.asStartElement().getName();
int tagLevel = 1;
do {
writer.add(event);
event = (XMLEvent) xmlEventReader.next();
if (event.isStartElement()) {
tagLevel++;
}
if (event.isEndElement()) {
tagLevel--;
}
} while (xmlEventReader.hasNext() && tagLevel > 0);
writer.add(event);
writer.flush();
return sw.toString();
} else {
return StaxParserUtil.getElementText(xmlEventReader);
}
} catch (Exception e) {
throw logger.parserError(e);
}
}
}

View file

@ -0,0 +1,61 @@
/*
* 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.assertion;
import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import java.net.URI;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
/**
* Parse the <conditions> in the saml assertion
*
* @since Oct 14, 2010
*/
public class SAMLAudienceRestrictionParser extends AbstractStaxSamlAssertionParser<AudienceRestrictionType> {
private static final SAMLAudienceRestrictionParser INSTANCE = new SAMLAudienceRestrictionParser();
private SAMLAudienceRestrictionParser() {
super(SAMLAssertionQNames.AUDIENCE_RESTRICTION);
}
public static SAMLAudienceRestrictionParser getInstance() {
return INSTANCE;
}
@Override
protected AudienceRestrictionType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new AudienceRestrictionType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, AudienceRestrictionType 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

@ -0,0 +1,94 @@
/*
* 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.assertion;
import org.keycloak.dom.saml.v2.assertion.AuthnContextClassRefType;
import org.keycloak.dom.saml.v2.assertion.AuthnContextDeclRefType;
import org.keycloak.dom.saml.v2.assertion.AuthnContextDeclType;
import org.keycloak.dom.saml.v2.assertion.AuthnContextType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import java.net.URI;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import org.w3c.dom.Element;
/**
* Parse the <conditions> in the saml assertion
*
* @since Oct 14, 2010
*/
public class SAMLAuthnContextParser extends AbstractStaxSamlAssertionParser<AuthnContextType> {
private static final SAMLAuthnContextParser INSTANCE = new SAMLAuthnContextParser();
private SAMLAuthnContextParser() {
super(SAMLAssertionQNames.AUTHN_CONTEXT);
}
public static SAMLAuthnContextParser getInstance() {
return INSTANCE;
}
@Override
protected AuthnContextType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new AuthnContextType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, AuthnContextType target, SAMLAssertionQNames element, StartElement elementDetail) throws ParsingException {
String text;
AuthnContextType.AuthnContextTypeSequence authnContextSequence;
switch (element) {
case AUTHN_CONTEXT_DECL:
Element dom = StaxParserUtil.getDOMElement(xmlEventReader);
AuthnContextDeclType authnContextDecl = new AuthnContextDeclType(dom);
authnContextSequence = target.getSequence() != null ? target.getSequence() : target.new AuthnContextTypeSequence();
authnContextSequence.setAuthnContextDecl(authnContextDecl);
target.setSequence(authnContextSequence);
break;
case AUTHN_CONTEXT_DECL_REF:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
AuthnContextDeclRefType authnContextDeclRef = new AuthnContextDeclRefType(URI.create(text));
target.addURIType(authnContextDeclRef);
break;
case AUTHN_CONTEXT_CLASS_REF:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
AuthnContextClassRefType authnContextClassRef = new AuthnContextClassRefType(URI.create(text));
authnContextSequence = target.getSequence() != null ? target.getSequence() : target.new AuthnContextTypeSequence();
authnContextSequence.setClassRef(authnContextClassRef);
target.setSequence(authnContextSequence);
break;
case AUTHENTICATING_AUTHORITY:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
target.addAuthenticatingAuthority(URI.create(text));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,76 @@
/*
* 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.assertion;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
import org.keycloak.dom.saml.v2.assertion.SubjectLocalityType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
/**
* Parse the <conditions> in the saml assertion
*
* @since Oct 14, 2010
*/
public class SAMLAuthnStatementParser extends AbstractStaxSamlAssertionParser<AuthnStatementType> {
private static final SAMLAuthnStatementParser INSTANCE = new SAMLAuthnStatementParser();
private SAMLAuthnStatementParser() {
super(SAMLAssertionQNames.AUTHN_STATEMENT);
}
public static SAMLAuthnStatementParser getInstance() {
return INSTANCE;
}
@Override
protected AuthnStatementType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
XMLGregorianCalendar authnInstant = XMLTimeUtil.parse(StaxParserUtil.getRequiredAttributeValue(element, SAMLAssertionQNames.ATTR_AUTHN_INSTANT));
AuthnStatementType res = new AuthnStatementType(authnInstant);
res.setSessionIndex(StaxParserUtil.getAttributeValue(element, SAMLAssertionQNames.ATTR_SESSION_INDEX));
res.setSessionNotOnOrAfter(StaxParserUtil.getXmlTimeAttributeValue(element, SAMLAssertionQNames.ATTR_NOT_ON_OR_AFTER));
return res;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, AuthnStatementType target, SAMLAssertionQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case SUBJECT_LOCALITY:
StaxParserUtil.advance(xmlEventReader);
SubjectLocalityType subjectLocalityType = new SubjectLocalityType();
subjectLocalityType.setAddress(StaxParserUtil.getAttributeValue(elementDetail, SAMLAssertionQNames.ATTR_ADDRESS));
subjectLocalityType.setDNSName(StaxParserUtil.getAttributeValue(elementDetail, SAMLAssertionQNames.ATTR_DNS_NAME));
target.setSubjectLocality(subjectLocalityType);
break;
case AUTHN_CONTEXT:
target.setAuthnContext(SAMLAuthnContextParser.getInstance().parse(xmlEventReader));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -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.assertion;
import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType;
import org.keycloak.dom.saml.v2.assertion.ConditionsType;
import org.keycloak.dom.saml.v2.assertion.OneTimeUseType;
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;
/**
* Parse the <conditions> in the saml assertion
*
* @since Oct 14, 2010
*/
public class SAMLConditionsParser extends AbstractStaxSamlAssertionParser<ConditionsType> {
private static final SAMLConditionsParser INSTANCE = new SAMLConditionsParser();
private SAMLConditionsParser() {
super(SAMLAssertionQNames.CONDITIONS);
}
public static SAMLConditionsParser getInstance() {
return INSTANCE;
}
@Override
protected ConditionsType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
final ConditionsType conditions = new ConditionsType();
conditions.setNotBefore(StaxParserUtil.getXmlTimeAttributeValue(element, SAMLAssertionQNames.ATTR_NOT_BEFORE));
conditions.setNotOnOrAfter(StaxParserUtil.getXmlTimeAttributeValue(element, SAMLAssertionQNames.ATTR_NOT_ON_OR_AFTER));
return conditions;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, ConditionsType target, SAMLAssertionQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case AUDIENCE_RESTRICTION:
AudienceRestrictionType audienceRestriction = SAMLAudienceRestrictionParser.getInstance().parse(xmlEventReader);
target.addCondition(audienceRestriction);
break;
case ONE_TIME_USE:
OneTimeUseType oneTimeUseCondition = new OneTimeUseType();
target.addCondition(oneTimeUseCondition);
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -14,28 +14,26 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.keycloak.saml.processing.core.parsers.saml.assertion;
package org.keycloak.saml.processing.core.parsers.saml.metadata; import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.AbstractParser; import org.keycloak.saml.common.parsers.StaxParser;
import org.keycloak.saml.common.util.StaxParserUtil;
import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
/** public class SAMLEncryptedAssertionParser implements StaxParser {
* <p>Abstract entity descriptor parser, which provides common parser functionality</p>
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public abstract class AbstractDescriptorParser extends AbstractParser {
protected XMLEventReader filterWhiteSpaceCharacters(XMLEventReader xmlEventReader) throws ParsingException { private static final SAMLEncryptedAssertionParser INSTANCE = new SAMLEncryptedAssertionParser();
try {
return filterWhitespaces(xmlEventReader); public static SAMLEncryptedAssertionParser getInstance() {
} catch (XMLStreamException e) { return INSTANCE;
throw new ParsingException(e);
}
} }
@Override
public EncryptedAssertionType parse(XMLEventReader xmlEventReader) throws ParsingException {
EncryptedAssertionType res = new EncryptedAssertionType();
res.setEncryptedElement(StaxParserUtil.getDOMElement(xmlEventReader));
return res;
}
} }

View file

@ -0,0 +1,68 @@
/*
* 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.assertion;
import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationDataType;
import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType;
import org.keycloak.saml.common.constants.WSTrustConstants;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.saml.xmldsig.KeyInfoParser;
import java.util.Objects;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
public class SAMLSubjectConfirmationDataParser extends AbstractStaxSamlAssertionParser<SubjectConfirmationDataType> {
public static final SAMLSubjectConfirmationDataParser INSTANCE = new SAMLSubjectConfirmationDataParser();
public SAMLSubjectConfirmationDataParser() {
super(SAMLAssertionQNames.SUBJECT_CONFIRMATION_DATA);
}
@Override
protected SubjectConfirmationDataType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
final SubjectConfirmationDataType subjectConfirmationData = new SubjectConfirmationDataType();
subjectConfirmationData.setInResponseTo(StaxParserUtil.getAttributeValue(element, SAMLAssertionQNames.ATTR_IN_RESPONSE_TO));
subjectConfirmationData.setNotBefore(StaxParserUtil.getXmlTimeAttributeValue(element, SAMLAssertionQNames.ATTR_NOT_BEFORE));
subjectConfirmationData.setNotOnOrAfter(StaxParserUtil.getXmlTimeAttributeValue(element, SAMLAssertionQNames.ATTR_NOT_ON_OR_AFTER));
subjectConfirmationData.setRecipient(StaxParserUtil.getAttributeValue(element, SAMLAssertionQNames.ATTR_RECIPIENT));
subjectConfirmationData.setAddress(StaxParserUtil.getAttributeValue(element, SAMLAssertionQNames.ATTR_ADDRESS));
return subjectConfirmationData;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, SubjectConfirmationDataType target, SAMLAssertionQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case KEY_INFO:
KeyInfoType keyInfo = KeyInfoParser.getInstance().parse(xmlEventReader);
target.setAnyType(keyInfo);
break;
default:
String tag = StaxParserUtil.getElementName(elementDetail);
if (Objects.equals(tag, WSTrustConstants.XMLEnc.ENCRYPTED_KEY)) {
target.setAnyType(StaxParserUtil.getDOMElement(xmlEventReader));
} else {
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}
}

View file

@ -0,0 +1,71 @@
/*
* 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.assertion;
import org.keycloak.dom.saml.v2.assertion.EncryptedElementType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationDataType;
import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationType;
import org.keycloak.saml.common.ErrorCodes;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.StaxParser;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import org.w3c.dom.Element;
public class SAMLSubjectConfirmationParser extends AbstractStaxSamlAssertionParser<SubjectConfirmationType> implements StaxParser {
public static final SAMLSubjectConfirmationParser INSTANCE = new SAMLSubjectConfirmationParser();
public SAMLSubjectConfirmationParser() {
super(SAMLAssertionQNames.SUBJECT_CONFIRMATION);
}
@Override
protected SubjectConfirmationType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
final SubjectConfirmationType res = new SubjectConfirmationType();
res.setMethod(StaxParserUtil.getAttributeValue(element, SAMLAssertionQNames.ATTR_METHOD));
return res;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, SubjectConfirmationType target, SAMLAssertionQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case NAMEID:
NameIDType nameID = SAMLParserUtil.parseNameIDType(xmlEventReader);
target.setNameID(nameID);
break;
case ENCRYPTED_ID:
Element domElement = StaxParserUtil.getDOMElement(xmlEventReader);
target.setEncryptedID(new EncryptedElementType(domElement));
break;
case SUBJECT_CONFIRMATION_DATA:
SubjectConfirmationDataType subjectConfirmationData = SAMLSubjectConfirmationDataParser.INSTANCE.parse(xmlEventReader);
target.setSubjectConfirmationData(subjectConfirmationData);
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,79 @@
/*
* 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.assertion;
import org.keycloak.dom.saml.v2.assertion.EncryptedElementType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.saml.common.ErrorCodes;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.StaxParser;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import org.w3c.dom.Element;
/**
* Parse the saml subject
*
* @since Oct 12, 2010
*/
public class SAMLSubjectParser extends AbstractStaxSamlAssertionParser<SubjectType> implements StaxParser {
private static final SAMLSubjectParser INSTANCE = new SAMLSubjectParser();
private SAMLSubjectParser() {
super(SAMLAssertionQNames.SUBJECT);
}
public static SAMLSubjectParser getInstance() {
return INSTANCE;
}
@Override
protected SubjectType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new SubjectType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, SubjectType target, SAMLAssertionQNames element, StartElement elementDetail) throws ParsingException {
SubjectType.STSubType subType;
switch (element) {
case NAMEID:
NameIDType nameID = SAMLParserUtil.parseNameIDType(xmlEventReader);
subType = new SubjectType.STSubType();
subType.addBaseID(nameID);
target.setSubType(subType);
break;
case ENCRYPTED_ID:
Element domElement = StaxParserUtil.getDOMElement(xmlEventReader);
subType = new SubjectType.STSubType();
subType.setEncryptedID(new EncryptedElementType(domElement));
target.setSubType(subType);
break;
case SUBJECT_CONFIRMATION:
target.addConfirmation(SAMLSubjectConfirmationParser.INSTANCE.parse(xmlEventReader));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,50 @@
/*
* 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;
}
}

View file

@ -23,7 +23,7 @@ import org.keycloak.saml.common.PicketLinkLoggerFactory;
import org.keycloak.saml.common.constants.JBossSAMLConstants; import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.ParserNamespaceSupport; import org.keycloak.saml.common.parsers.AbstractParser;
import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@ -34,6 +34,7 @@ import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement; import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement; import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent; import javax.xml.stream.events.XMLEvent;
import org.keycloak.saml.common.parsers.StaxParser;
/** /**
* Parse the SAML Entities Descriptor * Parse the SAML Entities Descriptor
@ -41,16 +42,14 @@ import javax.xml.stream.events.XMLEvent;
* @author Anil.Saldhana@redhat.com * @author Anil.Saldhana@redhat.com
* @since Jan 31, 2011 * @since Jan 31, 2011
*/ */
public class SAMLEntitiesDescriptorParser extends AbstractDescriptorParser implements ParserNamespaceSupport { public class SAMLEntitiesDescriptorParser extends AbstractParser {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
private final String EDT = JBossSAMLConstants.ENTITIES_DESCRIPTOR.get(); private static final String EDT = JBossSAMLConstants.ENTITIES_DESCRIPTOR.get();
public Object parse(XMLEventReader xmlEventReader) throws ParsingException { public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
xmlEventReader = filterWhiteSpaceCharacters(xmlEventReader);
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader); StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, EDT); StaxParserUtil.validate(startElement, EDT);
@ -93,7 +92,7 @@ public class SAMLEntitiesDescriptorParser extends AbstractDescriptorParser imple
if (JBossSAMLConstants.ENTITY_DESCRIPTOR.get().equals(localPart)) { if (JBossSAMLConstants.ENTITY_DESCRIPTOR.get().equals(localPart)) {
SAMLEntityDescriptorParser entityParser = new SAMLEntityDescriptorParser(); SAMLEntityDescriptorParser entityParser = new SAMLEntityDescriptorParser();
entitiesDescriptorType.addEntityDescriptor(entityParser.parse(xmlEventReader)); entitiesDescriptorType.addEntityDescriptor(entityParser.parse(xmlEventReader));
} else if (JBossSAMLConstants.EXTENSIONS.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.EXTENSIONS__METADATA.get().equalsIgnoreCase(localPart)) {
entitiesDescriptorType.setExtensions(parseExtensions(xmlEventReader)); entitiesDescriptorType.setExtensions(parseExtensions(xmlEventReader));
} else if (JBossSAMLConstants.ENTITIES_DESCRIPTOR.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.ENTITIES_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
SAMLEntitiesDescriptorParser parser = new SAMLEntitiesDescriptorParser(); SAMLEntitiesDescriptorParser parser = new SAMLEntitiesDescriptorParser();
@ -106,12 +105,6 @@ public class SAMLEntitiesDescriptorParser extends AbstractDescriptorParser imple
return entitiesDescriptorType; return entitiesDescriptorType;
} }
public boolean supports(QName qname) {
String nsURI = qname.getNamespaceURI();
String localPart = qname.getLocalPart();
return nsURI.equals(JBossSAMLURIConstants.ASSERTION_NSURI.get()) && localPart.equals(EDT);
}
private ExtensionsType parseExtensions(XMLEventReader xmlEventReader) throws ParsingException { private ExtensionsType parseExtensions(XMLEventReader xmlEventReader) throws ParsingException {
ExtensionsType extensions = new ExtensionsType(); ExtensionsType extensions = new ExtensionsType();

View file

@ -31,7 +31,6 @@ import org.keycloak.dom.saml.v2.metadata.KeyTypes;
import org.keycloak.dom.saml.v2.metadata.LocalizedNameType; import org.keycloak.dom.saml.v2.metadata.LocalizedNameType;
import org.keycloak.dom.saml.v2.metadata.LocalizedURIType; import org.keycloak.dom.saml.v2.metadata.LocalizedURIType;
import org.keycloak.dom.saml.v2.metadata.OrganizationType; import org.keycloak.dom.saml.v2.metadata.OrganizationType;
import org.keycloak.dom.saml.v2.metadata.RequestedAttributeType;
import org.keycloak.dom.saml.v2.metadata.RoleDescriptorType; import org.keycloak.dom.saml.v2.metadata.RoleDescriptorType;
import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType; import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
import org.keycloak.dom.xmlsec.w3.xmlenc.EncryptionMethodType; import org.keycloak.dom.xmlsec.w3.xmlenc.EncryptionMethodType;
@ -41,9 +40,10 @@ import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLConstants; import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.ParserNamespaceSupport; import org.keycloak.saml.common.parsers.AbstractParser;
import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil; 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.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@ -56,7 +56,10 @@ import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent; import javax.xml.stream.events.XMLEvent;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.StringTokenizer;
import org.keycloak.saml.common.parsers.StaxParser;
/** /**
* Parse the SAML Metadata element "EntityDescriptor" * Parse the SAML Metadata element "EntityDescriptor"
@ -64,16 +67,14 @@ import java.util.List;
* @author Anil.Saldhana@redhat.com * @author Anil.Saldhana@redhat.com
* @since Dec 14, 2010 * @since Dec 14, 2010
*/ */
public class SAMLEntityDescriptorParser extends AbstractDescriptorParser implements ParserNamespaceSupport { public class SAMLEntityDescriptorParser extends AbstractParser {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
private final String EDT = JBossSAMLConstants.ENTITY_DESCRIPTOR.get(); private static final String EDT = JBossSAMLConstants.ENTITY_DESCRIPTOR.get();
public Object parse(XMLEventReader xmlEventReader) throws ParsingException { public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
xmlEventReader = filterWhiteSpaceCharacters(xmlEventReader);
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader); StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, EDT); StaxParserUtil.validate(startElement, EDT);
@ -142,8 +143,8 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
entityDescriptorType.addContactPerson(parseContactPerson(xmlEventReader)); entityDescriptorType.addContactPerson(parseContactPerson(xmlEventReader));
} else if (JBossSAMLConstants.ADDITIONAL_METADATA_LOCATION.get().equals(localPart)) { } else if (JBossSAMLConstants.ADDITIONAL_METADATA_LOCATION.get().equals(localPart)) {
throw logger.unsupportedType("AdditionalMetadataLocation"); throw logger.unsupportedType("AdditionalMetadataLocation");
} else if (JBossSAMLConstants.EXTENSIONS.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
entityDescriptorType.setExtensions(parseExtensions(xmlEventReader)); entityDescriptorType.setExtensions(SAMLExtensionsParser.getInstance().parse(xmlEventReader));
} else if (JBossSAMLConstants.ROLE_DESCRIPTOR.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.ROLE_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
RoleDescriptorType roleDescriptor = parseRoleDescriptor(xmlEventReader); RoleDescriptorType roleDescriptor = parseRoleDescriptor(xmlEventReader);
@ -157,19 +158,12 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
return entityDescriptorType; return entityDescriptorType;
} }
public boolean supports(QName qname) {
String nsURI = qname.getNamespaceURI();
String localPart = qname.getLocalPart();
return nsURI.equals(JBossSAMLURIConstants.ASSERTION_NSURI.get())
&& localPart.equals(JBossSAMLConstants.ENTITY_DESCRIPTOR.get());
}
private SPSSODescriptorType parseSPSSODescriptor(XMLEventReader xmlEventReader) throws ParsingException { private SPSSODescriptorType parseSPSSODescriptor(XMLEventReader xmlEventReader) throws ParsingException {
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader); StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.SP_SSO_DESCRIPTOR.get()); StaxParserUtil.validate(startElement, JBossSAMLConstants.SP_SSO_DESCRIPTOR.get());
List<String> protocolEnum = SAMLParserUtil.parseProtocolEnumeration(startElement); List<String> protocolEnum = parseProtocolEnumeration(startElement);
SPSSODescriptorType spSSODescriptor = new SPSSODescriptorType(protocolEnum); SPSSODescriptorType spSSODescriptor = new SPSSODescriptorType(protocolEnum);
Attribute wantAssertionsSigned = startElement.getAttributeByName(new QName(JBossSAMLConstants.WANT_ASSERTIONS_SIGNED Attribute wantAssertionsSigned = startElement.getAttributeByName(new QName(JBossSAMLConstants.WANT_ASSERTIONS_SIGNED
@ -224,7 +218,7 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
spSSODescriptor.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader)); spSSODescriptor.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader));
} else if (JBossSAMLConstants.KEY_DESCRIPTOR.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.KEY_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
spSSODescriptor.addKeyDescriptor(parseKeyDescriptor(xmlEventReader)); spSSODescriptor.addKeyDescriptor(parseKeyDescriptor(xmlEventReader));
} else if (JBossSAMLConstants.EXTENSIONS.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
spSSODescriptor.setExtensions(parseExtensions(xmlEventReader)); spSSODescriptor.setExtensions(parseExtensions(xmlEventReader));
} else } else
throw logger.parserUnknownTag(localPart, startElement.getLocation()); throw logger.parserUnknownTag(localPart, startElement.getLocation());
@ -236,7 +230,7 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader); StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.IDP_SSO_DESCRIPTOR.get()); StaxParserUtil.validate(startElement, JBossSAMLConstants.IDP_SSO_DESCRIPTOR.get());
List<String> protocolEnum = SAMLParserUtil.parseProtocolEnumeration(startElement); List<String> protocolEnum = parseProtocolEnumeration(startElement);
IDPSSODescriptorType idpSSODescriptor = new IDPSSODescriptorType(protocolEnum); IDPSSODescriptorType idpSSODescriptor = new IDPSSODescriptorType(protocolEnum);
Attribute wantAuthnSigned = startElement.getAttributeByName(new QName(JBossSAMLConstants.WANT_AUTHN_REQUESTS_SIGNED Attribute wantAuthnSigned = startElement.getAttributeByName(new QName(JBossSAMLConstants.WANT_AUTHN_REQUESTS_SIGNED
@ -304,11 +298,11 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
startElement = StaxParserUtil.getNextStartElement(xmlEventReader); startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
idpSSODescriptor.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader)); idpSSODescriptor.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader));
} else if (JBossSAMLConstants.ATTRIBUTE.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.ATTRIBUTE.get().equalsIgnoreCase(localPart)) {
AttributeType attribute = SAMLParserUtil.parseAttribute(xmlEventReader); AttributeType attribute = SAMLAttributeParser.getInstance().parse(xmlEventReader);
idpSSODescriptor.addAttribute(attribute); idpSSODescriptor.addAttribute(attribute);
} else if (JBossSAMLConstants.KEY_DESCRIPTOR.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.KEY_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
idpSSODescriptor.addKeyDescriptor(parseKeyDescriptor(xmlEventReader)); idpSSODescriptor.addKeyDescriptor(parseKeyDescriptor(xmlEventReader));
} else if (JBossSAMLConstants.EXTENSIONS.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
idpSSODescriptor.setExtensions(parseExtensions(xmlEventReader)); idpSSODescriptor.setExtensions(parseExtensions(xmlEventReader));
} else } else
throw logger.parserUnknownTag(localPart, startElement.getLocation()); throw logger.parserUnknownTag(localPart, startElement.getLocation());
@ -335,7 +329,7 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
throws ParsingException { throws ParsingException {
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader); StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.ATTRIBUTE_AUTHORITY_DESCRIPTOR.get()); StaxParserUtil.validate(startElement, JBossSAMLConstants.ATTRIBUTE_AUTHORITY_DESCRIPTOR.get());
List<String> protocolEnum = SAMLParserUtil.parseProtocolEnumeration(startElement); List<String> protocolEnum = parseProtocolEnumeration(startElement);
AttributeAuthorityDescriptorType attributeAuthority = new AttributeAuthorityDescriptorType(protocolEnum); AttributeAuthorityDescriptorType attributeAuthority = new AttributeAuthorityDescriptorType(protocolEnum);
while (xmlEventReader.hasNext()) { while (xmlEventReader.hasNext()) {
@ -363,17 +357,25 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
StaxParserUtil.validate(endElement, JBossSAMLConstants.ATTRIBUTE_SERVICE.get()); StaxParserUtil.validate(endElement, JBossSAMLConstants.ATTRIBUTE_SERVICE.get());
attributeAuthority.addAttributeService(endpoint); 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)) { } else if (JBossSAMLConstants.ATTRIBUTE_PROFILE.get().equalsIgnoreCase(localPart)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader); startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
attributeAuthority.addAttributeProfile(StaxParserUtil.getElementText(xmlEventReader)); attributeAuthority.addAttributeProfile(StaxParserUtil.getElementText(xmlEventReader));
} else if (JBossSAMLConstants.ATTRIBUTE.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.ATTRIBUTE.get().equalsIgnoreCase(localPart)) {
attributeAuthority.addAttribute(SAMLParserUtil.parseAttribute(xmlEventReader)); attributeAuthority.addAttribute(SAMLAttributeParser.getInstance().parse(xmlEventReader));
} else if (JBossSAMLConstants.KEY_DESCRIPTOR.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.KEY_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
attributeAuthority.addKeyDescriptor(parseKeyDescriptor(xmlEventReader)); attributeAuthority.addKeyDescriptor(parseKeyDescriptor(xmlEventReader));
} else if (JBossSAMLConstants.NAMEID_FORMAT.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.NAMEID_FORMAT.get().equalsIgnoreCase(localPart)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader); startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
attributeAuthority.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader)); attributeAuthority.addNameIDFormat(StaxParserUtil.getElementText(xmlEventReader));
} else if (JBossSAMLConstants.EXTENSIONS.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
attributeAuthority.setExtensions(parseExtensions(xmlEventReader)); attributeAuthority.setExtensions(parseExtensions(xmlEventReader));
} else } else
throw logger.parserUnknownTag(localPart, startElement.getLocation()); throw logger.parserUnknownTag(localPart, startElement.getLocation());
@ -415,7 +417,7 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
LocalizedURIType localName = new LocalizedURIType(langVal); LocalizedURIType localName = new LocalizedURIType(langVal);
localName.setValue(URI.create(StaxParserUtil.getElementText(xmlEventReader))); localName.setValue(URI.create(StaxParserUtil.getElementText(xmlEventReader)));
org.addOrganizationURL(localName); org.addOrganizationURL(localName);
} else if (JBossSAMLConstants.EXTENSIONS.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
org.setExtensions(parseExtensions(xmlEventReader)); org.setExtensions(parseExtensions(xmlEventReader));
} else } else
throw logger.parserUnknownTag(localPart, startElement.getLocation()); throw logger.parserUnknownTag(localPart, startElement.getLocation());
@ -531,7 +533,7 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
} else if (JBossSAMLConstants.TELEPHONE_NUMBER.get().equals(localPart)) { } else if (JBossSAMLConstants.TELEPHONE_NUMBER.get().equals(localPart)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader); startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
contactType.addTelephone(StaxParserUtil.getElementText(xmlEventReader)); contactType.addTelephone(StaxParserUtil.getElementText(xmlEventReader));
} else if (JBossSAMLConstants.EXTENSIONS.get().equalsIgnoreCase(localPart)) { } else if (JBossSAMLConstants.EXTENSIONS__PROTOCOL.get().equalsIgnoreCase(localPart)) {
contactType.setExtensions(parseExtensions(xmlEventReader)); contactType.setExtensions(parseExtensions(xmlEventReader));
} else } else
throw logger.parserUnknownTag(localPart, startElement.getLocation()); throw logger.parserUnknownTag(localPart, startElement.getLocation());
@ -619,8 +621,7 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
LocalizedNameType localName = getLocalizedName(xmlEventReader, startElement); LocalizedNameType localName = getLocalizedName(xmlEventReader, startElement);
attributeConsumer.addServiceDescription(localName); attributeConsumer.addServiceDescription(localName);
} else if (JBossSAMLConstants.REQUESTED_ATTRIBUTE.get().equals(localPart)) { } else if (JBossSAMLConstants.REQUESTED_ATTRIBUTE.get().equals(localPart)) {
RequestedAttributeType attType = parseRequestedAttributeType(xmlEventReader, startElement); attributeConsumer.addRequestedAttribute(SAMLRequestedAttributeParser.getInstance().parse(xmlEventReader));
attributeConsumer.addRequestedAttribute(attType);
} else } else
throw logger.parserUnknownTag(localPart, startElement.getLocation()); throw logger.parserUnknownTag(localPart, startElement.getLocation());
} }
@ -628,27 +629,6 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
return attributeConsumer; return attributeConsumer;
} }
private RequestedAttributeType parseRequestedAttributeType(XMLEventReader xmlEventReader, StartElement startElement)
throws ParsingException {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.REQUESTED_ATTRIBUTE.get());
RequestedAttributeType attributeType = null;
Attribute name = startElement.getAttributeByName(new QName(JBossSAMLConstants.NAME.get()));
if (name == null)
throw logger.parserRequiredAttribute("Name");
attributeType = new RequestedAttributeType(StaxParserUtil.getAttributeValue(name));
Attribute isRequired = startElement.getAttributeByName(new QName(JBossSAMLConstants.IS_REQUIRED.get()));
if (isRequired != null) {
attributeType.setIsRequired(Boolean.parseBoolean(StaxParserUtil.getAttributeValue(isRequired)));
}
SAMLParserUtil.parseAttributeType(xmlEventReader, startElement, JBossSAMLConstants.REQUESTED_ATTRIBUTE.get(),
attributeType);
return attributeType;
}
private ExtensionsType parseExtensions(XMLEventReader xmlEventReader) throws ParsingException { private ExtensionsType parseExtensions(XMLEventReader xmlEventReader) throws ParsingException {
ExtensionsType extensions = new ExtensionsType(); ExtensionsType extensions = new ExtensionsType();
Element extElement = StaxParserUtil.getDOMElement(xmlEventReader); Element extElement = StaxParserUtil.getDOMElement(xmlEventReader);
@ -659,7 +639,7 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
private RoleDescriptorType parseRoleDescriptor(XMLEventReader xmlEventReader) throws ParsingException { private RoleDescriptorType parseRoleDescriptor(XMLEventReader xmlEventReader) throws ParsingException {
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader); StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.ROLE_DESCRIPTOR.get()); StaxParserUtil.validate(startElement, JBossSAMLConstants.ROLE_DESCRIPTOR.get());
List<String> protocolEnum = SAMLParserUtil.parseProtocolEnumeration(startElement); List<String> protocolEnum = parseProtocolEnumeration(startElement);
RoleDescriptorType roleDescriptorType = new RoleDescriptorType(protocolEnum) {}; RoleDescriptorType roleDescriptorType = new RoleDescriptorType(protocolEnum) {};
while (xmlEventReader.hasNext()) { while (xmlEventReader.hasNext()) {
@ -683,4 +663,25 @@ public class SAMLEntityDescriptorParser extends AbstractDescriptorParser impleme
return roleDescriptorType; 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());
}
}
return protocolEnum;
}
} }

View file

@ -0,0 +1,52 @@
/*
* 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 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;
/**
* Parses &lt;samlp:Extensions&gt; SAML2 element into series of DOM nodes.
*
* @author hmlnarik
*/
public class SAMLExtensionsParser extends AbstractStaxSamlParser<ExtensionsType> {
private static final SAMLExtensionsParser INSTANCE = new SAMLExtensionsParser();
private SAMLExtensionsParser() {
super(JBossSAMLConstants.EXTENSIONS__METADATA);
}
public static SAMLExtensionsParser getInstance() {
return INSTANCE;
}
@Override
protected ExtensionsType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new ExtensionsType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, ExtensionsType target, JBossSAMLConstants element, StartElement elementDetail) throws ParsingException {
target.setElement(StaxParserUtil.getDOMElement(xmlEventReader));
}
}

View file

@ -0,0 +1,80 @@
/*
* 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.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;
/**
* Parse the <conditions> in the saml assertion
*
* @since Oct 14, 2010
*/
public class SAMLRequestedAttributeParser extends AbstractStaxSamlParser<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);
}
public static SAMLRequestedAttributeParser getInstance() {
return INSTANCE;
}
@Override
protected RequestedAttributeType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
RequestedAttributeType attributeType;
// 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()));
Attribute x500EncodingAttr = element.getAttributeByName(X500_ENCODING);
if (x500EncodingAttr != null) {
attributeType.getOtherAttributes().put(x500EncodingAttr.getName(), StaxParserUtil.getAttributeValue(x500EncodingAttr));
}
return attributeType;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, RequestedAttributeType target, JBossSAMLConstants 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());
}
}
}

View file

@ -0,0 +1,40 @@
/*
* 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.protocol;
import org.keycloak.saml.common.parsers.AbstractStaxParser;
import org.keycloak.saml.processing.core.parsers.util.QNameEnumLookup;
import javax.xml.namespace.QName;
/**
*
* @author hmlnarik
*/
public abstract class AbstractStaxSamlProtocolParser<T> extends AbstractStaxParser<T, SAMLProtocolQNames> {
protected static final QNameEnumLookup<SAMLProtocolQNames> LOOKUP = new QNameEnumLookup(SAMLProtocolQNames.values());
public AbstractStaxSamlProtocolParser(SAMLProtocolQNames expectedStartElement) {
super(expectedStartElement.getQName(), SAMLProtocolQNames.UNKNOWN_ELEMENT);
}
@Override
protected SAMLProtocolQNames getElementFromName(QName name) {
return LOOKUP.from(name);
}
}

View file

@ -0,0 +1,87 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.ArtifactResolveType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import static org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLRequestAbstractParser.VERSION_2_0;
/**
* Parse the {@link ArtifactResolveType}
*
* @since Jul 1, 2011
*/
public class SAMLArtifactResolveParser extends SAMLRequestAbstractParser<ArtifactResolveType> {
private static final SAMLArtifactResolveParser INSTANCE = new SAMLArtifactResolveParser();
private SAMLArtifactResolveParser() {
super(SAMLProtocolQNames.ARTIFACT_RESOLVE);
}
public static SAMLArtifactResolveParser getInstance() {
return INSTANCE;
}
/**
* Parse the attributes at the authnrequesttype element
*
* @param startElement
*
* @return
*
* @throws ParsingException
*/
@Override
protected ArtifactResolveType instantiateElement(XMLEventReader xmlEventReader, StartElement startElement) throws ParsingException {
SAMLParserUtil.validateAttributeValue(startElement, SAMLProtocolQNames.ATTR_VERSION, VERSION_2_0);
String id = StaxParserUtil.getRequiredAttributeValue(startElement, SAMLProtocolQNames.ATTR_ID);
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getRequiredAttributeValue(startElement, SAMLProtocolQNames.ATTR_ISSUE_INSTANT));
ArtifactResolveType authnRequest = new ArtifactResolveType(id, issueInstant);
super.parseBaseAttributes(startElement, authnRequest);
return authnRequest;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, ArtifactResolveType target,
SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case ISSUER:
case SIGNATURE:
case EXTENSIONS:
parseCommonElements(element, elementDetail, xmlEventReader, target);
break;
case ARTIFACT:
StaxParserUtil.advance(xmlEventReader);
target.setArtifact(StaxParserUtil.getElementText(xmlEventReader));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,97 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.ArtifactResponseType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.datatype.XMLGregorianCalendar;
import org.w3c.dom.Element;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import static org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLStatusResponseTypeParser.VERSION_2_0;
/**
* Parse the SAML Response
*
* @since July 1, 2011
*/
public class SAMLArtifactResponseParser extends SAMLStatusResponseTypeParser<ArtifactResponseType> {
private static final SAMLArtifactResponseParser INSTANCE = new SAMLArtifactResponseParser();
private SAMLArtifactResponseParser() {
super(SAMLProtocolQNames.ARTIFACT_RESPONSE);
}
public static SAMLArtifactResponseParser getInstance() {
return INSTANCE;
}
@Override
protected ArtifactResponseType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
SAMLParserUtil.validateAttributeValue(element, SAMLProtocolQNames.ATTR_VERSION, VERSION_2_0);
String id = StaxParserUtil.getRequiredAttributeValue(element, SAMLProtocolQNames.ATTR_ID);
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getRequiredAttributeValue(element, SAMLProtocolQNames.ATTR_ISSUE_INSTANT));
ArtifactResponseType res = new ArtifactResponseType(id, issueInstant);
// Let us set the attributes
super.parseBaseAttributes(element, res);
return res;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, ArtifactResponseType target, SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case ISSUER:
target.setIssuer(SAMLParserUtil.parseNameIDType(xmlEventReader));
break;
case SIGNATURE:
Element sig = StaxParserUtil.getDOMElement(xmlEventReader);
target.setSignature(sig);
break;
case EXTENSIONS:
SAMLExtensionsParser extensionsParser = SAMLExtensionsParser.getInstance();
target.setExtensions(extensionsParser.parse(xmlEventReader));
break;
case AUTHN_REQUEST:
SAMLAuthNRequestParser authnParser = SAMLAuthNRequestParser.getInstance();
target.setAny(authnParser.parse(xmlEventReader));
break;
case RESPONSE:
SAMLResponseParser responseParser = SAMLResponseParser.getInstance();
target.setAny(responseParser.parse(xmlEventReader));
break;
case STATUS:
target.setStatus(SAMLStatusParser.getInstance().parse(xmlEventReader));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,83 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.AttributeQueryType;
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 org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAttributeParser;
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLSubjectParser;
import org.keycloak.saml.common.parsers.StaxParser;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.datatype.XMLGregorianCalendar;
import static org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLRequestAbstractParser.VERSION_2_0;
/**
* Parse the {@link org.keycloak.dom.saml.v2.protocol.ArtifactResolveType}
*
* @since Jul 1, 2011
*/
public class SAMLAttributeQueryParser extends SAMLRequestAbstractParser<AttributeQueryType> implements StaxParser {
private static final SAMLAttributeQueryParser INSTANCE = new SAMLAttributeQueryParser();
private SAMLAttributeQueryParser() {
super(SAMLProtocolQNames.ATTRIBUTE_QUERY);
}
public static SAMLAttributeQueryParser getInstance() {
return INSTANCE;
}
@Override
protected AttributeQueryType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
SAMLParserUtil.validateAttributeValue(element, SAMLProtocolQNames.ATTR_VERSION, VERSION_2_0);
String id = StaxParserUtil.getRequiredAttributeValue(element, SAMLProtocolQNames.ATTR_ID);
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getRequiredAttributeValue(element, SAMLProtocolQNames.ATTR_ISSUE_INSTANT));
AttributeQueryType authnRequest = new AttributeQueryType(id, issueInstant);
super.parseBaseAttributes(element, authnRequest);
return authnRequest;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, AttributeQueryType target, SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case ISSUER:
case SIGNATURE:
case EXTENSIONS:
parseCommonElements(element, elementDetail, xmlEventReader, target);
break;
case SUBJECT:
target.setSubject(SAMLSubjectParser.getInstance().parse(xmlEventReader));
break;
case ATTRIBUTE:
target.add(SAMLAttributeParser.getInstance().parse(xmlEventReader));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,127 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
import org.keycloak.dom.saml.v2.protocol.NameIDPolicyType;
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 org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLConditionsParser;
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLSubjectParser;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.datatype.XMLGregorianCalendar;
import static org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLRequestAbstractParser.VERSION_2_0;
/**
* Parse the SAML2 AuthnRequest
*
* @since Nov 2, 2010
*/
public class SAMLAuthNRequestParser extends SAMLRequestAbstractParser<AuthnRequestType> {
private static final SAMLAuthNRequestParser INSTANCE = new SAMLAuthNRequestParser();
private SAMLAuthNRequestParser() {
super(SAMLProtocolQNames.AUTHN_REQUEST);
}
public static SAMLAuthNRequestParser getInstance() {
return INSTANCE;
}
/**
* Parse the attributes at the authnrequesttype element
*
* @param startElement
*
* @return
*
* @throws ParsingException
*/
@Override
protected AuthnRequestType instantiateElement(XMLEventReader xmlEventReader, StartElement startElement) throws ParsingException {
SAMLParserUtil.validateAttributeValue(startElement, SAMLProtocolQNames.ATTR_VERSION, VERSION_2_0);
String id = StaxParserUtil.getRequiredAttributeValue(startElement, SAMLProtocolQNames.ATTR_ID);
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getRequiredAttributeValue(startElement, SAMLProtocolQNames.ATTR_ISSUE_INSTANT));
AuthnRequestType authnRequest = new AuthnRequestType(id, issueInstant);
super.parseBaseAttributes(startElement, authnRequest);
authnRequest.setAssertionConsumerServiceURL(StaxParserUtil.getUriAttributeValue(startElement, SAMLProtocolQNames.ATTR_ASSERTION_CONSUMER_SERVICE_URL));
authnRequest.setAssertionConsumerServiceIndex(StaxParserUtil.getIntegerAttributeValue(startElement, SAMLProtocolQNames.ATTR_ASSERTION_CONSUMER_SERVICE_INDEX));
authnRequest.setAttributeConsumingServiceIndex(StaxParserUtil.getIntegerAttributeValue(startElement, SAMLProtocolQNames.ATTR_ATTRIBUTE_CONSUMING_SERVICE_INDEX));
authnRequest.setForceAuthn(StaxParserUtil.getBooleanAttributeValue(startElement, SAMLProtocolQNames.ATTR_FORCE_AUTHN));
authnRequest.setIsPassive(StaxParserUtil.getBooleanAttributeValue(startElement, SAMLProtocolQNames.ATTR_IS_PASSIVE));
authnRequest.setProtocolBinding(StaxParserUtil.getUriAttributeValue(startElement, SAMLProtocolQNames.ATTR_PROTOCOL_BINDING));
authnRequest.setProviderName(StaxParserUtil.getAttributeValue(startElement, SAMLProtocolQNames.ATTR_PROVIDER_NAME));
return authnRequest;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, AuthnRequestType target, SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case ISSUER:
case SIGNATURE:
case EXTENSIONS:
parseCommonElements(element, elementDetail, xmlEventReader, target);
break;
case NAMEID_POLICY:
StaxParserUtil.advance(xmlEventReader);
target.setNameIDPolicy(getNameIDPolicy(elementDetail));
break;
case SUBJECT:
target.setSubject(SAMLSubjectParser.getInstance().parse(xmlEventReader));
break;
case CONDITIONS:
target.setConditions(SAMLConditionsParser.getInstance().parse(xmlEventReader));
break;
case REQUESTED_AUTHN_CONTEXT:
target.setRequestedAuthnContext(SAMLRequestedAuthnContextParser.getInstance().parse(xmlEventReader));
break;
case SCOPING:
StaxParserUtil.bypassElementBlock(xmlEventReader, element.getQName());
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
/**
* Get the NameIDPolicy
*
* @param startElement
*
* @return
*/
private NameIDPolicyType getNameIDPolicy(StartElement startElement) {
NameIDPolicyType nameIDPolicy = new NameIDPolicyType();
nameIDPolicy.setFormat(StaxParserUtil.getUriAttributeValue(startElement, SAMLProtocolQNames.ATTR_FORMAT));
nameIDPolicy.setAllowCreate(StaxParserUtil.getBooleanAttributeValue(startElement, SAMLProtocolQNames.ATTR_ALLOW_CREATE));
return nameIDPolicy;
}
}

View file

@ -0,0 +1,51 @@
/*
* 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.protocol;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import org.keycloak.dom.saml.v2.protocol.ExtensionsType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
/**
* Parses &lt;samlp:Extensions&gt; SAML2 element into series of DOM nodes.
*
* @author hmlnarik
*/
public class SAMLExtensionsParser extends AbstractStaxSamlProtocolParser<ExtensionsType> {
private static final SAMLExtensionsParser INSTANCE = new SAMLExtensionsParser();
private SAMLExtensionsParser() {
super(SAMLProtocolQNames.EXTENSIONS);
}
public static SAMLExtensionsParser getInstance() {
return INSTANCE;
}
@Override
protected ExtensionsType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new ExtensionsType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, ExtensionsType target, SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
target.addExtension(StaxParserUtil.getDOMElement(xmlEventReader));
}
}

View file

@ -0,0 +1,125 @@
/*
* 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.protocol;
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 javax.xml.namespace.QName;
import org.keycloak.saml.processing.core.parsers.util.HasQName;
/**
* Elements from saml-schema-protocol-2.0.xsd
* @author hmlnarik
*/
public enum SAMLProtocolQNames implements HasQName {
ARTIFACT("Artifact"),
ARTIFACT_RESOLVE("ArtifactResolve"),
ARTIFACT_RESPONSE("ArtifactResponse"),
ASSERTION_ID_REQUEST("AssertionIDRequest"),
ATTRIBUTE_QUERY("AttributeQuery"),
AUTHN_QUERY("AuthnQuery"),
AUTHN_REQUEST("AuthnRequest"),
AUTHZ_DECISION_QUERY("AuthzDecisionQuery"),
EXTENSIONS("Extensions"),
GET_COMPLETE("GetComplete"),
IDP_ENTRY("IDPEntry"),
IDP_LIST("IDPList"),
LOGOUT_REQUEST("LogoutRequest"),
LOGOUT_RESPONSE("LogoutResponse"),
MANAGE_NAMEID_REQUEST("ManageNameIDRequest"),
MANAGE_NAMEID_RESPONSE("ManageNameIDResponse"),
NAMEID_MAPPING_REQUEST("NameIDMappingRequest"),
NAMEID_MAPPING_RESPONSE("NameIDMappingResponse"),
NAMEID_POLICY("NameIDPolicy"),
NEW_ENCRYPTEDID("NewEncryptedID"),
NEWID("NewID"),
REQUESTED_AUTHN_CONTEXT("RequestedAuthnContext"),
REQUESTERID("RequesterID"),
RESPONSE("Response"),
SCOPING("Scoping"),
SESSION_INDEX("SessionIndex"),
STATUS_CODE("StatusCode"),
STATUS_DETAIL("StatusDetail"),
STATUS_MESSAGE("StatusMessage"),
STATUS("Status"),
SUBJECT_QUERY("SubjectQuery"),
TERMINATE("Terminate"),
// Attribute names
ATTR_ALLOW_CREATE(null, "AllowCreate"),
ATTR_ASSERTION_CONSUMER_SERVICE_URL(null, "AssertionConsumerServiceURL"),
ATTR_ASSERTION_CONSUMER_SERVICE_INDEX(null, "AssertionConsumerServiceIndex"),
ATTR_ATTRIBUTE_CONSUMING_SERVICE_INDEX(null, "AttributeConsumingServiceIndex"),
ATTR_COMPARISON(null, "Comparison"),
ATTR_CONSENT(null, "Consent"),
ATTR_DESTINATION(null, "Destination"),
ATTR_FORCE_AUTHN(null, "ForceAuthn"),
ATTR_FORMAT(null, "Format"),
ATTR_ID(null, "ID"),
ATTR_IN_RESPONSE_TO(null, "InResponseTo"),
ATTR_IS_PASSIVE(null, "IsPassive"),
ATTR_ISSUE_INSTANT(null, "IssueInstant"),
ATTR_NOT_BEFORE(null, "NotBefore"),
ATTR_NOT_ON_OR_AFTER(null, "NotOnOrAfter"),
ATTR_PROTOCOL_BINDING(null, "ProtocolBinding"),
ATTR_PROVIDER_NAME(null, "ProviderName"),
ATTR_REASON(null, "Reason"),
ATTR_VALUE(null, "Value"),
ATTR_VERSION(null, "Version"),
// Elements from other namespaces that can be direct subelements of this namespace's elements
ATTRIBUTE(SAMLAssertionQNames.ATTRIBUTE),
ASSERTION(SAMLAssertionQNames.ASSERTION),
AUTHN_CONTEXT_CLASS_REF(SAMLAssertionQNames.AUTHN_CONTEXT_CLASS_REF),
AUTHN_CONTEXT_DECL_REF(SAMLAssertionQNames.AUTHN_CONTEXT_DECL_REF),
BASEID(SAMLAssertionQNames.BASEID),
CONDITIONS(SAMLAssertionQNames.CONDITIONS),
ENCRYPTED_ASSERTION(SAMLAssertionQNames.ENCRYPTED_ASSERTION),
ISSUER(SAMLAssertionQNames.ISSUER),
NAMEID(SAMLAssertionQNames.NAMEID),
SIGNATURE(XmlDSigQNames.SIGNATURE),
ENCRYPTED_ID(SAMLAssertionQNames.ENCRYPTED_ID),
SUBJECT(SAMLAssertionQNames.SUBJECT),
UNKNOWN_ELEMENT("")
;
private final QName qName;
private SAMLProtocolQNames(String localName) {
this(JBossSAMLURIConstants.PROTOCOL_NSURI, localName);
}
private SAMLProtocolQNames(HasQName source) {
this.qName = source.getQName();
}
private SAMLProtocolQNames(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);
}
}

View file

@ -0,0 +1,75 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
/**
* Base Class for SAML Request Parsing
*
* @since Nov 2, 2010
*/
public abstract class SAMLRequestAbstractParser<T extends RequestAbstractType> extends AbstractStaxSamlProtocolParser<T> {
protected static final String VERSION_2_0 = "2.0";
protected SAMLRequestAbstractParser(SAMLProtocolQNames expectedStartElement) {
super(expectedStartElement);
}
/**
* Parse the attributes that are common to all SAML Request Types
*
* @param startElement
* @param request
*
* @throws ParsingException
*/
protected void parseBaseAttributes(StartElement startElement, T request) throws ParsingException {
request.setDestination(StaxParserUtil.getUriAttributeValue(startElement, SAMLProtocolQNames.ATTR_DESTINATION));
request.setConsent(StaxParserUtil.getAttributeValue(startElement, SAMLProtocolQNames.ATTR_CONSENT));
}
/**
* If the current element is one of the common request elements (Issuer, Signature, Extensions), parses it.
* @param element
* @param xmlEventReader
* @param request
* @throws ParsingException
*/
protected void parseCommonElements(SAMLProtocolQNames element, StartElement elementDetail, XMLEventReader xmlEventReader, RequestAbstractType request)
throws ParsingException {
switch (element) {
case ISSUER:
request.setIssuer(SAMLParserUtil.parseNameIDType(xmlEventReader));
break;
case SIGNATURE:
request.setSignature(StaxParserUtil.getDOMElement(xmlEventReader));
break;
case EXTENSIONS:
request.setExtensions(SAMLExtensionsParser.getInstance().parse(xmlEventReader));
break;
}
}
}

View file

@ -0,0 +1,85 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.AuthnContextComparisonType;
import org.keycloak.dom.saml.v2.protocol.RequestedAuthnContextType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
/**
* Parse the SAML2 RequestedAuthnContext
*
* @since Nov 2, 2010
*/
public class SAMLRequestedAuthnContextParser extends AbstractStaxSamlProtocolParser<RequestedAuthnContextType> {
private static final SAMLRequestedAuthnContextParser INSTANCE = new SAMLRequestedAuthnContextParser();
private SAMLRequestedAuthnContextParser() {
super(SAMLProtocolQNames.REQUESTED_AUTHN_CONTEXT);
}
public static SAMLRequestedAuthnContextParser getInstance() {
return INSTANCE;
}
/**
* Parse the attributes at the authnrequesttype element
*
* @param startElement
*
* @return
*
* @throws ParsingException
*/
@Override
protected RequestedAuthnContextType instantiateElement(XMLEventReader xmlEventReader, StartElement startElement) throws ParsingException {
RequestedAuthnContextType context = new RequestedAuthnContextType();
Attribute comparison = startElement.getAttributeByName(SAMLProtocolQNames.ATTR_COMPARISON.getQName());
if (comparison != null) {
context.setComparison(AuthnContextComparisonType.fromValue(comparison.getValue()));
}
return context;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, RequestedAuthnContextType target, SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case AUTHN_CONTEXT_CLASS_REF:
StaxParserUtil.advance(xmlEventReader);
String value = StaxParserUtil.getElementText(xmlEventReader);
target.addAuthnContextClassRef(value);
break;
case AUTHN_CONTEXT_DECL_REF:
StaxParserUtil.advance(xmlEventReader);
value = StaxParserUtil.getElementText(xmlEventReader);
target.addAuthnContextDeclRef(value);
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,96 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.dom.saml.v2.protocol.ResponseType.RTChoiceType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.w3c.dom.Element;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionParser;
import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLEncryptedAssertionParser;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.datatype.XMLGregorianCalendar;
/**
* Parse the SAML Response
*
* @since Nov 2, 2010
*/
public class SAMLResponseParser extends SAMLStatusResponseTypeParser<ResponseType> {
private static final SAMLResponseParser INSTANCE = new SAMLResponseParser();
private SAMLResponseParser() {
super(SAMLProtocolQNames.RESPONSE);
}
public static SAMLResponseParser getInstance() {
return INSTANCE;
}
@Override
protected ResponseType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
SAMLParserUtil.validateAttributeValue(element, SAMLProtocolQNames.ATTR_VERSION, VERSION_2_0);
String id = StaxParserUtil.getRequiredAttributeValue(element, SAMLProtocolQNames.ATTR_ID);
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getRequiredAttributeValue(element, SAMLProtocolQNames.ATTR_ISSUE_INSTANT));
ResponseType res = new ResponseType(id, issueInstant);
// Let us set the attributes
super.parseBaseAttributes(element, res);
return res;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, ResponseType target, SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case ISSUER:
target.setIssuer(SAMLParserUtil.parseNameIDType(xmlEventReader));
break;
case SIGNATURE:
Element sig = StaxParserUtil.getDOMElement(xmlEventReader);
target.setSignature(sig);
break;
case ASSERTION:
target.addAssertion(new RTChoiceType(SAMLAssertionParser.getInstance().parse(xmlEventReader)));
break;
case EXTENSIONS:
target.setExtensions(SAMLExtensionsParser.getInstance().parse(xmlEventReader));
break;
case STATUS:
target.setStatus(SAMLStatusParser.getInstance().parse(xmlEventReader));
break;
case ENCRYPTED_ASSERTION:
target.addAssertion(new RTChoiceType(SAMLEncryptedAssertionParser.getInstance().parse(xmlEventReader)));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,94 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.assertion.EncryptedElementType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import org.w3c.dom.Element;
import static org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLRequestAbstractParser.VERSION_2_0;
/**
* Parse the Single Log Out requests
*
* @since Nov 3, 2010
*/
public class SAMLSloRequestParser extends SAMLRequestAbstractParser<LogoutRequestType> {
private static final SAMLSloRequestParser INSTANCE = new SAMLSloRequestParser();
private SAMLSloRequestParser() {
super(SAMLProtocolQNames.LOGOUT_REQUEST);
}
public static SAMLSloRequestParser getInstance() {
return INSTANCE;
}
@Override
protected LogoutRequestType instantiateElement(XMLEventReader xmlEventReader, StartElement startElement) throws ParsingException {
SAMLParserUtil.validateAttributeValue(startElement, SAMLProtocolQNames.ATTR_VERSION, VERSION_2_0);
String id = StaxParserUtil.getRequiredAttributeValue(startElement, SAMLProtocolQNames.ATTR_ID);
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getRequiredAttributeValue(startElement, SAMLProtocolQNames.ATTR_ISSUE_INSTANT));
LogoutRequestType logoutRequest = new LogoutRequestType(id, issueInstant);
super.parseBaseAttributes(startElement, logoutRequest);
logoutRequest.setReason(StaxParserUtil.getAttributeValue(startElement, SAMLProtocolQNames.ATTR_REASON));
logoutRequest.setNotOnOrAfter(StaxParserUtil.getXmlTimeAttributeValue(startElement, SAMLProtocolQNames.ATTR_NOT_ON_OR_AFTER));
return logoutRequest;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, LogoutRequestType target,
SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case ISSUER:
case SIGNATURE:
case EXTENSIONS:
parseCommonElements(element, elementDetail, xmlEventReader, target);
break;
case NAMEID:
NameIDType nameID = SAMLParserUtil.parseNameIDType(xmlEventReader);
target.setNameID(nameID);
break;
case ENCRYPTED_ID:
Element domElement = StaxParserUtil.getDOMElement(xmlEventReader);
target.setEncryptedID(new EncryptedElementType(domElement));
break;
case SESSION_INDEX:
StaxParserUtil.getNextStartElement(xmlEventReader);
target.addSessionIndex(StaxParserUtil.getElementText(xmlEventReader));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,88 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import org.w3c.dom.Element;
import static org.keycloak.saml.processing.core.parsers.saml.protocol.SAMLStatusResponseTypeParser.VERSION_2_0;
/**
* Parse the SLO Response
*
* @since Nov 3, 2010
*/
public class SAMLSloResponseParser extends SAMLStatusResponseTypeParser<StatusResponseType> {
private static final SAMLSloResponseParser INSTANCE = new SAMLSloResponseParser();
public SAMLSloResponseParser() {
super(SAMLProtocolQNames.LOGOUT_RESPONSE);
}
public static SAMLSloResponseParser getInstance() {
return INSTANCE;
}
@Override
protected StatusResponseType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
SAMLParserUtil.validateAttributeValue(element, SAMLProtocolQNames.ATTR_VERSION, VERSION_2_0);
String id = StaxParserUtil.getRequiredAttributeValue(element, SAMLProtocolQNames.ATTR_ID);
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getRequiredAttributeValue(element, SAMLProtocolQNames.ATTR_ISSUE_INSTANT));
StatusResponseType res = new StatusResponseType(id, issueInstant);
// Let us set the attributes
super.parseBaseAttributes(element, res);
return res;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, StatusResponseType target, SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case ISSUER:
target.setIssuer(SAMLParserUtil.parseNameIDType(xmlEventReader));
break;
case SIGNATURE:
Element sig = StaxParserUtil.getDOMElement(xmlEventReader);
target.setSignature(sig);
break;
case EXTENSIONS:
SAMLExtensionsParser extensionsParser = SAMLExtensionsParser.getInstance();
target.setExtensions(extensionsParser.parse(xmlEventReader));
break;
case STATUS:
target.setStatus(SAMLStatusParser.getInstance().parse(xmlEventReader));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,59 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.StatusCodeType;
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;
/**
* Base Class for all Response Type parsing for SAML2
*
*/
public class SAMLStatusCodeParser extends AbstractStaxSamlProtocolParser<StatusCodeType> {
private static final SAMLStatusCodeParser INSTANCE = new SAMLStatusCodeParser();
private SAMLStatusCodeParser() {
super(SAMLProtocolQNames.STATUS_CODE);
}
public static SAMLStatusCodeParser getInstance() {
return INSTANCE;
}
@Override
protected StatusCodeType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
final StatusCodeType res = new StatusCodeType();
res.setValue(StaxParserUtil.getUriAttributeValue(element, SAMLProtocolQNames.ATTR_VALUE));
return res;
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, StatusCodeType target, SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case STATUS_CODE:
target.setStatusCode(SAMLStatusCodeParser.getInstance().parse(xmlEventReader));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,78 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.StatusDetailType;
import org.keycloak.dom.saml.v2.protocol.StatusType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.parsers.AnyDomParser;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.w3c.dom.Element;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.StartElement;
import java.util.List;
/**
* Base Class for all Response Type parsing for SAML2
*
*/
public class SAMLStatusParser extends AbstractStaxSamlProtocolParser<StatusType> {
private static final SAMLStatusParser INSTANCE = new SAMLStatusParser();
private static final AnyDomParser STATUS_DETAIL_PARSER = AnyDomParser.getInstance(SAMLProtocolQNames.STATUS_DETAIL.getQName());
private SAMLStatusParser() {
super(SAMLProtocolQNames.STATUS);
}
public static SAMLStatusParser getInstance() {
return INSTANCE;
}
@Override
protected StatusType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new StatusType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, StatusType target, SAMLProtocolQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case STATUS_CODE:
target.setStatusCode(SAMLStatusCodeParser.getInstance().parse(xmlEventReader));
break;
case STATUS_MESSAGE:
StaxParserUtil.advance(xmlEventReader);
target.setStatusMessage(StaxParserUtil.getElementText(xmlEventReader));
break;
case STATUS_DETAIL:
List<Element> elements = STATUS_DETAIL_PARSER.parse(xmlEventReader);
StatusDetailType statusDetailType = new StatusDetailType();
for (Element e : elements) {
statusDetailType.addStatusDetail(e);
}
target.setStatusDetail(statusDetailType);
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,49 @@
/*
* 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.protocol;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil;
import javax.xml.stream.events.StartElement;
/**
* Base Class for all Response Type parsing for SAML2
*
*/
public abstract class SAMLStatusResponseTypeParser<T extends StatusResponseType> extends AbstractStaxSamlProtocolParser<T> {
protected static final String VERSION_2_0 = "2.0";
protected SAMLStatusResponseTypeParser(SAMLProtocolQNames expectedStartElement) {
super(expectedStartElement);
}
/**
* Parse the attributes that are common to all SAML Response Types
*
* @param startElement
* @param response
*
* @throws org.keycloak.saml.common.exceptions.ParsingException
*/
protected void parseBaseAttributes(StartElement startElement, T response) throws ParsingException {
response.setDestination(StaxParserUtil.getAttributeValue(startElement, SAMLProtocolQNames.ATTR_DESTINATION));
response.setConsent(StaxParserUtil.getAttributeValue(startElement, SAMLProtocolQNames.ATTR_CONSENT));
response.setInResponseTo(StaxParserUtil.getAttributeValue(startElement, SAMLProtocolQNames.ATTR_IN_RESPONSE_TO));
}
}

View file

@ -0,0 +1,40 @@
/*
* 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.xmldsig;
import org.keycloak.saml.common.parsers.AbstractStaxParser;
import org.keycloak.saml.processing.core.parsers.util.QNameEnumLookup;
import javax.xml.namespace.QName;
/**
*
* @author hmlnarik
*/
public abstract class AbstractStaxXmlDSigParser<T> extends AbstractStaxParser<T, XmlDSigQNames> {
protected static final QNameEnumLookup<XmlDSigQNames> LOOKUP = new QNameEnumLookup(XmlDSigQNames.values());
public AbstractStaxXmlDSigParser(XmlDSigQNames expectedStartElement) {
super(expectedStartElement.getQName(), XmlDSigQNames.UNKNOWN_ELEMENT);
}
@Override
protected XmlDSigQNames getElementFromName(QName name) {
return LOOKUP.from(name);
}
}

View file

@ -0,0 +1,94 @@
/*
* 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.xmldsig;
import org.keycloak.dom.xmlsec.w3.xmldsig.DSAKeyValueType;
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;
public class DsaKeyValueParser extends AbstractStaxXmlDSigParser<DSAKeyValueType> {
public static final DsaKeyValueParser INSTANCE = new DsaKeyValueParser();
private DsaKeyValueParser() {
super(XmlDSigQNames.DSA_KEY_VALUE);
}
public static DsaKeyValueParser getInstance() {
return INSTANCE;
}
@Override
protected DSAKeyValueType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new DSAKeyValueType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, DSAKeyValueType target, XmlDSigQNames element, StartElement elementDetail) throws ParsingException {
String text;
switch (element) {
case P:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
target.setP(text.getBytes(GeneralConstants.SAML_CHARSET));
break;
case Q:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
target.setQ(text.getBytes(GeneralConstants.SAML_CHARSET));
break;
case G:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
target.setG(text.getBytes(GeneralConstants.SAML_CHARSET));
break;
case Y:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
target.setY(text.getBytes(GeneralConstants.SAML_CHARSET));
break;
case J:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
target.setJ(text.getBytes(GeneralConstants.SAML_CHARSET));
break;
case SEED:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
target.setSeed(text.getBytes(GeneralConstants.SAML_CHARSET));
break;
case PGEN_COUNTER:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
target.setPgenCounter(text.getBytes(GeneralConstants.SAML_CHARSET));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,78 @@
/*
* 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.xmldsig;
import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType;
import org.keycloak.dom.xmlsec.w3.xmldsig.KeyValueType;
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;
public class KeyInfoParser extends AbstractStaxXmlDSigParser<KeyInfoType> {
public static final KeyInfoParser INSTANCE = new KeyInfoParser();
private KeyInfoParser() {
super(XmlDSigQNames.KEY_INFO);
}
public static KeyInfoParser getInstance() {
return INSTANCE;
}
@Override
protected KeyInfoType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new KeyInfoType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, KeyInfoType target, XmlDSigQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case X509_DATA:
target.addContent(X509DataParser.getInstance().parse(xmlEventReader));
break;
case KEY_VALUE:
StaxParserUtil.advance(xmlEventReader);
StartElement startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
KeyValueType keyValue;
switch (LOOKUP.from(startElement.getName())) {
case RSA_KEY_VALUE:
keyValue = RsaKeyValueParser.getInstance().parse(xmlEventReader);
break;
case DSA_KEY_VALUE:
keyValue = DsaKeyValueParser.getInstance().parse(xmlEventReader);
break;
default:
String tag = StaxParserUtil.getElementName(startElement);
throw LOGGER.parserUnknownTag(tag, elementDetail.getLocation());
}
target.addContent(keyValue);
break;
default:
// Ignore unknown tags
StaxParserUtil.bypassElementBlock(xmlEventReader);
}
}
}

View file

@ -0,0 +1,64 @@
/*
* 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.xmldsig;
import org.keycloak.dom.xmlsec.w3.xmldsig.RSAKeyValueType;
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;
public class RsaKeyValueParser extends AbstractStaxXmlDSigParser<RSAKeyValueType> {
public static final RsaKeyValueParser INSTANCE = new RsaKeyValueParser();
private RsaKeyValueParser() {
super(XmlDSigQNames.RSA_KEY_VALUE);
}
public static RsaKeyValueParser getInstance() {
return INSTANCE;
}
@Override
protected RSAKeyValueType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new RSAKeyValueType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, RSAKeyValueType target, XmlDSigQNames element, StartElement elementDetail) throws ParsingException {
String text;
switch (element) {
case MODULUS:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
target.setModulus(text.getBytes(GeneralConstants.SAML_CHARSET));
break;
case EXPONENT:
StaxParserUtil.advance(xmlEventReader);
text = StaxParserUtil.getElementText(xmlEventReader);
target.setExponent(text.getBytes(GeneralConstants.SAML_CHARSET));
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,66 @@
/*
* 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.xmldsig;
import org.keycloak.dom.xmlsec.w3.xmldsig.X509CertificateType;
import org.keycloak.dom.xmlsec.w3.xmldsig.X509DataType;
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;
/**
* Base Class for all Response Type parsing for SAML2
*
*/
public class X509DataParser extends AbstractStaxXmlDSigParser<X509DataType> {
private static final X509DataParser INSTANCE = new X509DataParser();
public X509DataParser() {
super(XmlDSigQNames.X509_DATA);
}
public static X509DataParser getInstance() {
return INSTANCE;
}
@Override
protected X509DataType instantiateElement(XMLEventReader xmlEventReader, StartElement element) throws ParsingException {
return new X509DataType();
}
@Override
protected void processSubElement(XMLEventReader xmlEventReader, X509DataType target, XmlDSigQNames element, StartElement elementDetail) throws ParsingException {
switch (element) {
case X509_CERTIFICATE:
StaxParserUtil.advance(xmlEventReader);
String certValue = StaxParserUtil.getElementText(xmlEventReader);
X509CertificateType cert = new X509CertificateType();
cert.setEncodedCertificate(certValue.getBytes(GeneralConstants.SAML_CHARSET));
target.add(cert);
break;
default:
throw LOGGER.parserUnknownTag(StaxParserUtil.getElementName(elementDetail), elementDetail.getLocation());
}
}
}

View file

@ -0,0 +1,96 @@
/*
* 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.xmldsig;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import javax.xml.namespace.QName;
import org.keycloak.saml.processing.core.parsers.util.HasQName;
/**
* Elements from saml-schema-protocol-2.0.xsd
* @author hmlnarik
*/
public enum XmlDSigQNames implements HasQName {
CANONICALIZATION_METHOD("CanonicalizationMethod"),
DIGEST_METHOD("DigestMethod"),
DIGEST_VALUE("DigestValue"),
DSA_KEY_VALUE("DSAKeyValue"),
EXPONENT("Exponent"),
G("G"),
HMAC_OUTPUT_LENGTH("HMACOutputLength"),
J("J"),
KEY_INFO("KeyInfo"),
KEY_NAME("KeyName"),
KEY_VALUE("KeyValue"),
MANIFEST("Manifest"),
MGMT_DATA("MgmtData"),
MODULUS("Modulus"),
OBJECT("Object"),
PGEN_COUNTER("PgenCounter"),
PGP_DATA("PGPData"),
PGP_KEY_ID("PGPKeyID"),
PGP_KEY_PACKET("PGPKeyPacket"),
P("P"),
Q("Q"),
REFERENCE("Reference"),
RETRIEVAL_METHOD("RetrievalMethod"),
RSA_KEY_VALUE("RSAKeyValue"),
SEED("Seed"),
SIGNATURE_METHOD("SignatureMethod"),
SIGNATURE_PROPERTIES("SignatureProperties"),
SIGNATURE_PROPERTY("SignatureProperty"),
SIGNATURE("Signature"),
SIGNATURE_VALUE("SignatureValue"),
SIGNED_INFO("SignedInfo"),
SPKI_DATA("SPKIData"),
SPKIS_EXP("SPKISexp"),
TRANSFORMS("Transforms"),
TRANSFORM("Transform"),
XPATH("XPath"),
X509_CERTIFICATE("X509Certificate"),
X509_CRL("X509CRL"),
X509_DATA("X509Data"),
X509_ISSUER_NAME("X509IssuerName"),
X509_ISSUER_SERIAL("X509IssuerSerial"),
X509_SERIAL_NUMBER("X509SerialNumber"),
X509_SKI("X509SKI"),
X509_SUBJECT_NAME("X509SubjectName"),
Y("Y"),
UNKNOWN_ELEMENT("")
;
private final QName qName;
private XmlDSigQNames(String localName) {
this(JBossSAMLURIConstants.XMLDSIG_NSURI, localName);
}
private XmlDSigQNames(HasQName source) {
this.qName = source.getQName();
}
private XmlDSigQNames(JBossSAMLURIConstants nsUri, String localName) {
this.qName = new QName(nsUri == null ? null : nsUri.get(), localName);
}
@Override
public QName getQName() {
return qName;
}
}

View file

@ -0,0 +1,29 @@
/*
* 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.util;
import javax.xml.namespace.QName;
/**
*
* @author hmlnarik
*/
public interface HasQName {
QName getQName();
}

View file

@ -0,0 +1,64 @@
/*
* 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.util;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
/**
*
* @author hmlnarik
*/
public class QNameEnumLookup<E extends Enum<E> & HasQName> {
private final Map<QName, E> qNameConstants;
public QNameEnumLookup(E[] e) {
Map<QName, E> q = new HashMap<>(e.length);
E old;
for (E c : e) {
QName qName = c.getQName();
if ((old = q.put(qName, c)) != null) {
throw new IllegalStateException("Same name " + qName + " used for two distinct constants: " + c + ", " + old);
}
// Add the relaxed version without namespace
if (qName.getNamespaceURI() != null && ! Objects.equals(qName.getNamespaceURI(), XMLConstants.NULL_NS_URI)) {
qName = new QName(qName.getLocalPart());
if (q.containsKey(qName)) {
q.put(qName, null);
} else {
q.put(qName, c);
}
}
}
this.qNameConstants = Collections.unmodifiableMap(q);
}
public E from(QName name) {
E c = qNameConstants.get(name);
if (c == null) {
name = new QName(name.getLocalPart());
c = qNameConstants.get(name);
}
return c;
}
}

View file

@ -49,7 +49,6 @@ import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.StaxParserUtil; import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.core.parsers.saml.SAML11SubjectParser; import org.keycloak.saml.processing.core.parsers.saml.SAML11SubjectParser;
import org.keycloak.saml.processing.core.saml.v1.SAML11Constants; import org.keycloak.saml.processing.core.saml.v1.SAML11Constants;
import org.keycloak.saml.processing.core.saml.v2.util.SignatureUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil; import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@ -61,6 +60,8 @@ import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement; import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent; import javax.xml.stream.events.XMLEvent;
import java.net.URI; import java.net.URI;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/** /**
* Utility for parsing SAML 1.1 payload * Utility for parsing SAML 1.1 payload
@ -106,11 +107,11 @@ public class SAML11ParserUtil {
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader); xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader);
EndElement endElement = (EndElement) xmlEvent; EndElement endElement = (EndElement) xmlEvent;
String endElementTag = StaxParserUtil.getEndElementName(endElement); String endElementTag = StaxParserUtil.getElementName(endElement);
if (endElementTag.equals(SAML11Constants.AUTHENTICATION_STATEMENT)) if (endElementTag.equals(SAML11Constants.AUTHENTICATION_STATEMENT))
break; break;
else else
throw logger.parserUnknownEndElement(endElementTag); throw logger.parserUnknownEndElement(endElementTag, xmlEvent.getLocation());
} }
startElement = null; startElement = null;
@ -122,7 +123,7 @@ public class SAML11ParserUtil {
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (JBossSAMLConstants.SUBJECT.get().equalsIgnoreCase(tag)) { if (JBossSAMLConstants.SUBJECT.get().equalsIgnoreCase(tag)) {
SAML11SubjectParser subjectParser = new SAML11SubjectParser(); SAML11SubjectParser subjectParser = new SAML11SubjectParser();
@ -199,7 +200,7 @@ public class SAML11ParserUtil {
if (xmlEvent instanceof StartElement) { if (xmlEvent instanceof StartElement) {
startElement = (StartElement) xmlEvent; startElement = (StartElement) xmlEvent;
String startTag = StaxParserUtil.getStartElementName(startElement); String startTag = StaxParserUtil.getElementName(startElement);
if (startTag.equals(SAML11Constants.CONFIRMATION_METHOD)) { if (startTag.equals(SAML11Constants.CONFIRMATION_METHOD)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader); startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
@ -264,7 +265,7 @@ public class SAML11ParserUtil {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader); XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (!(xmlEvent instanceof EndElement)) { if (!(xmlEvent instanceof EndElement)) {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(WSTrustConstants.XMLDSig.KEYINFO)) { if (tag.equals(WSTrustConstants.XMLDSig.KEYINFO)) {
KeyInfoType keyInfo = parseKeyInfo(xmlEventReader); KeyInfoType keyInfo = parseKeyInfo(xmlEventReader);
subjectConfirmationData.setAnyType(keyInfo); subjectConfirmationData.setAnyType(keyInfo);
@ -371,7 +372,7 @@ public class SAML11ParserUtil {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (JBossSAMLConstants.ATTRIBUTE.get().equals(tag)) if (JBossSAMLConstants.ATTRIBUTE.get().equals(tag))
break; break;
@ -440,7 +441,7 @@ public class SAML11ParserUtil {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (SAML11Constants.ACTION.equals(tag)) { if (SAML11Constants.ACTION.equals(tag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader); startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
@ -512,14 +513,14 @@ public class SAML11ParserUtil {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null) if (startElement == null)
break; break;
String tag = StaxParserUtil.getStartElementName(startElement); String tag = StaxParserUtil.getElementName(startElement);
if (SAML11Constants.AUDIENCE_RESTRICTION_CONDITION.equals(tag)) { if (SAML11Constants.AUDIENCE_RESTRICTION_CONDITION.equals(tag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader); startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
SAML11AudienceRestrictionCondition restrictCond = new SAML11AudienceRestrictionCondition(); SAML11AudienceRestrictionCondition restrictCond = new SAML11AudienceRestrictionCondition();
startElement = StaxParserUtil.getNextStartElement(xmlEventReader); startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
if (StaxParserUtil.getStartElementName(startElement).equals(JBossSAMLConstants.AUDIENCE.get())) { if (StaxParserUtil.getElementName(startElement).equals(JBossSAMLConstants.AUDIENCE.get())) {
restrictCond.add(URI.create(StaxParserUtil.getElementText(xmlEventReader))); restrictCond.add(URI.create(StaxParserUtil.getElementText(xmlEventReader)));
} }
EndElement theEndElement = StaxParserUtil.getNextEndElement(xmlEventReader); EndElement theEndElement = StaxParserUtil.getNextEndElement(xmlEventReader);
@ -542,15 +543,15 @@ public class SAML11ParserUtil {
while (xmlEventReader.hasNext()) { while (xmlEventReader.hasNext()) {
xmlEvent = StaxParserUtil.peek(xmlEventReader); xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
tag = StaxParserUtil.getEndElementName((EndElement) xmlEvent); tag = StaxParserUtil.getElementName((EndElement) xmlEvent);
if (tag.equals(WSTrustConstants.XMLDSig.KEYINFO)) { if (tag.equals(WSTrustConstants.XMLDSig.KEYINFO)) {
xmlEvent = StaxParserUtil.getNextEndElement(xmlEventReader); xmlEvent = StaxParserUtil.getNextEndElement(xmlEventReader);
break; break;
} else } else
throw logger.parserUnknownEndElement(tag); throw logger.parserUnknownEndElement(tag, xmlEvent.getLocation());
} }
startElement = (StartElement) xmlEvent; startElement = (StartElement) xmlEvent;
tag = StaxParserUtil.getStartElementName(startElement); tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(WSTrustConstants.XMLEnc.ENCRYPTED_KEY)) { if (tag.equals(WSTrustConstants.XMLEnc.ENCRYPTED_KEY)) {
keyInfo.addContent(StaxParserUtil.getDOMElement(xmlEventReader)); keyInfo.addContent(StaxParserUtil.getDOMElement(xmlEventReader));
} else if (tag.equals(WSTrustConstants.XMLDSig.X509DATA)) { } else if (tag.equals(WSTrustConstants.XMLDSig.X509DATA)) {
@ -574,7 +575,7 @@ public class SAML11ParserUtil {
KeyValueType keyValue = null; KeyValueType keyValue = null;
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader); startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
tag = StaxParserUtil.getStartElementName(startElement); tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(WSTrustConstants.XMLDSig.RSA_KEYVALUE)) { if (tag.equals(WSTrustConstants.XMLDSig.RSA_KEYVALUE)) {
keyValue = parseRSAKeyValue(xmlEventReader); keyValue = parseRSAKeyValue(xmlEventReader);
} else if (tag.equals(WSTrustConstants.XMLDSig.DSA_KEYVALUE)) { } else if (tag.equals(WSTrustConstants.XMLDSig.DSA_KEYVALUE)) {
@ -603,16 +604,16 @@ public class SAML11ParserUtil {
while (xmlEventReader.hasNext()) { while (xmlEventReader.hasNext()) {
xmlEvent = StaxParserUtil.peek(xmlEventReader); xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) { if (xmlEvent instanceof EndElement) {
tag = StaxParserUtil.getEndElementName((EndElement) xmlEvent); tag = StaxParserUtil.getElementName((EndElement) xmlEvent);
if (tag.equals(WSTrustConstants.XMLDSig.RSA_KEYVALUE)) { if (tag.equals(WSTrustConstants.XMLDSig.RSA_KEYVALUE)) {
xmlEvent = StaxParserUtil.getNextEndElement(xmlEventReader); xmlEvent = StaxParserUtil.getNextEndElement(xmlEventReader);
break; break;
} else } else
throw logger.parserUnknownEndElement(tag); throw logger.parserUnknownEndElement(tag, xmlEvent.getLocation());
} }
startElement = (StartElement) xmlEvent; startElement = (StartElement) xmlEvent;
tag = StaxParserUtil.getStartElementName(startElement); tag = StaxParserUtil.getElementName(startElement);
if (tag.equals(WSTrustConstants.XMLDSig.MODULUS)) { if (tag.equals(WSTrustConstants.XMLDSig.MODULUS)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader); startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String text = StaxParserUtil.getElementText(xmlEventReader); String text = StaxParserUtil.getElementText(xmlEventReader);
@ -632,7 +633,48 @@ public class SAML11ParserUtil {
StaxParserUtil.validate(startElement, WSTrustConstants.XMLDSig.DSA_KEYVALUE); StaxParserUtil.validate(startElement, WSTrustConstants.XMLDSig.DSA_KEYVALUE);
Element dsaElement = StaxParserUtil.getDOMElement(xmlEventReader); Element dsaElement = StaxParserUtil.getDOMElement(xmlEventReader);
return SignatureUtil.getDSAKeyValue(dsaElement); return getDSAKeyValue(dsaElement);
}
/**
* Given a dsig:DSAKeyValue element, return {@link DSAKeyValueType}
*
* @param element
*
* @return
*
* @throws org.keycloak.saml.common.exceptions.ParsingException
*/
private static DSAKeyValueType getDSAKeyValue(Element element) throws ParsingException {
DSAKeyValueType dsa = new DSAKeyValueType();
NodeList nl = element.getChildNodes();
int length = nl.getLength();
for (int i = 0; i < length; i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element childElement = (Element) node;
String tag = childElement.getLocalName();
byte[] text = childElement.getTextContent().getBytes(GeneralConstants.SAML_CHARSET);
if (WSTrustConstants.XMLDSig.P.equals(tag)) {
dsa.setP(text);
} else if (WSTrustConstants.XMLDSig.Q.equals(tag)) {
dsa.setQ(text);
} else if (WSTrustConstants.XMLDSig.G.equals(tag)) {
dsa.setG(text);
} else if (WSTrustConstants.XMLDSig.Y.equals(tag)) {
dsa.setY(text);
} else if (WSTrustConstants.XMLDSig.SEED.equals(tag)) {
dsa.setSeed(text);
} else if (WSTrustConstants.XMLDSig.PGEN_COUNTER.equals(tag)) {
dsa.setPgenCounter(text);
}
}
}
return dsa;
} }
/** /**
@ -655,13 +697,13 @@ public class SAML11ParserUtil {
if (StaxParserUtil.matches(endElement, SAML11Constants.ATTRIBUTE_QUERY)) if (StaxParserUtil.matches(endElement, SAML11Constants.ATTRIBUTE_QUERY))
break; break;
else else
throw logger.parserUnknownEndElement(StaxParserUtil.getEndElementName(endElement)); throw logger.parserUnknownEndElement(StaxParserUtil.getElementName(endElement), xmlEvent.getLocation());
} }
if (xmlEvent instanceof StartElement) { if (xmlEvent instanceof StartElement) {
startElement = (StartElement) xmlEvent; startElement = (StartElement) xmlEvent;
String startTag = StaxParserUtil.getStartElementName(startElement); String startTag = StaxParserUtil.getElementName(startElement);
if (startTag.equals(JBossSAMLConstants.SUBJECT.get())) { if (startTag.equals(JBossSAMLConstants.SUBJECT.get())) {
SAML11SubjectParser parser = new SAML11SubjectParser(); SAML11SubjectParser parser = new SAML11SubjectParser();
@ -694,13 +736,13 @@ public class SAML11ParserUtil {
if (StaxParserUtil.matches(endElement, SAML11Constants.AUTHENTICATION_QUERY)) if (StaxParserUtil.matches(endElement, SAML11Constants.AUTHENTICATION_QUERY))
break; break;
else else
throw logger.parserUnknownEndElement(StaxParserUtil.getEndElementName(endElement)); throw logger.parserUnknownEndElement(StaxParserUtil.getElementName(endElement), xmlEvent.getLocation());
} }
if (xmlEvent instanceof StartElement) { if (xmlEvent instanceof StartElement) {
startElement = (StartElement) xmlEvent; startElement = (StartElement) xmlEvent;
String startTag = StaxParserUtil.getStartElementName(startElement); String startTag = StaxParserUtil.getElementName(startElement);
if (startTag.equals(JBossSAMLConstants.SUBJECT.get())) { if (startTag.equals(JBossSAMLConstants.SUBJECT.get())) {
SAML11SubjectParser parser = new SAML11SubjectParser(); SAML11SubjectParser parser = new SAML11SubjectParser();
@ -733,13 +775,13 @@ public class SAML11ParserUtil {
if (StaxParserUtil.matches(endElement, SAML11Constants.AUTHORIZATION_DECISION_QUERY)) if (StaxParserUtil.matches(endElement, SAML11Constants.AUTHORIZATION_DECISION_QUERY))
break; break;
else else
throw logger.parserUnknownEndElement(StaxParserUtil.getEndElementName(endElement)); throw logger.parserUnknownEndElement(StaxParserUtil.getElementName(endElement), xmlEvent.getLocation());
} }
if (xmlEvent instanceof StartElement) { if (xmlEvent instanceof StartElement) {
startElement = (StartElement) xmlEvent; startElement = (StartElement) xmlEvent;
String startTag = StaxParserUtil.getStartElementName(startElement); String startTag = StaxParserUtil.getElementName(startElement);
if (startTag.equals(JBossSAMLConstants.SUBJECT.get())) { if (startTag.equals(JBossSAMLConstants.SUBJECT.get())) {
SAML11SubjectParser parser = new SAML11SubjectParser(); SAML11SubjectParser parser = new SAML11SubjectParser();

View file

@ -15,51 +15,16 @@
* limitations under the License. * limitations under the License.
*/ */
package org.keycloak.saml.processing.core.parsers.util; package org.keycloak.saml.processing.core.parsers.util;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType.ASTChoiceType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.assertion.AuthnContextClassRefType;
import org.keycloak.dom.saml.v2.assertion.AuthnContextDeclRefType;
import org.keycloak.dom.saml.v2.assertion.AuthnContextDeclType;
import org.keycloak.dom.saml.v2.assertion.AuthnContextType;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectLocalityType;
import org.keycloak.dom.xmlsec.w3.xmldsig.DSAKeyValueType;
import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType;
import org.keycloak.dom.xmlsec.w3.xmldsig.KeyValueType;
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.saml.common.PicketLinkLogger; import org.keycloak.saml.common.PicketLinkLogger;
import org.keycloak.saml.common.PicketLinkLoggerFactory; 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.constants.WSTrustConstants;
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 org.keycloak.saml.common.util.StringUtil;
import org.keycloak.saml.processing.core.saml.v2.util.SignatureUtil;
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
import org.w3c.dom.Element; import org.keycloak.saml.processing.core.parsers.saml.assertion.SAMLAssertionQNames;
import java.util.Objects;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement; import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import java.io.StringWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/** /**
* Utility methods for SAML Parser * Utility methods for SAML Parser
@ -69,472 +34,7 @@ import java.util.StringTokenizer;
*/ */
public class SAMLParserUtil { public class SAMLParserUtil {
private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private static final PicketLinkLogger LOGGER = PicketLinkLoggerFactory.getLogger();
public static KeyInfoType parseKeyInfo(XMLEventReader xmlEventReader) throws ParsingException {
KeyInfoType keyInfo = new KeyInfoType();
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, WSTrustConstants.XMLDSig.KEYINFO);
XMLEvent xmlEvent = null;
String tag = null;
while (xmlEventReader.hasNext()) {
xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
tag = StaxParserUtil.getEndElementName((EndElement) xmlEvent);
if (tag.equals(WSTrustConstants.XMLDSig.KEYINFO)) {
xmlEvent = StaxParserUtil.getNextEndElement(xmlEventReader);
break;
} else
throw logger.parserUnknownEndElement(tag);
}
startElement = (StartElement) xmlEvent;
tag = StaxParserUtil.getStartElementName(startElement);
if (tag.equals(WSTrustConstants.XMLEnc.ENCRYPTED_KEY)) {
keyInfo.addContent(StaxParserUtil.getDOMElement(xmlEventReader));
} else if (tag.equals(WSTrustConstants.XMLDSig.X509DATA)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
X509DataType x509 = new X509DataType();
// Let us go for the X509 certificate
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, WSTrustConstants.XMLDSig.X509CERT);
X509CertificateType cert = new X509CertificateType();
String certValue = StaxParserUtil.getElementText(xmlEventReader);
cert.setEncodedCertificate(certValue.getBytes(GeneralConstants.SAML_CHARSET));
x509.add(cert);
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
StaxParserUtil.validate(endElement, WSTrustConstants.XMLDSig.X509DATA);
keyInfo.addContent(x509);
} else if (tag.equals(WSTrustConstants.XMLDSig.KEYVALUE)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
KeyValueType keyValue = null;
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
tag = StaxParserUtil.getStartElementName(startElement);
if (tag.equals(WSTrustConstants.XMLDSig.RSA_KEYVALUE)) {
keyValue = parseRSAKeyValue(xmlEventReader);
} else if (tag.equals(WSTrustConstants.XMLDSig.DSA_KEYVALUE)) {
keyValue = parseDSAKeyValue(xmlEventReader);
} else
throw logger.parserUnknownTag(tag, startElement.getLocation());
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
StaxParserUtil.validate(endElement, WSTrustConstants.XMLDSig.KEYVALUE);
keyInfo.addContent(keyValue);
}
}
return keyInfo;
}
private static RSAKeyValueType parseRSAKeyValue(XMLEventReader xmlEventReader) throws ParsingException {
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, WSTrustConstants.XMLDSig.RSA_KEYVALUE);
XMLEvent xmlEvent = null;
String tag = null;
RSAKeyValueType rsaKeyValue = new RSAKeyValueType();
while (xmlEventReader.hasNext()) {
xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
tag = StaxParserUtil.getEndElementName((EndElement) xmlEvent);
if (tag.equals(WSTrustConstants.XMLDSig.RSA_KEYVALUE)) {
xmlEvent = StaxParserUtil.getNextEndElement(xmlEventReader);
break;
} else
throw logger.parserUnknownEndElement(tag);
}
startElement = (StartElement) xmlEvent;
tag = StaxParserUtil.getStartElementName(startElement);
if (tag.equals(WSTrustConstants.XMLDSig.MODULUS)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String text = StaxParserUtil.getElementText(xmlEventReader);
rsaKeyValue.setModulus(text.getBytes(GeneralConstants.SAML_CHARSET));
} else if (tag.equals(WSTrustConstants.XMLDSig.EXPONENT)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String text = StaxParserUtil.getElementText(xmlEventReader);
rsaKeyValue.setExponent(text.getBytes(GeneralConstants.SAML_CHARSET));
} else
throw logger.parserUnknownTag(tag, startElement.getLocation());
}
return rsaKeyValue;
}
private static DSAKeyValueType parseDSAKeyValue(XMLEventReader xmlEventReader) throws ParsingException {
StartElement startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, WSTrustConstants.XMLDSig.DSA_KEYVALUE);
Element dsaElement = StaxParserUtil.getDOMElement(xmlEventReader);
return SignatureUtil.getDSAKeyValue(dsaElement);
}
/**
* Parse an {@code AttributeStatementType}
*
* @param xmlEventReader
*
* @return
*
* @throws ParsingException
*/
public static AttributeStatementType parseAttributeStatement(XMLEventReader xmlEventReader) throws ParsingException {
AttributeStatementType attributeStatementType = new AttributeStatementType();
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String ATTRIBSTATEMT = JBossSAMLConstants.ATTRIBUTE_STATEMENT.get();
StaxParserUtil.validate(startElement, ATTRIBSTATEMT);
while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
StaxParserUtil.validate(endElement, JBossSAMLConstants.ATTRIBUTE_STATEMENT.get());
break;
}
// Get the next start element
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
String tag = startElement.getName().getLocalPart();
if (JBossSAMLConstants.ATTRIBUTE.get().equals(tag)) {
AttributeType attribute = parseAttribute(xmlEventReader);
attributeStatementType.addAttribute(new ASTChoiceType(attribute));
} else
throw logger.parserUnknownTag(tag, startElement.getLocation());
}
return attributeStatementType;
}
/**
* Parse an {@code AttributeType}
*
* @param xmlEventReader
*
* @return
*
* @throws ParsingException
*/
public static AttributeType parseAttribute(XMLEventReader xmlEventReader) throws ParsingException {
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.ATTRIBUTE.get());
AttributeType attributeType = null;
Attribute name = startElement.getAttributeByName(new QName(JBossSAMLConstants.NAME.get()));
if (name == null)
throw logger.parserRequiredAttribute("Name");
attributeType = new AttributeType(StaxParserUtil.getAttributeValue(name));
parseAttributeType(xmlEventReader, startElement, JBossSAMLConstants.ATTRIBUTE.get(), attributeType);
return attributeType;
}
/**
* Parse an {@code AttributeType}
*
* @param xmlEventReader
*
* @throws ParsingException
*/
public static void parseAttributeType(XMLEventReader xmlEventReader, StartElement startElement, String rootTag,
AttributeType attributeType) throws ParsingException {
// Look for X500 Encoding
QName x500EncodingName = new QName(JBossSAMLURIConstants.X500_NSURI.get(), JBossSAMLConstants.ENCODING.get(),
JBossSAMLURIConstants.X500_PREFIX.get());
Attribute x500EncodingAttr = startElement.getAttributeByName(x500EncodingName);
if (x500EncodingAttr != null) {
attributeType.getOtherAttributes().put(x500EncodingAttr.getName(),
StaxParserUtil.getAttributeValue(x500EncodingAttr));
}
Attribute friendlyName = startElement.getAttributeByName(new QName(JBossSAMLConstants.FRIENDLY_NAME.get()));
if (friendlyName != null)
attributeType.setFriendlyName(StaxParserUtil.getAttributeValue(friendlyName));
Attribute nameFormat = startElement.getAttributeByName(new QName(JBossSAMLConstants.NAME_FORMAT.get()));
if (nameFormat != null)
attributeType.setNameFormat(StaxParserUtil.getAttributeValue(nameFormat));
while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof EndElement) {
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
if (StaxParserUtil.matches(end, rootTag))
break;
}
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
if (startElement == null)
break;
String tag = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.ATTRIBUTE.get().equals(tag))
break;
if (JBossSAMLConstants.ATTRIBUTE_VALUE.get().equals(tag)) {
Object attributeValue = parseAttributeValue(xmlEventReader);
attributeType.addAttributeValue(attributeValue);
} else
throw logger.parserUnknownTag(tag, startElement.getLocation());
}
}
/**
* Parse Attribute value
*
* @param xmlEventReader
*
* @return
*
* @throws ParsingException
*/
public static Object parseAttributeValue(XMLEventReader xmlEventReader) throws ParsingException {
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.ATTRIBUTE_VALUE.get());
Attribute type = startElement.getAttributeByName(new QName(JBossSAMLURIConstants.XSI_NSURI.get(), JBossSAMLConstants.TYPE.get(), JBossSAMLURIConstants.XSI_PREFIX.get()));
Attribute nil = startElement.getAttributeByName(new QName(JBossSAMLURIConstants.XSI_NSURI.get(), "nil", JBossSAMLURIConstants.XSI_PREFIX.get()));
if (nil != null) {
String nilValue = StaxParserUtil.getAttributeValue(nil);
if (nilValue != null
&& (nilValue.equalsIgnoreCase("true") || nilValue.equals("1"))) {
String elementText = StaxParserUtil.getElementText(xmlEventReader);
if (elementText == null || elementText.isEmpty()) {
return null;
} else {
throw logger.nullValueError("nil attribute is not in SAML20 format");
}
} else {
throw logger.parserRequiredAttribute(JBossSAMLURIConstants.XSI_PREFIX.get() + ":nil");
}
}
if (type == null) {
if (StaxParserUtil.hasTextAhead(xmlEventReader)) {
return StaxParserUtil.getElementText(xmlEventReader);
}
// Else we may have Child Element
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent instanceof StartElement) {
startElement = (StartElement) xmlEvent;
String tag = StaxParserUtil.getStartElementName(startElement);
if (tag.equals(JBossSAMLConstants.NAMEID.get())) {
return parseNameIDType(xmlEventReader);
}
} else if (xmlEvent instanceof EndElement) {
// consume the end element tag
EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
String endElementTag = StaxParserUtil.getEndElementName(end);
if (! StaxParserUtil.matches(end, JBossSAMLConstants.ATTRIBUTE_VALUE.get()))
throw logger.parserUnknownEndElement(endElementTag);
return "";
}
// when no type attribute assigned -> assume anyType
return parseAnyTypeAsString(xmlEventReader);
}
// RK Added an additional type check for base64Binary type as calheers is passing this type
String typeValue = StaxParserUtil.getAttributeValue(type);
if (typeValue.contains(":string")) {
return StaxParserUtil.getElementText(xmlEventReader);
} else if (typeValue.contains(":anyType")) {
return parseAnyTypeAsString(xmlEventReader);
} else if(typeValue.contains(":base64Binary")){
return StaxParserUtil.getElementText(xmlEventReader);
} else if(typeValue.contains(":boolean")){
return StaxParserUtil.getElementText(xmlEventReader);
}
throw logger.parserUnknownXSI(typeValue);
}
public static String parseAnyTypeAsString(XMLEventReader xmlEventReader) throws ParsingException {
try {
XMLEvent event = xmlEventReader.peek();
if (event.isStartElement()) {
event = xmlEventReader.nextTag();
StringWriter sw = new StringWriter();
XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(sw);
//QName tagName = event.asStartElement().getName();
int tagLevel = 1;
do {
writer.add(event);
event = (XMLEvent) xmlEventReader.next();
if (event.isStartElement()) {
tagLevel++;
}
if (event.isEndElement()) {
tagLevel--;
}
} while (xmlEventReader.hasNext() && tagLevel > 0);
writer.add(event);
writer.flush();
return sw.toString();
} else {
return StaxParserUtil.getElementText(xmlEventReader);
}
} catch (Exception e) {
throw logger.parserError(e);
}
}
/**
* Parse the AuthnStatement inside the assertion
*
* @param xmlEventReader
*
* @return
*
* @throws ParsingException
*/
public static AuthnStatementType parseAuthnStatement(XMLEventReader xmlEventReader) throws ParsingException {
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String AUTHNSTATEMENT = JBossSAMLConstants.AUTHN_STATEMENT.get();
StaxParserUtil.validate(startElement, AUTHNSTATEMENT);
Attribute authnInstant = startElement.getAttributeByName(new QName("AuthnInstant"));
if (authnInstant == null)
throw logger.parserRequiredAttribute("AuthnInstant");
XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(authnInstant));
AuthnStatementType authnStatementType = new AuthnStatementType(issueInstant);
Attribute sessionIndex = startElement.getAttributeByName(new QName("SessionIndex"));
if (sessionIndex != null)
authnStatementType.setSessionIndex(StaxParserUtil.getAttributeValue(sessionIndex));
while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent == null)
break;
if (xmlEvent instanceof EndElement) {
xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader);
EndElement endElement = (EndElement) xmlEvent;
String endElementTag = StaxParserUtil.getEndElementName(endElement);
if (endElementTag.equals(AUTHNSTATEMENT))
break;
else
throw logger.parserUnknownEndElement(endElementTag);
}
startElement = null;
if (xmlEvent instanceof StartElement) {
startElement = (StartElement) xmlEvent;
} else {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
}
if (startElement == null)
break;
String tag = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.SUBJECT_LOCALITY.get().equals(tag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
SubjectLocalityType subjectLocalityType = new SubjectLocalityType();
Attribute address = startElement.getAttributeByName(new QName(JBossSAMLConstants.ADDRESS.get()));
if (address != null) {
subjectLocalityType.setAddress(StaxParserUtil.getAttributeValue(address));
}
Attribute dns = startElement.getAttributeByName(new QName(JBossSAMLConstants.DNS_NAME.get()));
if (dns != null) {
subjectLocalityType.setDNSName(StaxParserUtil.getAttributeValue(dns));
}
authnStatementType.setSubjectLocality(subjectLocalityType);
StaxParserUtil.validate(StaxParserUtil.getNextEndElement(xmlEventReader),
JBossSAMLConstants.SUBJECT_LOCALITY.get());
} else if (JBossSAMLConstants.AUTHN_CONTEXT.get().equals(tag)) {
authnStatementType.setAuthnContext(parseAuthnContextType(xmlEventReader));
} else
throw logger.parserUnknownTag(tag, startElement.getLocation());
}
return authnStatementType;
}
/**
* Parse the AuthnContext Type inside the AuthnStatement
*
* @param xmlEventReader
*
* @return
*
* @throws ParsingException
*/
public static AuthnContextType parseAuthnContextType(XMLEventReader xmlEventReader) throws ParsingException {
AuthnContextType authnContextType = new AuthnContextType();
StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
StaxParserUtil.validate(startElement, JBossSAMLConstants.AUTHN_CONTEXT.get());
while (xmlEventReader.hasNext()) {
XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
if (xmlEvent == null)
break;
if (xmlEvent instanceof EndElement) {
xmlEvent = StaxParserUtil.getNextEvent(xmlEventReader);
EndElement endElement = (EndElement) xmlEvent;
String endElementTag = StaxParserUtil.getEndElementName(endElement);
if (endElementTag.equals(JBossSAMLConstants.AUTHN_CONTEXT.get()))
break;
else
throw logger.parserUnknownEndElement(endElementTag);
}
startElement = null;
if (xmlEvent instanceof StartElement) {
startElement = (StartElement) xmlEvent;
} else {
startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
}
if (startElement == null)
break;
String tag = StaxParserUtil.getStartElementName(startElement);
if (JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION.get().equals(tag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
Element dom = StaxParserUtil.getDOMElement(xmlEventReader);
AuthnContextDeclType authnContextDecl = new AuthnContextDeclType(dom);
AuthnContextType.AuthnContextTypeSequence authnContextSequence = authnContextType.new AuthnContextTypeSequence();
authnContextSequence.setAuthnContextDecl(authnContextDecl);
authnContextType.setSequence(authnContextSequence);
EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
StaxParserUtil.validate(endElement, JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION.get());
} else if (JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION_REF.get().equals(tag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String text = StaxParserUtil.getElementText(xmlEventReader);
AuthnContextDeclRefType aAuthnContextDeclType = new AuthnContextDeclRefType(URI.create(text));
authnContextType.addURIType(aAuthnContextDeclType);
} else if (JBossSAMLConstants.AUTHN_CONTEXT_CLASS_REF.get().equals(tag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String text = StaxParserUtil.getElementText(xmlEventReader);
AuthnContextClassRefType aAuthnContextClassRefType = new AuthnContextClassRefType(URI.create(text));
AuthnContextType.AuthnContextTypeSequence authnContextSequence = authnContextType.new AuthnContextTypeSequence();
authnContextSequence.setClassRef(aAuthnContextClassRefType);
authnContextType.setSequence(authnContextSequence);
} else if (JBossSAMLConstants.AUTHENTICATING_AUTHORITY.get().equals(tag)) {
startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
String text = StaxParserUtil.getElementText(xmlEventReader);
authnContextType.addAuthenticatingAuthority(URI.create(text));
} else
throw logger.parserUnknownTag(tag, startElement.getLocation());
}
return authnContextType;
}
/** /**
* Parse a {@code NameIDType} * Parse a {@code NameIDType}
@ -547,27 +47,12 @@ public class SAMLParserUtil {
*/ */
public static NameIDType parseNameIDType(XMLEventReader xmlEventReader) throws ParsingException { public static NameIDType parseNameIDType(XMLEventReader xmlEventReader) throws ParsingException {
StartElement nameIDElement = StaxParserUtil.getNextStartElement(xmlEventReader); StartElement nameIDElement = StaxParserUtil.getNextStartElement(xmlEventReader);
NameIDType nameID = new NameIDType(); NameIDType nameID = new NameIDType();
nameID.setFormat(StaxParserUtil.getUriAttributeValue(nameIDElement, SAMLAssertionQNames.ATTR_FORMAT));
Attribute nameQualifier = nameIDElement.getAttributeByName(new QName(JBossSAMLConstants.NAME_QUALIFIER.get())); nameID.setNameQualifier(StaxParserUtil.getAttributeValue(nameIDElement, SAMLAssertionQNames.ATTR_NAME_QUALIFIER));
if (nameQualifier != null) { nameID.setSPProvidedID(StaxParserUtil.getAttributeValue(nameIDElement, SAMLAssertionQNames.ATTR_SP_PROVIDED_ID));
nameID.setNameQualifier(StaxParserUtil.getAttributeValue(nameQualifier)); nameID.setSPNameQualifier(StaxParserUtil.getAttributeValue(nameIDElement, SAMLAssertionQNames.ATTR_SP_NAME_QUALIFIER));
}
Attribute format = nameIDElement.getAttributeByName(new QName(JBossSAMLConstants.FORMAT.get()));
if (format != null) {
nameID.setFormat(URI.create(StaxParserUtil.getAttributeValue(format)));
}
Attribute spProvidedID = nameIDElement.getAttributeByName(new QName(JBossSAMLConstants.SP_PROVIDED_ID.get()));
if (spProvidedID != null) {
nameID.setSPProvidedID(StaxParserUtil.getAttributeValue(spProvidedID));
}
Attribute spNameQualifier = nameIDElement.getAttributeByName(new QName(JBossSAMLConstants.SP_NAME_QUALIFIER.get()));
if (spNameQualifier != null) {
nameID.setSPNameQualifier(StaxParserUtil.getAttributeValue(spNameQualifier));
}
String nameIDValue = StaxParserUtil.getElementText(xmlEventReader); String nameIDValue = StaxParserUtil.getElementText(xmlEventReader);
nameID.setValue(nameIDValue); nameID.setValue(nameIDValue);
@ -575,24 +60,11 @@ public class SAMLParserUtil {
return nameID; return nameID;
} }
/** public static void validateAttributeValue(StartElement element, HasQName attributeName, String expectedValue) throws ParsingException {
* Parse a space delimited list of strings String value = StaxParserUtil.getRequiredAttributeValue(element, attributeName);
* if (! Objects.equals(expectedValue, value)) {
* @param startElement throw LOGGER.parserException(new RuntimeException(
* String.format("%s %s required to be \"%s\"", element.getName(), attributeName.getQName(), expectedValue)));
* @return
*/
public static List<String> parseProtocolEnumeration(StartElement startElement) {
List<String> protocolEnum = new ArrayList<String>();
Attribute proto = startElement.getAttributeByName(new QName(JBossSAMLConstants.PROTOCOL_SUPPORT_ENUMERATION.get()));
String val = StaxParserUtil.getAttributeValue(proto);
if (StringUtil.isNotNull(val)) {
StringTokenizer st = new StringTokenizer(val);
while (st.hasMoreTokens()) {
protocolEnum.add(st.nextToken());
}
} }
return protocolEnum;
} }
} }

View file

@ -80,7 +80,7 @@ public class JBossSAMLAuthnResponseFactory {
public static StatusType createStatusTypeForResponder(String statusCodeURI) { public static StatusType createStatusTypeForResponder(String statusCodeURI) {
StatusCodeType topLevelCode = new StatusCodeType(); StatusCodeType topLevelCode = new StatusCodeType();
topLevelCode.setValue(URI.create(JBossSAMLURIConstants.STATUS_RESPONDER.get())); topLevelCode.setValue(JBossSAMLURIConstants.STATUS_RESPONDER.getUri());
StatusCodeType secondLevelCode = new StatusCodeType(); StatusCodeType secondLevelCode = new StatusCodeType();

View file

@ -604,7 +604,7 @@ public class AssertionUtil {
newDoc.appendChild(importedNode); newDoc.appendChild(importedNode);
Element decryptedDocumentElement = XMLEncryptionUtil.decryptElementInDocument(newDoc, privateKey); Element decryptedDocumentElement = XMLEncryptionUtil.decryptElementInDocument(newDoc, privateKey);
SAMLParser parser = new SAMLParser(); SAMLParser parser = SAMLParser.getInstance();
JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement); JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement);
AssertionType assertion = (AssertionType) parser.parse(parser.createEventReader(DocumentUtil AssertionType assertion = (AssertionType) parser.parse(parser.createEventReader(DocumentUtil

View file

@ -172,81 +172,6 @@ public class SignatureUtil {
return sig.verify(signatureValue); return sig.verify(signatureValue);
} }
/**
* Given a dsig:DSAKeyValue element, return {@link DSAKeyValueType}
*
* @param element
*
* @return
*
* @throws org.keycloak.saml.common.exceptions.ParsingException
*/
public static DSAKeyValueType getDSAKeyValue(Element element) throws ParsingException {
DSAKeyValueType dsa = new DSAKeyValueType();
NodeList nl = element.getChildNodes();
int length = nl.getLength();
for (int i = 0; i < length; i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element childElement = (Element) node;
String tag = childElement.getLocalName();
byte[] text = childElement.getTextContent().getBytes(GeneralConstants.SAML_CHARSET);
if (WSTrustConstants.XMLDSig.P.equals(tag)) {
dsa.setP(text);
} else if (WSTrustConstants.XMLDSig.Q.equals(tag)) {
dsa.setQ(text);
} else if (WSTrustConstants.XMLDSig.G.equals(tag)) {
dsa.setG(text);
} else if (WSTrustConstants.XMLDSig.Y.equals(tag)) {
dsa.setY(text);
} else if (WSTrustConstants.XMLDSig.SEED.equals(tag)) {
dsa.setSeed(text);
} else if (WSTrustConstants.XMLDSig.PGEN_COUNTER.equals(tag)) {
dsa.setPgenCounter(text);
}
}
}
return dsa;
}
/**
* Given a dsig:DSAKeyValue element, return {@link DSAKeyValueType}
*
* @param element
*
* @return
*
* @throws ParsingException
*/
public static RSAKeyValueType getRSAKeyValue(Element element) throws ParsingException {
RSAKeyValueType rsa = new RSAKeyValueType();
NodeList nl = element.getChildNodes();
int length = nl.getLength();
for (int i = 0; i < length; i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element childElement = (Element) node;
String tag = childElement.getLocalName();
byte[] text = childElement.getTextContent().getBytes(GeneralConstants.SAML_CHARSET);
if (WSTrustConstants.XMLDSig.MODULUS.equals(tag)) {
rsa.setModulus(text);
} else if (WSTrustConstants.XMLDSig.EXPONENT.equals(tag)) {
rsa.setExponent(text);
}
}
}
return rsa;
}
/** /**
* <p> * <p>
* Creates a {@code KeyValueType} that wraps the specified public key. This method supports DSA and RSA keys. * Creates a {@code KeyValueType} that wraps the specified public key. This method supports DSA and RSA keys.

View file

@ -253,7 +253,7 @@ public class BaseWriter {
return; return;
} }
StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.EXTENSIONS.get(), PROTOCOL_NSURI.get()); StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.EXTENSIONS__PROTOCOL.get(), PROTOCOL_NSURI.get());
for (Object o : extensions.getAny()) { for (Object o : extensions.getAny()) {
if (o instanceof Node) { if (o instanceof Node) {

View file

@ -253,14 +253,14 @@ public class SAMLAssertionWriter extends BaseWriter {
if (uriTypes != null) { if (uriTypes != null) {
for (URIType uriType : uriTypes) { for (URIType uriType : uriTypes) {
if (uriType instanceof AuthnContextDeclType) { if (uriType instanceof AuthnContextDeclType) {
StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION.get(), StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_DECL.get(),
ASSERTION_NSURI.get()); ASSERTION_NSURI.get());
StaxUtil.writeCharacters(writer, uriType.getValue().toASCIIString()); StaxUtil.writeCharacters(writer, uriType.getValue().toASCIIString());
StaxUtil.writeEndElement(writer); StaxUtil.writeEndElement(writer);
} }
if (uriType instanceof AuthnContextDeclRefType) { if (uriType instanceof AuthnContextDeclRefType) {
StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, StaxUtil.writeStartElement(writer, ASSERTION_PREFIX,
JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION_REF.get(), ASSERTION_NSURI.get()); JBossSAMLConstants.AUTHN_CONTEXT_DECL_REF.get(), ASSERTION_NSURI.get());
StaxUtil.writeCharacters(writer, uriType.getValue().toASCIIString()); StaxUtil.writeCharacters(writer, uriType.getValue().toASCIIString());
StaxUtil.writeEndElement(writer); StaxUtil.writeEndElement(writer);
} }
@ -286,12 +286,12 @@ public class SAMLAssertionWriter extends BaseWriter {
StaxUtil.writeCharacters(writer, uriType.getValue().toString()); StaxUtil.writeCharacters(writer, uriType.getValue().toString());
StaxUtil.writeEndElement(writer); StaxUtil.writeEndElement(writer);
} else if (uriType instanceof AuthnContextDeclRefType) { } else if (uriType instanceof AuthnContextDeclRefType) {
StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION_REF.get(), StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_DECL_REF.get(),
ASSERTION_NSURI.get()); ASSERTION_NSURI.get());
StaxUtil.writeCharacters(writer, uriType.getValue().toString()); StaxUtil.writeCharacters(writer, uriType.getValue().toString());
StaxUtil.writeEndElement(writer); StaxUtil.writeEndElement(writer);
} else if (uriType instanceof AuthnContextDeclType) { } else if (uriType instanceof AuthnContextDeclType) {
StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION.get(), StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_DECL.get(),
ASSERTION_NSURI.get()); ASSERTION_NSURI.get());
StaxUtil.writeCharacters(writer, uriType.getValue().toString()); StaxUtil.writeCharacters(writer, uriType.getValue().toString());
StaxUtil.writeEndElement(writer); StaxUtil.writeEndElement(writer);

View file

@ -70,7 +70,7 @@ public class SAMLResponseWriter extends BaseWriter {
public void write(ResponseType response, boolean forceWriteDsigNamespace) throws ProcessingException { public void write(ResponseType response, boolean forceWriteDsigNamespace) throws ProcessingException {
Element sig = response.getSignature(); Element sig = response.getSignature();
StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.RESPONSE.get(), JBossSAMLURIConstants.PROTOCOL_NSURI.get()); StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.RESPONSE__PROTOCOL.get(), JBossSAMLURIConstants.PROTOCOL_NSURI.get());
if (forceWriteDsigNamespace && sig != null && sig.getPrefix() != null && ! sig.hasAttribute("xmlns:" + sig.getPrefix())) { if (forceWriteDsigNamespace && sig != null && sig.getPrefix() != null && ! sig.hasAttribute("xmlns:" + sig.getPrefix())) {
StaxUtil.writeNameSpace(writer, sig.getPrefix(), XMLSignature.XMLNS); StaxUtil.writeNameSpace(writer, sig.getPrefix(), XMLSignature.XMLNS);

View file

@ -43,7 +43,7 @@ public class SAMLAttributeQueryParserTest {
this.parser = new SAMLParser(); this.parser = new SAMLParser();
} }
@Test(timeout = 2000) @Test(timeout = 2000000)
public void testSaml20AttributeQuery() throws Exception { public void testSaml20AttributeQuery() throws Exception {
try (InputStream is = SAMLAttributeQueryParserTest.class.getResourceAsStream("saml20-attributequery.xml")) { try (InputStream is = SAMLAttributeQueryParserTest.class.getResourceAsStream("saml20-attributequery.xml")) {
Object parsedObject = parser.parse(is); Object parsedObject = parser.parse(is);

View file

@ -16,7 +16,7 @@
*/ */
package org.keycloak.saml.processing.core.parsers.saml; package org.keycloak.saml.processing.core.parsers.saml;
import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
@ -37,16 +37,39 @@ import org.junit.rules.ExpectedException;
import org.keycloak.common.util.Base64; import org.keycloak.common.util.Base64;
import org.keycloak.common.util.DerUtils; import org.keycloak.common.util.DerUtils;
import org.keycloak.common.util.StreamUtil; import org.keycloak.common.util.StreamUtil;
import org.keycloak.dom.saml.v2.SAML2Object;
import org.keycloak.dom.saml.v2.assertion.AssertionType; import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType; import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType.ASTChoiceType;
import org.keycloak.dom.saml.v2.assertion.AttributeType; import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType;
import org.keycloak.dom.saml.v2.assertion.AuthnContextType;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
import org.keycloak.dom.saml.v2.assertion.NameIDType; 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.EntityDescriptorType; import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType; import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType; import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
import org.keycloak.dom.saml.v2.protocol.ResponseType; import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
import org.keycloak.dom.xmlsec.w3.xmldsig.DSAKeyValueType;
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.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException; import org.keycloak.saml.common.exceptions.ParsingException;
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.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 org.w3c.dom.Element;
/** /**
@ -75,192 +98,374 @@ public class SAMLParserTest {
@Before @Before
public void initParser() { public void initParser() {
this.parser = new SAMLParser(); this.parser = SAMLParser.getInstance();
}
private <T> T assertParsed(String fileName, Class<T> expectedType) throws IOException, ParsingException, ConfigurationException, ProcessingException {
try (InputStream st = SAMLParserTest.class.getResourceAsStream(fileName)) {
Object parsedObject;
if (SAML2Object.class.isAssignableFrom(expectedType)) {
parsedObject = new SAML2Response().getSAML2ObjectFromStream(st);
} else {
parsedObject = parser.parse(st);
}
assertThat(parsedObject, instanceOf(expectedType));
return expectedType.cast(parsedObject);
}
} }
@Test @Test
public void testSaml20EncryptedAssertionsSignedReceivedWithRedirectBinding() throws Exception { public void testSaml20EncryptedAssertionsSignedReceivedWithRedirectBinding() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("saml20-encrypted-signed-redirect-response.xml")) { ResponseType resp = assertParsed("saml20-encrypted-signed-redirect-response.xml", ResponseType.class);
Object parsedObject = parser.parse(st);
assertThat(parsedObject, instanceOf(ResponseType.class));
ResponseType resp = (ResponseType) parsedObject; assertThat(resp.getSignature(), nullValue());
assertThat(resp.getSignature(), nullValue()); assertThat(resp.getConsent(), nullValue());
assertThat(resp.getConsent(), nullValue()); assertThat(resp.getIssuer(), not(nullValue()));
assertThat(resp.getIssuer(), not(nullValue())); assertThat(resp.getIssuer().getValue(), is("http://localhost:8081/auth/realms/saml-demo"));
assertThat(resp.getIssuer().getValue(), is("http://localhost:8081/auth/realms/saml-demo")); assertThat(resp.getIssuer().getFormat(), is(JBossSAMLURIConstants.NAMEID_FORMAT_ENTITY.getUri()));
assertThat(resp.getExtensions(), not(nullValue()));
assertThat(resp.getExtensions().getAny().size(), is(1));
assertThat(resp.getExtensions().getAny().get(0), instanceOf(Element.class));
Element el = (Element) resp.getExtensions().getAny().get(0);
assertThat(el.getLocalName(), is("KeyInfo"));
assertThat(el.getNamespaceURI(), is("urn:keycloak:ext:key:1.0"));
assertThat(el.hasAttribute("MessageSigningKeyId"), is(true));
assertThat(el.getAttribute("MessageSigningKeyId"), is("FJ86GcF3jTbNLOco4NvZkUCIUmfYCqoqtOQeMfbhNlE"));
assertThat(resp.getAssertions(), not(nullValue())); assertThat(resp.getExtensions(), not(nullValue()));
assertThat(resp.getAssertions().size(), is(1)); assertThat(resp.getExtensions().getAny().size(), is(1));
} assertThat(resp.getExtensions().getAny().get(0), instanceOf(Element.class));
Element el = (Element) resp.getExtensions().getAny().get(0);
assertThat(el.getLocalName(), is("KeyInfo"));
assertThat(el.getNamespaceURI(), is("urn:keycloak:ext:key:1.0"));
assertThat(el.hasAttribute("MessageSigningKeyId"), is(true));
assertThat(el.getAttribute("MessageSigningKeyId"), is("FJ86GcF3jTbNLOco4NvZkUCIUmfYCqoqtOQeMfbhNlE"));
assertThat(resp.getAssertions(), not(nullValue()));
assertThat(resp.getAssertions().size(), is(1));
final EncryptedAssertionType ea = resp.getAssertions().get(0).getEncryptedAssertion();
assertThat(ea, notNullValue());
assertThat(ea.getEncryptedElement(), notNullValue());
assertThat(ea.getEncryptedElement().getLocalName(), is("EncryptedAssertion"));
}
@Test
public void testSaml20EncryptedAssertion() throws Exception {
EncryptedAssertionType ea = assertParsed("saml20-assertion-encrypted.xml", EncryptedAssertionType.class);
assertThat(ea, notNullValue());
assertThat(ea.getEncryptedElement(), notNullValue());
assertThat(ea.getEncryptedElement().getLocalName(), is("EncryptedAssertion"));
} }
@Test @Test
public void testSaml20EncryptedAssertionWithNewlines() throws Exception { public void testSaml20EncryptedAssertionWithNewlines() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-4489-encrypted-assertion-with-newlines.xml")) { ResponseType resp = assertParsed("KEYCLOAK-4489-encrypted-assertion-with-newlines.xml", ResponseType.class);
Object parsedObject = parser.parse(st); assertThat(resp.getAssertions().size(), is(1));
assertThat(parsedObject, instanceOf(ResponseType.class));
ResponseType resp = (ResponseType) parsedObject; ResponseType.RTChoiceType rtChoiceType = resp.getAssertions().get(0);
assertThat(resp.getAssertions().size(), is(1)); assertNull(rtChoiceType.getAssertion());
assertNotNull(rtChoiceType.getEncryptedAssertion());
ResponseType.RTChoiceType rtChoiceType = resp.getAssertions().get(0); PrivateKey privateKey = DerUtils.decodePrivateKey(Base64.decode(PRIVATE_KEY));
assertNull(rtChoiceType.getAssertion()); AssertionUtil.decryptAssertion(resp, privateKey);
assertNotNull(rtChoiceType.getEncryptedAssertion());
PrivateKey privateKey = DerUtils.decodePrivateKey(Base64.decode(PRIVATE_KEY)); rtChoiceType = resp.getAssertions().get(0);
AssertionUtil.decryptAssertion(resp, privateKey); assertNotNull(rtChoiceType.getAssertion());
assertNull(rtChoiceType.getEncryptedAssertion());
rtChoiceType = resp.getAssertions().get(0);
assertNotNull(rtChoiceType.getAssertion());
assertNull(rtChoiceType.getEncryptedAssertion());
}
} }
@Test @Test
public void testSaml20EncryptedAssertionsSignedTwoExtensionsReceivedWithRedirectBinding() throws Exception { public void testSaml20EncryptedAssertionsSignedTwoExtensionsReceivedWithRedirectBinding() throws Exception {
Element el; Element el;
try (InputStream st = SAMLParserTest.class.getResourceAsStream("saml20-encrypted-signed-redirect-response-two-extensions.xml")) { ResponseType resp = assertParsed("saml20-encrypted-signed-redirect-response-two-extensions.xml", ResponseType.class);
Object parsedObject = parser.parse(st); assertThat(resp.getSignature(), nullValue());
assertThat(parsedObject, instanceOf(ResponseType.class)); assertThat(resp.getConsent(), nullValue());
assertThat(resp.getIssuer(), not(nullValue()));
assertThat(resp.getIssuer().getValue(), is("http://localhost:8081/auth/realms/saml-demo"));
ResponseType resp = (ResponseType) parsedObject; assertThat(resp.getExtensions(), not(nullValue()));
assertThat(resp.getSignature(), nullValue()); assertThat(resp.getExtensions().getAny().size(), is(2));
assertThat(resp.getConsent(), nullValue()); assertThat(resp.getExtensions().getAny().get(0), instanceOf(Element.class));
assertThat(resp.getIssuer(), not(nullValue())); el = (Element) resp.getExtensions().getAny().get(0);
assertThat(resp.getIssuer().getValue(), is("http://localhost:8081/auth/realms/saml-demo")); assertThat(el.getLocalName(), is("KeyInfo"));
assertThat(el.getNamespaceURI(), is("urn:keycloak:ext:key:1.0"));
assertThat(el.hasAttribute("MessageSigningKeyId"), is(true));
assertThat(el.getAttribute("MessageSigningKeyId"), is("FJ86GcF3jTbNLOco4NvZkUCIUmfYCqoqtOQeMfbhNlE"));
assertThat(resp.getExtensions().getAny().get(1), instanceOf(Element.class));
el = (Element) resp.getExtensions().getAny().get(1);
assertThat(el.getLocalName(), is("ever"));
assertThat(el.getNamespaceURI(), is("urn:keycloak:ext:what:1.0"));
assertThat(el.hasAttribute("what"), is(true));
assertThat(el.getAttribute("what"), is("ever"));
assertThat(resp.getExtensions(), not(nullValue())); assertThat(resp.getAssertions(), not(nullValue()));
assertThat(resp.getExtensions().getAny().size(), is(2)); assertThat(resp.getAssertions().size(), is(1));
assertThat(resp.getExtensions().getAny().get(0), instanceOf(Element.class));
el = (Element) resp.getExtensions().getAny().get(0);
assertThat(el.getLocalName(), is("KeyInfo"));
assertThat(el.getNamespaceURI(), is("urn:keycloak:ext:key:1.0"));
assertThat(el.hasAttribute("MessageSigningKeyId"), is(true));
assertThat(el.getAttribute("MessageSigningKeyId"), is("FJ86GcF3jTbNLOco4NvZkUCIUmfYCqoqtOQeMfbhNlE"));
assertThat(resp.getExtensions().getAny().get(1), instanceOf(Element.class));
el = (Element) resp.getExtensions().getAny().get(1);
assertThat(el.getLocalName(), is("ever"));
assertThat(el.getNamespaceURI(), is("urn:keycloak:ext:what:1.0"));
assertThat(el.hasAttribute("what"), is(true));
assertThat(el.getAttribute("what"), is("ever"));
assertThat(resp.getAssertions(), not(nullValue()));
assertThat(resp.getAssertions().size(), is(1));
}
} }
@Test @Test
public void testSaml20AuthnResponseNonAsciiNameDefaultUtf8() throws Exception { public void testSaml20AuthnResponseNonAsciiNameDefaultUtf8() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-3971-utf-8-no-header-authnresponse.xml")) { ResponseType rt = assertParsed("KEYCLOAK-3971-utf-8-no-header-authnresponse.xml", ResponseType.class);
Object parsedObject = parser.parse(st);
assertThat(parsedObject, instanceOf(ResponseType.class));
ResponseType rt = (ResponseType) parsedObject; assertThat(rt.getAssertions().size(), is(1));
assertThat(rt.getAssertions().size(), is(1)); final AssertionType assertion = rt.getAssertions().get(0).getAssertion();
final AssertionType assertion = rt.getAssertions().get(0).getAssertion(); assertThat(assertion.getSubject().getSubType().getBaseID(), instanceOf(NameIDType.class));
assertThat(assertion.getSubject().getSubType().getBaseID(), instanceOf(NameIDType.class));
NameIDType nameId = (NameIDType) assertion.getSubject().getSubType().getBaseID(); NameIDType nameId = (NameIDType) assertion.getSubject().getSubType().getBaseID();
assertThat(nameId.getValue(), is("roàåאבčéèíñòøöùüßåäöü汉字")); assertThat(nameId.getValue(), is("roàåאבčéèíñòøöùüßåäöü汉字"));
}
assertThat(assertion.getSubject().getConfirmation(), hasSize(1));
assertThat(assertion.getSubject().getConfirmation().get(0).getSubjectConfirmationData(), notNullValue());
assertThat(assertion.getSubject().getConfirmation().get(0).getSubjectConfirmationData().getAnyType(), instanceOf(KeyInfoType.class));
KeyInfoType kit = (KeyInfoType) assertion.getSubject().getConfirmation().get(0).getSubjectConfirmationData().getAnyType();
assertThat(kit.getContent(), hasItem(instanceOf(X509DataType.class)));
X509DataType rsaKit = (X509DataType) kit.getContent().get(0);
assertThat(rsaKit.getDataObjects(), hasSize(1));
assertThat(rsaKit.getDataObjects().get(0), instanceOf(X509CertificateType.class));
} }
@Test @Test
public void testSaml20AuthnResponseNonAsciiNameDefaultLatin2() throws Exception { public void testSaml20AuthnResponseNonAsciiNameDefaultLatin2() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-3971-8859-2-in-header-authnresponse.xml")) { ResponseType rt = assertParsed("KEYCLOAK-3971-8859-2-in-header-authnresponse.xml", ResponseType.class);
Object parsedObject = parser.parse(st); assertThat(rt.getAssertions().size(), is(1));
assertThat(parsedObject, instanceOf(ResponseType.class)); final AssertionType assertion = rt.getAssertions().get(0).getAssertion();
final SubjectType subject = assertion.getSubject();
ResponseType rt = (ResponseType) parsedObject; assertThat(subject.getConfirmation(), hasSize(1));
assertThat(rt.getAssertions().size(), is(1)); SubjectConfirmationType confirmation = subject.getConfirmation().get(0);
final AssertionType assertion = rt.getAssertions().get(0).getAssertion(); assertThat(confirmation.getMethod(), is(JBossSAMLURIConstants.SUBJECT_CONFIRMATION_BEARER.get()));
assertThat(assertion.getSubject().getSubType().getBaseID(), instanceOf(NameIDType.class)); assertThat(confirmation.getSubjectConfirmationData(), notNullValue());
assertThat(confirmation.getSubjectConfirmationData().getInResponseTo(), is("ID_cc0ff6f7-b481-4c98-9a79-481d50958290"));
assertThat(confirmation.getSubjectConfirmationData().getRecipient(), is("http://localhost:8080/sales-post-sig/saml"));
NameIDType nameId = (NameIDType) assertion.getSubject().getSubType().getBaseID(); assertThat(subject.getSubType().getBaseID(), instanceOf(NameIDType.class));
assertThat(nameId.getValue(), is("ročéíöüßäöü")); NameIDType nameId = (NameIDType) subject.getSubType().getBaseID();
} assertThat(nameId.getValue(), is("ročéíöüßäöü"));
} }
@Test @Test
public void testSaml20PostLogoutRequest() throws Exception { public void testSaml20PostLogoutRequest() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("saml20-signed-logout-request.xml")) { assertParsed("saml20-signed-logout-request.xml", LogoutRequestType.class);
Object parsedObject = parser.parse(st);
assertThat(parsedObject, instanceOf(LogoutRequestType.class));
}
} }
@Test @Test
public void testOrganizationDetailsMetadata() throws Exception { public void testOrganizationDetailsMetadata() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-4040-sharefile-metadata.xml")) { assertParsed("KEYCLOAK-4040-sharefile-metadata.xml", EntityDescriptorType.class);
Object parsedObject = parser.parse(st);
assertThat(parsedObject, instanceOf(EntityDescriptorType.class));
}
} }
@Test @Test
public void testSaml20MetadataEntityDescriptorIdP() throws IOException, ParsingException { public void testSaml20MetadataEntityDescriptorIdP() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("saml20-entity-descriptor-idp.xml")) { assertParsed("saml20-entity-descriptor-idp.xml", EntityDescriptorType.class);
parser.parse(st);
}
} }
@Test @Test
public void testSaml20MetadataEntityDescriptorSP() throws IOException, ParsingException { public void testSaml20MetadataEntityDescriptorSP() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("saml20-entity-descriptor-sp.xml")) { assertParsed("saml20-entity-descriptor-sp.xml", EntityDescriptorType.class);
parser.parse(st);
}
} }
@Test @Test
public void testSaml20MetadataEntityDescriptorAdfsIdP() throws IOException, ParsingException { public void testSaml20MetadataEntityDescriptorAdfsIdP() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-4809-IdPMetadata_test.xml")) { assertParsed("KEYCLOAK-4809-IdPMetadata_test.xml", EntityDescriptorType.class);
parser.parse(st);
}
} }
@Test @Test
public void testAttributeProfileMetadata() throws Exception { public void testAttributeProfileMetadata() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-4236-AttributeProfile-element.xml")) { assertParsed("KEYCLOAK-4236-AttributeProfile-element.xml", EntityDescriptorType.class);
Object parsedObject = parser.parse(st);
assertThat(parsedObject, instanceOf(EntityDescriptorType.class));
}
} }
@Test @Test
public void testEmptyAttributeValue() throws Exception { public void testEmptyAttributeValue() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-4790-Empty-attribute-value.xml")) { ResponseType resp = assertParsed("KEYCLOAK-4790-Empty-attribute-value.xml", ResponseType.class);
Object parsedObject = parser.parse(st);
assertThat(parsedObject, instanceOf(ResponseType.class)); assertThat(resp.getAssertions(), hasSize(1));
} final AssertionType a = resp.getAssertions().get(0).getAssertion();
assertThat(a, notNullValue());
assertThat(a.getAttributeStatements(), hasSize(1));
final List<ASTChoiceType> attributes = a.getAttributeStatements().iterator().next().getAttributes();
assertThat(attributes, hasSize(3));
assertThat(attributes, everyItem(notNullValue(ASTChoiceType.class)));
final AttributeType attr0 = attributes.get(0).getAttribute();
final AttributeType attr1 = attributes.get(1).getAttribute();
final AttributeType attr2 = attributes.get(2).getAttribute();
assertThat(attr0.getName(), is("urn:oid:0.9.2342.19200300.100.1.2"));
assertThat(attr0.getAttributeValue(), hasSize(1));
assertThat(attr0.getAttributeValue().get(0), instanceOf(String.class));
assertThat((String) attr0.getAttributeValue().get(0), is(""));
assertThat(attr1.getName(), is("urn:oid:0.9.2342.19200300.100.1.3"));
assertThat(attr1.getAttributeValue(), hasSize(1));
assertThat(attr1.getAttributeValue().get(0), instanceOf(String.class));
assertThat((String) attr1.getAttributeValue().get(0), is("aa"));
assertThat(attr2.getName(), is("urn:oid:0.9.2342.19200300.100.1.4"));
assertThat(attr2.getAttributeValue(), hasSize(1));
assertThat(attr2.getAttributeValue().get(0), instanceOf(String.class));
assertThat((String) attr2.getAttributeValue().get(0), is(""));
} }
@Test @Test
public void testEmptyAttributeValueLast() throws Exception { public void testEmptyAttributeValueLast() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-4790-Empty-attribute-value-last.xml")) { assertParsed("KEYCLOAK-4790-Empty-attribute-value-last.xml", ResponseType.class);
Object parsedObject = parser.parse(st); }
assertThat(parsedObject, instanceOf(ResponseType.class));
@Test
public void testAuthnRequest() throws Exception {
AuthnRequestType req = assertParsed("saml20-authnrequest.xml", AuthnRequestType.class);
assertThat(req.getRequestedAuthnContext(), notNullValue());
assertThat(req.getRequestedAuthnContext().getAuthnContextClassRef(), hasItem(is("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport")));
assertThat(req.getRequestedAuthnContext().getAuthnContextDeclRef(), hasItem(is("urn:kc:SAML:2.0:ac:ref:demo:decl")));
}
@Test
public void testAuthnRequestInvalidPerXsdWithValidationDisabled() throws Exception {
AuthnRequestType req = assertParsed("saml20-authnrequest-invalid-per-xsd.xml", AuthnRequestType.class);
}
@Test
public void testAuthnRequestInvalidPerXsdWithValidationEnabled() throws Exception {
try {
thrown.expect(ProcessingException.class);
System.setProperty("picketlink.schema.validate", "true");
AuthnRequestType req = assertParsed("saml20-authnrequest-invalid-per-xsd.xml", AuthnRequestType.class);
} finally {
System.clearProperty("picketlink.schema.validate");
} }
} }
@Test
public void testAuthnRequestInvalidNamespace() throws Exception {
thrown.expect(ParsingException.class);
thrown.expectMessage(containsString("Unknown Start Element"));
assertParsed("saml20-authnrequest-invalid-namespace.xml", AuthnRequestType.class);
}
@Test @Test
public void testAuthnRequestScoping() throws Exception { public void testAuthnRequestScoping() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-6109-authnrequest-scoping.xml")) { assertParsed("KEYCLOAK-6109-authnrequest-scoping.xml", AuthnRequestType.class);
Object parsedObject = parser.parse(st); }
assertThat(parsedObject, instanceOf(AuthnRequestType.class));
@Test
public void testLogoutResponseStatusDetail() throws Exception {
StatusResponseType resp = assertParsed("saml20-logout-response-status-detail.xml", StatusResponseType.class);
assertThat(resp.getIssuer(), notNullValue());
assertThat(resp.getIssuer().getValue(), is("http://idp.example.com/metadata.php"));
assertThat(resp.getIssuer().getFormat(), is(JBossSAMLURIConstants.NAMEID_FORMAT_ENTITY.getUri()));
assertThat(resp.getStatus(), notNullValue());
assertThat(resp.getStatus().getStatusDetail(), notNullValue());
assertThat(resp.getStatus().getStatusDetail().getAny(), notNullValue());
assertThat(resp.getStatus().getStatusDetail().getAny().size(), is(2));
assertThat(resp.getStatus().getStatusCode(), notNullValue());
assertThat(resp.getStatus().getStatusCode().getValue(), is(URI.create("urn:oasis:names:tc:SAML:2.0:status:Responder")));
assertThat(resp.getStatus().getStatusCode().getStatusCode(), nullValue());
}
@Test
public void testLogoutResponseSimpleStatus() throws Exception {
StatusResponseType resp = assertParsed("saml20-logout-response-status.xml", StatusResponseType.class);
assertThat(resp.getStatus(), notNullValue());
assertThat(resp.getStatus().getStatusMessage(), is("Status Message"));
assertThat(resp.getStatus().getStatusCode(), notNullValue());
assertThat(resp.getStatus().getStatusCode().getValue(), is(URI.create("urn:oasis:names:tc:SAML:2.0:status:Responder")));
assertThat(resp.getStatus().getStatusCode().getStatusCode(), nullValue());
}
@Test
public void testLogoutResponseNestedStatus() throws Exception {
StatusResponseType resp = assertParsed("saml20-logout-response-nested-status.xml", StatusResponseType.class);
assertThat(resp.getStatus(), notNullValue());
assertThat(resp.getStatus().getStatusCode(), notNullValue());
assertThat(resp.getStatus().getStatusCode().getValue(), is(URI.create("urn:oasis:names:tc:SAML:2.0:status:Responder")));
assertThat(resp.getStatus().getStatusCode().getStatusCode(), notNullValue());
assertThat(resp.getStatus().getStatusCode().getStatusCode().getValue(), is(URI.create("urn:oasis:names:tc:SAML:2.0:status:AuthnFailed")));
assertThat(resp.getStatus().getStatusCode().getStatusCode().getStatusCode(), nullValue());
}
@Test
public void testLogoutResponseDeepNestedStatus() throws Exception {
StatusResponseType resp = assertParsed("saml20-logout-response-nested-status-deep.xml", StatusResponseType.class);
assertThat(resp.getStatus(), notNullValue());
assertThat(resp.getStatus().getStatusDetail(), notNullValue());
assertThat(resp.getStatus().getStatusDetail().getAny(), notNullValue());
assertThat(resp.getStatus().getStatusDetail().getAny().size(), is(2));
assertThat(resp.getStatus().getStatusCode(), notNullValue());
assertThat(resp.getStatus().getStatusCode().getValue(), is(URI.create("urn:oasis:names:tc:SAML:2.0:status:Responder")));
assertThat(resp.getStatus().getStatusCode().getStatusCode(), notNullValue());
assertThat(resp.getStatus().getStatusCode().getStatusCode().getValue(), is(URI.create("urn:oasis:names:tc:SAML:2.0:status:AuthnFailed")));
assertThat(resp.getStatus().getStatusCode().getStatusCode().getStatusCode(), notNullValue());
assertThat(resp.getStatus().getStatusCode().getStatusCode().getStatusCode().getValue(), is(URI.create("urn:oasis:names:tc:SAML:2.0:status:VersionMismatch")));
}
@Test
public void testSaml20AssertionContents() throws Exception {
AssertionType a = assertParsed("saml20-assertion-example.xml", AssertionType.class);
assertThat(a.getSubject().getConfirmation(), hasSize(1));
assertThat(a.getSubject().getConfirmation().get(0).getSubjectConfirmationData(), notNullValue());
assertThat(a.getSubject().getConfirmation().get(0).getSubjectConfirmationData().getAnyType(), instanceOf(KeyInfoType.class));
KeyInfoType kit = (KeyInfoType) a.getSubject().getConfirmation().get(0).getSubjectConfirmationData().getAnyType();
assertThat(kit.getContent(), hasItem(instanceOf(RSAKeyValueType.class)));
RSAKeyValueType rsaKit = (RSAKeyValueType) kit.getContent().get(0);
assertThat(rsaKit.getModulus(), notNullValue());
assertThat(rsaKit.getExponent(), notNullValue());
assertThat(a.getStatements(), containsInAnyOrder(instanceOf(AuthnStatementType.class), instanceOf(AttributeStatementType.class)));
for (StatementAbstractType statement : a.getStatements()) {
if (statement instanceof AuthnStatementType) {
AuthnStatementType as = (AuthnStatementType) statement;
assertThat(as.getSessionNotOnOrAfter(), notNullValue());
assertThat(as.getSessionNotOnOrAfter(), is(XMLTimeUtil.parse("2009-06-17T18:55:10.738Z")));
final AuthnContextType ac = as.getAuthnContext();
assertThat(ac, notNullValue());
assertThat(ac.getSequence(), notNullValue());
assertThat(ac.getSequence().getClassRef().getValue(), is(JBossSAMLURIConstants.AC_UNSPECIFIED.getUri()));
assertThat(ac.getSequence(), notNullValue());
assertThat(ac.getSequence().getAuthnContextDecl(), nullValue());
}
} }
} }
@Test
public void testSaml20AssertionDsaKey() throws Exception {
AssertionType a = assertParsed("saml20-assertion-dsakey.xml", AssertionType.class);
assertThat(a.getSubject().getConfirmation(), hasSize(1));
assertThat(a.getSubject().getConfirmation().get(0).getSubjectConfirmationData(), notNullValue());
assertThat(a.getSubject().getConfirmation().get(0).getSubjectConfirmationData().getAnyType(), instanceOf(KeyInfoType.class));
KeyInfoType kit = (KeyInfoType) a.getSubject().getConfirmation().get(0).getSubjectConfirmationData().getAnyType();
assertThat(kit.getContent(), hasItem(instanceOf(DSAKeyValueType.class)));
DSAKeyValueType rsaKit = (DSAKeyValueType) kit.getContent().get(0);
assertThat(rsaKit.getG(), notNullValue());
assertThat(rsaKit.getJ(), nullValue());
assertThat(rsaKit.getP(), notNullValue());
assertThat(rsaKit.getQ(), notNullValue());
assertThat(rsaKit.getY(), notNullValue());
}
@Test @Test
public void testSaml20AssertionsAnyTypeAttributeValue() throws Exception { public void testSaml20AssertionsAnyTypeAttributeValue() throws Exception {
@ -348,21 +553,21 @@ public class SAMLParserTest {
} }
@Test(expected = ParsingException.class) @Test(expected = ParsingException.class)
public void testSaml20AssertionsNil1() throws IOException, ParsingException { public void testSaml20AssertionsNil1() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("saml20-assertion-nil-wrong-1.xml")) { try (InputStream st = SAMLParserTest.class.getResourceAsStream("saml20-assertion-nil-wrong-1.xml")) {
parser.parse(st); parser.parse(st);
} }
} }
@Test(expected = ParsingException.class) @Test(expected = ParsingException.class)
public void testSaml20AssertionsNil2() throws IOException, ParsingException { public void testSaml20AssertionsNil2() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("saml20-assertion-nil-wrong-2.xml")) { try (InputStream st = SAMLParserTest.class.getResourceAsStream("saml20-assertion-nil-wrong-2.xml")) {
parser.parse(st); parser.parse(st);
} }
} }
@Test @Test
public void testSaml20AssertionsMissingId() throws IOException, ParsingException { public void testSaml20AssertionsMissingId() throws Exception {
try (InputStream st = removeAttribute("saml20-assertion-example.xml", "ID")) { try (InputStream st = removeAttribute("saml20-assertion-example.xml", "ID")) {
thrown.expect(ParsingException.class); thrown.expect(ParsingException.class);
thrown.expectMessage(endsWith("Required attribute missing: ID")); thrown.expectMessage(endsWith("Required attribute missing: ID"));
@ -371,8 +576,17 @@ public class SAMLParserTest {
} }
@Test @Test
public void testSaml20AssertionsMissingVersion() throws IOException, ParsingException { public void testSaml20AssertionsMissingVersion() throws Exception {
try (InputStream st = removeAttribute("saml20-assertion-example.xml", "Version")) { try (InputStream st = removeAttribute("saml20-assertion-example.xml", "Version")) {
thrown.expect(ParsingException.class);
thrown.expectMessage(endsWith("Required attribute missing: Version"));
parser.parse(st);
}
}
@Test
public void testSaml20AssertionsWrongVersion() throws Exception {
try (InputStream st = updateAttribute("saml20-assertion-example.xml", "Version", "1.1")) {
thrown.expect(ParsingException.class); thrown.expect(ParsingException.class);
thrown.expectMessage(endsWith("Assertion Version required to be \"2.0\"")); thrown.expectMessage(endsWith("Assertion Version required to be \"2.0\""));
parser.parse(st); parser.parse(st);
@ -380,7 +594,7 @@ public class SAMLParserTest {
} }
@Test @Test
public void testSaml20AssertionsMissingIssueInstance() throws IOException, ParsingException { public void testSaml20AssertionsMissingIssueInstance() throws Exception {
try (InputStream st = removeAttribute("saml20-assertion-example.xml", "IssueInstant")) { try (InputStream st = removeAttribute("saml20-assertion-example.xml", "IssueInstant")) {
thrown.expect(ParsingException.class); thrown.expect(ParsingException.class);
thrown.expectMessage(endsWith("Required attribute missing: IssueInstant")); thrown.expectMessage(endsWith("Required attribute missing: IssueInstant"));
@ -389,10 +603,60 @@ public class SAMLParserTest {
} }
@Test @Test
public void testSaml20AssertionsAdviceTag() throws IOException, ParsingException { public void testSaml20AssertionsAdviceTag() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("saml20-assertion-advice.xml")) { Matcher<String>[] ATTR_NAME = new Matcher[] {
parser.parse(st); is("portal_id"),
is("organization_id"),
is("status"),
is("has_sub_organization"),
is("anytype_test"),
is("anytype_no_xml_test"),
is("ssostartpage"),
is("logouturl"),
is("nil_value_attribute"),
};
Matcher<List<Object>>[] ATTR_VALUE = new Matcher[] {
contains(is("060D00000000SHZ")),
contains(is("<n1:elem2 xmlns:n1=\"http://example.net\" xml:lang=\"en\"><n3:stuff xmlns:n3=\"ftp://example.org\">00DD0000000F7L5</n3:stuff></n1:elem2>")),
contains(is("<status><code><status>XYZ</status></code></status>")),
contains(is("true")),
contains(is("<elem1 atttr1=\"en\"><elem2>val2</elem2></elem1>")),
contains(is("value_no_xml")),
contains(is("http://www.salesforce.com/security/saml/saml20-gen.jsp")),
contains(is("http://www.salesforce.com/security/del_auth/SsoLogoutPage.html")),
contains(nullValue()),
};
AssertionType a = assertParsed("saml20-assertion-advice.xml", AssertionType.class);
assertThat(a.getStatements(), containsInAnyOrder(instanceOf(AuthnStatementType.class), instanceOf(AttributeStatementType.class)));
for (StatementAbstractType statement : a.getStatements()) {
if (statement instanceof AuthnStatementType) {
AuthnStatementType as = (AuthnStatementType) statement;
final AuthnContextType ac = as.getAuthnContext();
assertThat(ac, notNullValue());
assertThat(ac.getSequence(), notNullValue());
assertThat(ac.getSequence().getClassRef().getValue(), is(JBossSAMLURIConstants.AC_UNSPECIFIED.getUri()));
assertThat(ac.getSequence(), notNullValue());
assertThat(ac.getSequence().getAuthnContextDecl(), notNullValue());
assertThat(ac.getSequence().getAuthnContextDecl().getValue(), instanceOf(Element.class));
final Element el = (Element) ac.getSequence().getAuthnContextDecl().getValue();
assertThat(el.getTextContent(), is("auth.weak"));
} else {
AttributeStatementType as = (AttributeStatementType) statement;
assertThat(as.getAttributes(), hasSize(9));
for (int i = 0; i < as.getAttributes().size(); i ++) {
AttributeType attr = as.getAttributes().get(i).getAttribute();
assertThat(attr.getName(), ATTR_NAME[i]);
assertThat(attr.getAttributeValue(), ATTR_VALUE[i]);
}
}
} }
assertThat(a.getConditions().getConditions(), contains(instanceOf(AudienceRestrictionType.class)));
} }
private InputStream removeAttribute(String resourceName, String attribute) throws IOException { private InputStream removeAttribute(String resourceName, String attribute) throws IOException {
@ -403,5 +667,13 @@ public class SAMLParserTest {
} }
} }
private InputStream updateAttribute(String resourceName, String attribute, String newValue) throws IOException {
try (InputStream st = SAMLParserTest.class.getResourceAsStream(resourceName)) {
String str = StreamUtil.readString(st, StandardCharsets.UTF_8);
String processed = str.replaceAll("(" + attribute + "=)\"[^\"]+\"", "$1\"" + newValue + "\"");
return new ByteArrayInputStream(processed.getBytes());
}
}
} }

View file

@ -20,6 +20,7 @@
<saml:AuthnStatement AuthnInstant="2016-12-15T12:42:49.788Z" SessionIndex="fb5d5a23-aa34-4528-a29a-6aad8c0ef0e8"> <saml:AuthnStatement AuthnInstant="2016-12-15T12:42:49.788Z" SessionIndex="fb5d5a23-aa34-4528-a29a-6aad8c0ef0e8">
<saml:AuthnContext> <saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
<saml:AuthnContextDeclRef>http://www.example.com/</saml:AuthnContextDeclRef>
</saml:AuthnContext> </saml:AuthnContext>
</saml:AuthnStatement> </saml:AuthnStatement>
<saml:AttributeStatement> <saml:AttributeStatement>

View file

@ -8,7 +8,14 @@
<saml:Subject> <saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">roàåאבčéèíñòøöùüßåäöü汉字</saml:NameID> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">roàåאבčéèíñòøöùüßåäöü汉字</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData InResponseTo="ID_cc0ff6f7-b481-4c98-9a79-481d50958290" NotOnOrAfter="2016-12-15T12:47:47.787Z" Recipient="http://localhost:8080/sales-post-sig/saml"/> <saml:SubjectConfirmationData InResponseTo="ID_cc0ff6f7-b481-4c98-9a79-481d50958290" NotOnOrAfter="2016-12-15T12:47:47.787Z" Recipient="http://localhost:8080/sales-post-sig/saml">
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<a>should be ignored</a>
<X509Data>
<X509Certificate>MIIFUjCCBDqgAwIBAgIDBbH0MA0GCSqGSIb3DQEBBQUAMGExCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR0wGwYDVQQLExREb21haW4gVmFsaWRhdGVkIFNTTDEbMBkGA1UEAxMSR2VvVHJ1c3QgRFYgU1NMIENBMB4XDTEyMTIxODAyMjcxOVoXDTE2MTIyMDAwNTYwMFowgckxKTAnBgNVBAUTIHlMbC1HNjFUWWtiaHBaL1JMTnNIYU8vTmJyWEVQOXc1MRMwEQYDVQQLEwpHVDQ4MjA0OTU4MTEwLwYDVQQLEyhTZWUgd3d3Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvY3BzIChjKTEyMTcwNQYDVQQLEy5Eb21haW4gQ29udHJvbCBWYWxpZGF0ZWQgLSBRdWlja1NTTChSKSBQcmVtaXVtMRswGQYDVQQDExJzYW1sLnNoYXJlZmlsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPUZyhTw3RmP7Y7v06aHgTNuv/Fm0PbGWbGlZEwqr8TGabocPbnb8iTBWAL2ECXMbx+VrpaHiSOVxqC2Y/vDXOs+1r0CzRKeMC6oQPsXZbieW6HxOAv3UVShxc9nfWI6+immo/o3BYI5WKcOaeZieVlDq7a7ctfSUJXHEBhpaSJNhghb+cUZtp1/EXs8/LyVQ31coo1q726WjCvFVB8OUU2u6BQLcbJF5aG3qh5CkNyivwM3NtNAyHhSXRmwyE+Yv5YNo5QAtUagCGYmS2saEJj8FxhXsNRtfW5B6vVhgmNreTcHCcWTpFGhjvferPjsjaIQAs3P2zx/pW/GSCXHy1AgMBAAGjggGoMIIBpDAfBgNVHSMEGDAWgBSM9NmTCke8AKBKzkt1bqC2sLJ+/DAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdEQQWMBSCEnNhbWwuc2hhcmVmaWxlLmNvbTBBBgNVHR8EOjA4MDagNKAyhjBodHRwOi8vZ3Rzc2xkdi1jcmwuZ2VvdHJ1c3QuY29tL2NybHMvZ3Rzc2xkdi5jcmwwHQYDVR0OBBYEFIDTam2PfOzLpQoclHMwfsUtSi3kMAwGA1UdEwEB/wQCMAAwdQYIKwYBBQUHAQEEaTBnMCwGCCsGAQUFBzABhiBodHRwOi8vZ3Rzc2xkdi1vY3NwLmdlb3RydXN0LmNvbTA3BggrBgEFBQcwAoYraHR0cDovL2d0c3NsZHYtYWlhLmdlb3RydXN0LmNvbS9ndHNzbGR2LmNydDBMBgNVHSAERTBDMEEGCmCGSAGG+EUBBzYwMzAxBggrBgEFBQcCARYlaHR0cDovL3d3dy5nZW90cnVzdC5jb20vcmVzb3VyY2VzL2NwczANBgkqhkiG9w0BAQUFAAOCAQEAU0I6sMe1ZgJ27pdu9qhQLMIgt0w7CuEbLfsSZZdo5TXEj15SGQwU2A0F6o5ivdAvMWTCISJsjHdqCkvB6ZOdMHIfSqA9ARLqX7wLKYfM8X/4RM3koHfqHOvxXBLqCLj2mn34oZrMU5CVI6rqbMoU4D61io7DVswR7Dss0rCh1b1o52ZEBjy5w9oJhRTEFwL7ekf6tR9UioyxQ37pGfD8qOpX1hj5gqcZ5+qUSVNjOjeh+9e9OO5Y/ns3jjHK5ieZPdYeLLOp+D6qzAnOERgvKvkPyRIHZA9tAjxj5KIEzQUopmbP7oH4Ovo6YXT+iIuMVvX3dDu00ExOSZjEeDzo/w==</X509Certificate>
</X509Data>
</KeyInfo>
</saml:SubjectConfirmationData>
</saml:SubjectConfirmation> </saml:SubjectConfirmation>
</saml:Subject> </saml:Subject>
<saml:Conditions NotBefore="2016-12-15T12:42:47.787Z" NotOnOrAfter="2016-12-15T12:43:47.787Z"> <saml:Conditions NotBefore="2016-12-15T12:42:47.787Z" NotOnOrAfter="2016-12-15T12:43:47.787Z">

View file

@ -10,7 +10,29 @@
<Subject> <Subject>
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName">C=c,OU=ou</NameID> <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName">C=c,OU=ou</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<SubjectConfirmationData InResponseTo="ID_638a829f-7ad2-408e-b3e5-5f224001057f" NotOnOrAfter="2017-04-24T12:55:14.645Z" Recipient="https://y/auth/realms/administration/broker/saml/endpoint"/> <SubjectConfirmationData InResponseTo="ID_638a829f-7ad2-408e-b3e5-5f224001057f" NotOnOrAfter="2017-04-24T12:55:14.645Z" Recipient="https://y/auth/realms/administration/broker/saml/endpoint">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<!-- principal's X.509 cert -->
<ds:X509Certificate>
MIICiDCCAXACCQDE+9eiWrm62jANBgkqhkiG9w0BAQQFADBFMQswCQYDVQQGEwJV
UzESMBAGA1UEChMJTkNTQS1URVNUMQ0wCwYDVQQLEwRVc2VyMRMwEQYDVQQDEwpT
UC1TZXJ2aWNlMB4XDTA2MDcxNzIwMjE0MVoXDTA2MDcxODIwMjE0MVowSzELMAkG
A1UEBhMCVVMxEjAQBgNVBAoTCU5DU0EtVEVTVDENMAsGA1UECxMEVXNlcjEZMBcG
A1UEAwwQdHJzY2F2b0B1aXVjLmVkdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEAv9QMe4lRl3XbWPcflbCjGK9gty6zBJmp+tsaJINM0VaBaZ3t+tSXknelYife
nCc2O3yaX76aq53QMXy+5wKQYe8Rzdw28Nv3a73wfjXJXoUhGkvERcscs9EfIWcC
g2bHOg8uSh+Fbv3lHih4lBJ5MCS2buJfsR7dlr/xsadU2RcCAwEAATANBgkqhkiG
9w0BAQQFAAOCAQEAdyIcMTob7TVkelfJ7+I1j0LO24UlKvbLzd2OPvcFTCv6fVHx
Ejk0QxaZXJhreZ6+rIdiMXrEzlRdJEsNMxtDW8++sVp6avoB5EX1y3ez+CEAIL4g
cjvKZUR4dMryWshWIBHKFFul+r7urUgvWI12KbMeE9KP+kiiiiTskLcKgFzngw1J
selmHhTcTCrcDocn5yO2+d3dog52vSOtVFDBsBuvDixO2hv679JR6Hlqjtk4GExp
E9iVI0wdPE038uQIJJTXlhsMMLvUGVh/c0ReJBn92Vj4dI/yy6PtY/8ncYLYNkjg
oVN0J/ymOktn9lTlFyTiuY4OuJsZRO1+zWLy9g==
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</SubjectConfirmationData>
</SubjectConfirmation> </SubjectConfirmation>
</Subject> </Subject>
<Conditions NotBefore="2017-04-24T12:45:14.380Z" NotOnOrAfter="2017-04-24T13:45:14.380Z"> <Conditions NotBefore="2017-04-24T12:45:14.380Z" NotOnOrAfter="2017-04-24T13:45:14.380Z">
@ -25,6 +47,11 @@
<Attribute Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <Attribute Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<AttributeValue>aa</AttributeValue> <AttributeValue>aa</AttributeValue>
</Attribute> </Attribute>
<Attribute Name="urn:oid:0.9.2342.19200300.100.1.4" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<AttributeValue>
</AttributeValue>
</Attribute>
</AttributeStatement> </AttributeStatement>
<AuthnStatement AuthnInstant="2017-04-24T12:50:14.037Z" SessionIndex="_0cceed2a-e409-4faa-a411-c647be748f2b"> <AuthnStatement AuthnInstant="2017-04-24T12:50:14.037Z" SessionIndex="_0cceed2a-e409-4faa-a411-c647be748f2b">
<AuthnContext> <AuthnContext>

View file

@ -59,10 +59,6 @@
</saml:AudienceRestriction> </saml:AudienceRestriction>
</saml:Conditions> </saml:Conditions>
<saml:Advice>
<saml:AssertionIDRef>NCName</saml:AssertionIDRef>
</saml:Advice>
<saml:Advice> <saml:Advice>
<saml:AssertionURIRef>NCName</saml:AssertionURIRef> <saml:AssertionURIRef>NCName</saml:AssertionURIRef>
<a:a xmlns:a="urn:a"> <a:a xmlns:a="urn:a">
@ -74,8 +70,8 @@
<saml:AuthnStatement AuthnInstant="2009-06-17T18:45:10.738Z"> <saml:AuthnStatement AuthnInstant="2009-06-17T18:45:10.738Z">
<saml:AuthnContext> <saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContextClassRef> <saml:AuthnContextDecl xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">auth.weak</saml:AuthnContextDecl>
</saml:AuthnContext> </saml:AuthnContext>
</saml:AuthnStatement> </saml:AuthnStatement>

View file

@ -0,0 +1,44 @@
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema"
ID="_3c39bc0fe7b13769cab2f6f45eba801b1245264310738"
IssueInstant="2009-06-17T18:45:10.738Z" Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
https://www.salesforce.com
</saml:Issuer>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">
saml01@salesforce.com
</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2009-06-17T18:50:10.738Z"
Recipient="https://login.salesforce.com">
<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<dsig:KeyValue>
<dsig:DSAKeyValue>
<dsig:P>/KaCzo4Syrom78z3EQ5SbbB4sF7ey80etKII864WF64B81uRpH5t9jQTxeEu0ImbzRMqzVDZkVG9xD7nN1kuFw==</dsig:P>
<dsig:Q>li7dzDacuo67Jg7mtqEm2TRuOMU=</dsig:Q>
<dsig:G>Z4Rxsnqc9E7pGknFFH2xqaryRPBaQ01khpMdLRQnG541Awtx/XPaF5Bpsy4pNWMOHCBiNU0NogpsQW5QvnlMpA==</dsig:G>
<dsig:Y>qV38IqrWJG0V/mZQvRVi1OHw9Zj84nDC4jO8P0axi1gb6d+475yhMjSc/BrIVC58W3ydbkK+Ri4OKbaRZlYeRA==</dsig:Y>
</dsig:DSAKeyValue>
</dsig:KeyValue>
</dsig:KeyInfo>
</saml:SubjectConfirmationData>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2009-06-17T18:45:10.738Z"
NotOnOrAfter="2009-06-17T18:50:10.738Z">
<saml:AudienceRestriction>
<saml:Audience>https://saml.salesforce.com</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2009-06-17T18:45:10.738Z" NotOnOrAfter="2009-06-17T18:55:10.738Z">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
</saml:Assertion>

View file

@ -0,0 +1,10 @@
<saml:EncryptedAssertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
<xenc:CipherData>
<xenc:CipherValue>
RW2eu9nP2Ez9hfRlug9xC+kFfVF3HZpEb4kIFH33gmVbzrQjPk0l67uXkwRjC82FZZ482QnHCBIqNFlAryds/zTa6wdRvFmhQnIM6WxoAl8TM+e9h8MoKkalMc8J/Qfp+WQ7/XdmCg2pp9VvUZTK+g0+G4aGuL+S5+ssZq4rl9k7LrSYyp6vj+djgvISZiz5hPYJCN/WY/gWXfVuLHSpu4CmZt8D2APtT3ax1WmGcuzStAfTW8q3MFIDNV59hkpFmDb+gvyLNbZ95cDYxofiPXaC5cOTftnSBp68Ay1eienqdttEDo4fyakszdvq128KwXkH9azCg6sqLxli6B8l2xdq41MeuJO54VqmOhhLxwKy42NtnJvK/NkNwttH4yMwDPpPbC4vOKCXxT2r2F7jjvJQNB2VFv+oiUAWSSc3fGQcc2uNlx9YQVuzTmjqc7fXAWCGgYoogC8AeNWni204bnBoVpFrEo3gzuOe2fFsddJIclglmTH1hWf31FXUHDO2nl/lT4puQVTo+I+d6jpiV+qdp823NDntRxljRlUJO2AzSTXuIIGtF5q5KWyEi9Nj93BCWa1Llcddkn3ZEZMvDwR4MacwUj8G8hwoH73VvT3jAiakjSpNEIqYCzofeejdfN/gEuuAUfe8uNbTu+gBS+iP3QJe3Pc0Fs/lKJzd3frPNj7xb83wpOf865EQQoOozhnRIKKcMReSjakr/Px5NNooeiJcWEreDagQO2TbwTnHg1kCNG3BAXV/2lV3XBU4afZBoUfxAzYWFOl6xFCAPzhQCPL1SFJp1VRADY/1MU2Kaje5AZoJ4jjph8+yspxBvjic1vC1uYRGW8LWRind9w4eVhCm0LfPiFRCpP+jKPQOJzcNH580/nIMFXPHHnLKv/It7Qex1unDv/QjkuCFFHR6SWJm4WBrwDek+MyOIvgT6o878Cu0Ps472QpoYBQ+7l2WoylWdG1lHZV1UiHPj7PLHPNAL4rbbN3U88fS6N9OJHegQTfcX0i/1KPk4IN/5Z+/15dHI658BINjRvI/6O1QqaTVZkqM8ORcoGpn6BjAiz5rRhjWpOCwlmT+VzOAp3IqACURS1X+txjWE2mfVjlHLJsvyGRDLv1dUR3IeStDAEfsjR/ruRgn5XTFpYaccB/u//DJonJr5A+KFiLbYl+sbbSVAoQCAiAdxKdUpKPx7C473UJ2nYQGby5H5xwboa0Uj0SnJLYWdQ0jvVvzWpWFVWATc4UqnaxdoUDAmewrM6cSSIAmQBB34orCunFbriK9Z4efZ7gB9erQ1fpi3z/IjQBoTEpOUUIPW/qMAApIDPVM6UV9PumW7RL9zKEP5PuWJoGGnKbWGP/b9G4vMFiWMaSNHBYYMI6OLH4WJ3E+4QBGh2vjjfQ0gobhaLgIerIwCQFYEdl9KddAjaflUEFXal9fIQ8Bz9L3rDhQE5AGBZL6ULZmJe3GnkN6Cc+UWAGyD5zv2rsCG2lvR5ox4UE2mFi6nBJbC5Vj5m9Sz1l0QpRwUkH2kD2QQ5iV6nNmQOcU/mz7ulxluf8+FBJJimYVqK8UkJ6+W6j8Eft9Q8fTpEuEVLxqTWGgOAEUBf87RWDU+iF3A+AxFGsJLc5RC+5BKNTEDlV2qDCjHT7b5wqBKJ3FHulOih9EenlZiI51m6kg5yyxnMdbhasvSh6Az8Mp/4lFo/wSA/mXxNhBrEEmRhFiIE5yYUEYIj5F8fH+93tIuWQqyhXIwCntEOdSSmoei9EYFzj8deXcEzVf8y/N6HQErZcJjyg34caOsfRcJYoxEiCm4icA/btWhdjUNT02B20qnxGFndO4CRUQlyDqTbyVD8LRLK9/95L9+5v9zojLle8xQe30dsxKn7r9TTJH8QQai5iam9lU1ik50lwTKpZb18k4rNdO5cnnYoHzCXeCg38YZxyFt9G7um/MxlID5Qd5Ywq6thDzL7WxvanKeRhCuJ2MTVV0EoJxZKIj9Yv0Ars9mZHkoHoP0ikcW8d5ciDj1Onnbj+XDcYI3FZj0Y2vToZvYi/7eLWi8EnSjaIQrr/AHnrmZK1w3Uicd691U6r3Y0UdnzQEl4Ub/l1uhSaGAg2oEdDxkOdZ3Frvf/C4nTEBmunPlNvnJjVFssdeVVXKLBOZ5eRiJjasHUKnTeJVwolvd/dBI+ypfw1+5ae/0upxd9/gV1lbwX9N2yOwqbxz24cKXZWvOFBAGc3+gQFu8RrF6NAeQ96PlkuRsiNOKPPtJT3JNrLGvVKY8g==
</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</saml:EncryptedAssertion>

View file

@ -47,7 +47,18 @@
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2009-06-17T18:50:10.738Z" <saml:SubjectConfirmationData NotOnOrAfter="2009-06-17T18:50:10.738Z"
Recipient="https://login.salesforce.com"/> Recipient="https://login.salesforce.com">
<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<dsig:KeyValue>
<dsig:RSAKeyValue>
<dsig:Modulus>
2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEik=
</dsig:Modulus>
<dsig:Exponent>AQAB</dsig:Exponent>
</dsig:RSAKeyValue>
</dsig:KeyValue>
</dsig:KeyInfo>
</saml:SubjectConfirmationData>
</saml:SubjectConfirmation> </saml:SubjectConfirmation>
</saml:Subject> </saml:Subject>
@ -59,7 +70,7 @@
</saml:AudienceRestriction> </saml:AudienceRestriction>
</saml:Conditions> </saml:Conditions>
<saml:AuthnStatement AuthnInstant="2009-06-17T18:45:10.738Z"> <saml:AuthnStatement AuthnInstant="2009-06-17T18:45:10.738Z" NotOnOrAfter="2009-06-17T18:55:10.738Z">
<saml:AuthnContext> <saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified
</saml:AuthnContextClassRef> </saml:AuthnContextClassRef>

View file

@ -0,0 +1,9 @@
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:3.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:3.0:assertion"
ID="aaf23196-1773-2113-474a-fe114412ab72" Version="2.0" IssueInstant="2004-12-05T09:21:59">
<saml:Issuer>https://sp/</saml:Issuer>
<samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
<samlp:RequestedAuthnContext Comparison="exact">
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
<saml:AuthnContextDeclRef>urn:kc:SAML:2.0:ac:ref:demo:decl</saml:AuthnContextDeclRef>
</samlp:RequestedAuthnContext>
</samlp:AuthnRequest>

View file

@ -0,0 +1,10 @@
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="aaf23196-1773-2113-474a-fe114412ab72" Version="2.0" IssueInstant="2004-12-05T09:21:59">
<saml:Issuer>https://sp/</saml:Issuer>
<saml:Issuer>https://sp/</saml:Issuer>
<samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
<samlp:RequestedAuthnContext Comparison="exact">
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
<saml:AuthnContextDeclRef>urn:kc:SAML:2.0:ac:ref:demo:decl</saml:AuthnContextDeclRef>
</samlp:RequestedAuthnContext>
</samlp:AuthnRequest>

View file

@ -2,4 +2,8 @@
ID="aaf23196-1773-2113-474a-fe114412ab72" Version="2.0" IssueInstant="2004-12-05T09:21:59"> ID="aaf23196-1773-2113-474a-fe114412ab72" Version="2.0" IssueInstant="2004-12-05T09:21:59">
<saml:Issuer>https://sp/</saml:Issuer> <saml:Issuer>https://sp/</saml:Issuer>
<samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/> <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
<samlp:RequestedAuthnContext Comparison="exact">
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
<saml:AuthnContextDeclRef>urn:kc:SAML:2.0:ac:ref:demo:decl</saml:AuthnContextDeclRef>
</samlp:RequestedAuthnContext>
</samlp:AuthnRequest> </samlp:AuthnRequest>

View file

@ -1,5 +1,5 @@
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Destination="http://localhost:8080/sales-post-enc/saml" ID="ID_0b43d444-d1a8-44a5-8caf-38e176489e1f" InResponseTo="ID_223d3591-22fb-4b3c-9e38-4719293b2d94" IssueInstant="2016-11-01T13:52:43.054Z" Version="2.0"> <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Destination="http://localhost:8080/sales-post-enc/saml" ID="ID_0b43d444-d1a8-44a5-8caf-38e176489e1f" InResponseTo="ID_223d3591-22fb-4b3c-9e38-4719293b2d94" IssueInstant="2016-11-01T13:52:43.054Z" Version="2.0">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:8081/auth/realms/saml-demo</saml:Issuer> <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://localhost:8081/auth/realms/saml-demo</saml:Issuer>
<samlp:Extensions> <samlp:Extensions>
<kckey:KeyInfo xmlns:kckey="urn:keycloak:ext:key:1.0" MessageSigningKeyId="FJ86GcF3jTbNLOco4NvZkUCIUmfYCqoqtOQeMfbhNlE"/> <kckey:KeyInfo xmlns:kckey="urn:keycloak:ext:key:1.0" MessageSigningKeyId="FJ86GcF3jTbNLOco4NvZkUCIUmfYCqoqtOQeMfbhNlE"/>
</samlp:Extensions> </samlp:Extensions>

Some files were not shown because too many files have changed in this diff Show more