KEYCLOAK-6473 KEYCLOAK-6472 SAML parser refactor + protocol parsers
This commit is contained in:
parent
898347366d
commit
e7cdb8ad54
117 changed files with 4747 additions and 3060 deletions
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -225,7 +225,7 @@ public interface PicketLinkLogger {
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
RuntimeException parserUnknownEndElement(String endElementName);
|
RuntimeException parserUnknownEndElement(String endElementName, Location location);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tag
|
* @param tag
|
||||||
|
|
|
@ -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;
|
private static final Pattern WHITESPACE_ONLY = Pattern.compile("\\s*");
|
||||||
}
|
|
||||||
|
|
||||||
protected XMLEventReader filterWhitespaces(XMLEventReader xmlEventReader) throws XMLStreamException {
|
/**
|
||||||
|
* 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();
|
||||||
|
|
||||||
|
try {
|
||||||
xmlEventReader = xmlInputFactory.createFilteredReader(xmlEventReader, new EventFilter() {
|
xmlEventReader = xmlInputFactory.createFilteredReader(xmlEventReader, new EventFilter() {
|
||||||
|
@Override
|
||||||
public boolean accept(XMLEvent xmlEvent) {
|
public boolean accept(XMLEvent xmlEvent) {
|
||||||
// We are going to disregard characters that are new line and whitespace
|
// We are going to disregard characters that are new line and whitespace
|
||||||
if (xmlEvent.isCharacters()) {
|
if (xmlEvent.isCharacters()) {
|
||||||
Characters chars = xmlEvent.asCharacters();
|
Characters chars = xmlEvent.asCharacters();
|
||||||
String data = chars.getData();
|
String data = chars.getData();
|
||||||
data = valid(data) ? data.trim() : null;
|
return data != null && ! WHITESPACE_ONLY.matcher(data).matches();
|
||||||
return valid(data);
|
|
||||||
} else {
|
} else {
|
||||||
return xmlEvent.isStartElement() || xmlEvent.isEndElement();
|
return xmlEvent.isStartElement() || xmlEvent.isEndElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean valid(String str) {
|
|
||||||
return str != null && ! str.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
} catch (XMLStreamException ex) {
|
||||||
|
throw logger.parserException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
}
|
|
@ -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()) {
|
||||||
if (xmlEvent == null || xmlEvent.isStartElement())
|
xmlEventReader.nextEvent();
|
||||||
return (StartElement) xmlEvent;
|
xmlEvent = xmlEventReader.peek();
|
||||||
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 + ">"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 <samlp:Extensions> 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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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) {
|
||||||
String elementName = StaxParserUtil.getStartElementName(startElement);
|
throw logger.parserException(new RuntimeException(ErrorCodes.UNKNOWN_START_ELEMENT + name + "::location="
|
||||||
|
+ startElement.getLocation()));
|
||||||
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);
|
return pf.create().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());
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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 <samlp:Extensions> 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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 <samlp:Extensions> 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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,20 +98,33 @@ 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(), not(nullValue()));
|
||||||
assertThat(resp.getExtensions().getAny().size(), is(1));
|
assertThat(resp.getExtensions().getAny().size(), is(1));
|
||||||
|
@ -101,16 +137,24 @@ public class SAMLParserTest {
|
||||||
|
|
||||||
assertThat(resp.getAssertions(), not(nullValue()));
|
assertThat(resp.getAssertions(), not(nullValue()));
|
||||||
assertThat(resp.getAssertions().size(), is(1));
|
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(parsedObject, instanceOf(ResponseType.class));
|
|
||||||
|
|
||||||
ResponseType resp = (ResponseType) parsedObject;
|
|
||||||
assertThat(resp.getAssertions().size(), is(1));
|
assertThat(resp.getAssertions().size(), is(1));
|
||||||
|
|
||||||
ResponseType.RTChoiceType rtChoiceType = resp.getAssertions().get(0);
|
ResponseType.RTChoiceType rtChoiceType = resp.getAssertions().get(0);
|
||||||
|
@ -124,17 +168,12 @@ public class SAMLParserTest {
|
||||||
assertNotNull(rtChoiceType.getAssertion());
|
assertNotNull(rtChoiceType.getAssertion());
|
||||||
assertNull(rtChoiceType.getEncryptedAssertion());
|
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(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()));
|
||||||
|
@ -158,107 +197,273 @@ public class SAMLParserTest {
|
||||||
assertThat(resp.getAssertions(), not(nullValue()));
|
assertThat(resp.getAssertions(), not(nullValue()));
|
||||||
assertThat(resp.getAssertions().size(), is(1));
|
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(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));
|
final SubjectType subject = assertion.getSubject();
|
||||||
|
|
||||||
NameIDType nameId = (NameIDType) assertion.getSubject().getSubType().getBaseID();
|
assertThat(subject.getConfirmation(), hasSize(1));
|
||||||
|
SubjectConfirmationType confirmation = subject.getConfirmation().get(0);
|
||||||
|
assertThat(confirmation.getMethod(), is(JBossSAMLURIConstants.SUBJECT_CONFIRMATION_BEARER.get()));
|
||||||
|
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"));
|
||||||
|
|
||||||
|
assertThat(subject.getSubType().getBaseID(), instanceOf(NameIDType.class));
|
||||||
|
NameIDType nameId = (NameIDType) subject.getSubType().getBaseID();
|
||||||
assertThat(nameId.getValue(), is("ročéíöüßäöü"));
|
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
|
@Test
|
||||||
public void testAuthnRequestScoping() throws Exception {
|
public void testAuthnRequestInvalidNamespace() throws Exception {
|
||||||
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-6109-authnrequest-scoping.xml")) {
|
thrown.expect(ParsingException.class);
|
||||||
Object parsedObject = parser.parse(st);
|
thrown.expectMessage(containsString("Unknown Start Element"));
|
||||||
assertThat(parsedObject, instanceOf(AuthnRequestType.class));
|
|
||||||
|
assertParsed("saml20-authnrequest-invalid-namespace.xml", AuthnRequestType.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAuthnRequestScoping() throws Exception {
|
||||||
|
assertParsed("KEYCLOAK-6109-authnrequest-scoping.xml", 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
|
||||||
|
@ -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,11 +603,61 @@ 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 {
|
||||||
try (InputStream st = SAMLParserTest.class.getResourceAsStream(resourceName)) {
|
try (InputStream st = SAMLParserTest.class.getResourceAsStream(resourceName)) {
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
Loading…
Reference in a new issue