keycloak-aplcache
Changes
pom.xml 2(+1 -1)
saml/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/ManageNameIDRequestType.java 158(+0 -158)
saml/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDMappingRequestType.java 135(+0 -135)
saml/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDMappingResponseType.java 90(+0 -90)
saml/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/RequestAbstractType.java 149(+0 -149)
saml/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/RequestedAuthnContextType.java 135(+0 -135)
saml/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/SubjectQueryAbstractType.java 63(+0 -63)
saml/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/CanonicalizationMethodType.java 67(+0 -67)
saml/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/RetrievalMethodType.java 101(+0 -101)
saml/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignaturePropertiesType.java 85(+0 -85)
saml/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignaturePropertyType.java 95(+0 -95)
saml/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/X509IssuerSerialType.java 82(+0 -82)
saml/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionPropertiesType.java 84(+0 -84)
saml/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionPropertyType.java 109(+0 -109)
saml/saml-core/src/main/java/org/keycloak/saml/common/constants/JBossSAMLURIConstants.java 132(+0 -132)
saml/saml-core/src/main/java/org/keycloak/saml/common/constants/PicketLinkCommonConstants.java 30(+0 -30)
saml/saml-core/src/main/java/org/keycloak/saml/common/constants/SAMLAuthenticationContextClass.java 63(+0 -63)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ConfigurationException.java 45(+0 -45)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/AssertionExpiredException.java 53(+0 -53)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/IssueInstantMissingException.java 45(+0 -45)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/IssuerNotTrustedException.java 45(+0 -45)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/SignatureValidationException.java 44(+0 -44)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/WSTrustException.java 65(+0 -65)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/NotImplementedException.java 36(+0 -36)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/PicketLinkException.java 45(+0 -45)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ProcessingException.java 45(+0 -45)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/TrustKeyConfigurationException.java 43(+0 -43)
saml/saml-core/src/main/java/org/keycloak/saml/common/exceptions/TrustKeyProcessingException.java 43(+0 -43)
saml/saml-core/src/main/java/org/keycloak/saml/common/parsers/ParserNamespaceSupport.java 54(+0 -54)
saml/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java 336(+0 -336)
saml/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SecurityActions.java 166(+0 -166)
saml/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/response/SecurityActions.java 122(+0 -122)
saml/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java 238(+0 -238)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/constants/AttributeConstants.java 34(+0 -34)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/constants/PicketLinkFederationConstants.java 53(+0 -53)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/AbstractDescriptorParser.java 66(+0 -66)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java 123(+0 -123)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11AssertionParser.java 178(+0 -178)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11RequestParser.java 116(+0 -116)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11ResponseParser.java 189(+0 -189)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11SubjectParser.java 114(+0 -114)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLArtifactResolveParser.java 90(+0 -90)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLArtifactResponseParser.java 111(+0 -111)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAssertionParser.java 174(+0 -174)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAttributeQueryParser.java 92(+0 -92)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAuthNRequestParser.java 212(+0 -212)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLConditionsParser.java 174(+0 -174)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParser.java 129(+0 -129)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLRequestAbstractParser.java 109(+0 -109)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLResponseParser.java 108(+0 -108)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSloRequestParser.java 119(+0 -119)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSloResponseParser.java 78(+0 -78)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLStatusResponseTypeParser.java 187(+0 -187)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSubjectParser.java 206(+0 -206)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SecurityActions.java 94(+0 -94)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/SAML11Constants.java 131(+0 -131)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/BaseSAML11Writer.java 48(+0 -48)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11RequestWriter.java 171(+0 -171)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11ResponseWriter.java 137(+0 -137)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/common/IDGenerator.java 58(+0 -58)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/common/SAMLDocumentHolder.java 64(+0 -64)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/constants/X500SAMLProfileConstants.java 154(+0 -154)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java 217(+0 -217)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java 197(+0 -197)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SecurityActions.java 126(+0 -126)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/DestinationInfoHolder.java 56(+0 -56)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/IDPInfoHolder.java 78(+0 -78)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/IssuerInfoHolder.java 80(+0 -80)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/SignatureInfoHolder.java 45(+0 -45)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/SPInfoHolder.java 60(+0 -60)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/DocumentUtil.java 28(+0 -28)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java 101(+0 -101)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SecurityActions.java 161(+0 -161)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SignatureUtil.java 297(+0 -297)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StatementUtil.java 241(+0 -241)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StaxWriterUtil.java 166(+0 -166)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/XMLTimeUtil.java 254(+0 -254)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java 322(+0 -322)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java 289(+0 -289)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java 335(+0 -335)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java 264(+0 -264)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/CoreConfigUtil.java 208(+0 -208)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/EncryptionKeyUtil.java 50(+0 -50)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolver.java 224(+0 -224)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXPValidationUtil.java 168(+0 -168)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/NamespaceContext.java 96(+0 -96)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SchemaManagerUtil.java 106(+0 -106)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SecurityActions.java 225(+0 -225)
saml/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SignatureUtilTransferObject.java 115(+0 -115)
saml/saml-core/src/main/java/org/keycloak/saml/processing/web/util/RedirectBindingSignatureUtil.java 345(+0 -345)
saml/saml-core/src/main/java/org/keycloak/saml/processing/web/util/RedirectBindingUtil.java 219(+0 -219)
saml/saml-core/src/main/java/org/keycloak/saml/processing/web/util/SecurityActions.java 125(+0 -125)
saml-core/pom.xml 2(+1 -1)
saml-core/src/main/java/org/keycloak/dom/saml/v1/assertion/SAML11AttributeDesignatorType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/assertion/SAML11AttributeStatementType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/assertion/SAML11AudienceRestrictionCondition.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/assertion/SAML11AuthenticationStatementType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/assertion/SAML11AuthorizationDecisionStatementType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/assertion/SAML11ConditionAbstractType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/assertion/SAML11ConditionsAbstractType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/assertion/SAML11DoNotCacheConditionType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/assertion/SAML11StatementAbstractType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/assertion/SAML11SubjectConfirmationType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/protocol/SAML11AuthenticationQueryType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/protocol/SAML11AuthorizationDecisionQueryType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v1/protocol/SAML11SubjectQueryAbstractType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/AuthenticatorTransportProtocolType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/ActivationLimitDurationType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/ActivationLimitSessionType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/AuthenticatorTransportProtocolType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/AuthnContextDeclarationBaseType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/OriginalAuthenticatorBaseType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/OriginalAuthenticatorTransportProtocolType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/OriginalAuthnContextDeclarationBaseType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/OriginalAuthnMethodBaseType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/PrincipalAuthenticationMechanismType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/SharedSecretChallengeResponseType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/classes/TechnicalProtectionBaseType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/ac/PrincipalAuthenticationMechanismType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/assertion/KeyInfoConfirmationDataType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/assertion/SubjectConfirmationDataType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/metadata/AdditionalMetadataLocationType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/metadata/AttributeAuthorityDescriptorType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/metadata/AttributeConsumingServiceType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/metadata/AuthnAuthorityDescriptorType.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDMappingRequestType.java 135(+135 -0)
saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/RequestedAuthnContextType.java 135(+135 -0)
saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/CanonicalizationMethodType.java 67(+67 -0)
saml-core/src/main/java/org/keycloak/saml/common/constants/PicketLinkCommonConstants.java 30(+30 -0)
saml-core/src/main/java/org/keycloak/saml/common/constants/SAMLAuthenticationContextClass.java 63(+63 -0)
saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/AssertionExpiredException.java 53(+53 -0)
saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/IssueInstantMissingException.java 45(+45 -0)
saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/IssuerNotTrustedException.java 45(+45 -0)
saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/SignatureValidationException.java 44(+44 -0)
saml-core/src/main/java/org/keycloak/saml/common/exceptions/TrustKeyConfigurationException.java 43(+43 -0)
saml-core/src/main/java/org/keycloak/saml/common/exceptions/TrustKeyProcessingException.java 43(+43 -0)
saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java 336(+336 -0)
saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SecurityActions.java 166(+166 -0)
saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/response/SAML2Response.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/response/SecurityActions.java 122(+122 -0)
saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java 238(+238 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/constants/AttributeConstants.java 34(+34 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/constants/PicketLinkFederationConstants.java 53(+53 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/AbstractDescriptorParser.java 66(+66 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java 123(+123 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntityDescriptorParser.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11AssertionParser.java 178(+178 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11RequestParser.java 116(+116 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11ResponseParser.java 189(+189 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11SubjectParser.java 114(+114 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLArtifactResolveParser.java 90(+90 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLArtifactResponseParser.java 111(+111 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAssertionParser.java 174(+174 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAttributeQueryParser.java 92(+92 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAuthNRequestParser.java 212(+212 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLConditionsParser.java 174(+174 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLRequestAbstractParser.java 109(+109 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLResponseParser.java 108(+108 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSloRequestParser.java 119(+119 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSloResponseParser.java 78(+78 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLStatusResponseTypeParser.java 187(+187 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSubjectParser.java 206(+206 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SAML11ParserUtil.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SecurityActions.java 94(+94 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/BaseSAML11Writer.java 48(+48 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11AssertionWriter.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11RequestWriter.java 171(+171 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11ResponseWriter.java 137(+137 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/common/IDGenerator.java 58(+58 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/common/SAMLDocumentHolder.java 64(+64 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/constants/X500SAMLProfileConstants.java 154(+154 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java 217(+217 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java 197(+197 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SecurityActions.java 126(+126 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/DestinationInfoHolder.java 56(+56 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/IDPInfoHolder.java 78(+78 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/IssuerInfoHolder.java 80(+80 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/SignatureInfoHolder.java 45(+45 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/SPInfoHolder.java 60(+60 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java 101(+101 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SecurityActions.java 161(+161 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SignatureUtil.java 297(+297 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StatementUtil.java 241(+241 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StaxWriterUtil.java 166(+166 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/XMLTimeUtil.java 254(+254 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java 322(+322 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java 289(+289 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLMetadataWriter.java 0(+0 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java 335(+335 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java 264(+264 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolver.java 224(+224 -0)
saml-core/src/main/java/org/keycloak/saml/processing/core/util/SignatureUtilTransferObject.java 115(+115 -0)
Details
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index ee11349..a7cf76d 100755
--- a/pom.xml
+++ b/pom.xml
@@ -140,7 +140,7 @@
<module>core</module>
<module>dependencies</module>
<module>server-spi</module>
- <module>saml</module>
+ <module>saml-core</module>
<module>proxy</module>
<module>federation</module>
<module>services</module>
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/IDPListType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/IDPListType.java
new file mode 100755
index 0000000..fe1dbb8
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/IDPListType.java
@@ -0,0 +1,93 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for IDPListType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="IDPListType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}IDPEntry" maxOccurs="unbounded"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}GetComplete" minOccurs="0"/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class IDPListType {
+
+ protected List<IDPEntryType> idpEntry = new ArrayList<IDPEntryType>();
+ protected URI getComplete;
+
+ /**
+ * Add an idp entry
+ *
+ * @param entry
+ */
+ public void addIDPEntry(IDPEntryType entry) {
+ this.idpEntry.add(entry);
+ }
+
+ /**
+ * Remove an idp entry
+ *
+ * @param entry
+ */
+ public void removeIDPEntry(IDPEntryType entry) {
+ this.idpEntry.remove(entry);
+ }
+
+ /**
+ * Gets the value of the idpEntry property.
+ */
+ public List<IDPEntryType> getIDPEntry() {
+ return Collections.unmodifiableList(this.idpEntry);
+ }
+
+ /**
+ * Gets the value of the getComplete property.
+ *
+ * @return possible object is {@link String }
+ */
+ public URI getGetComplete() {
+ return getComplete;
+ }
+
+ /**
+ * Sets the value of the getComplete property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setGetComplete(URI value) {
+ this.getComplete = value;
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/LogoutRequestType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/LogoutRequestType.java
new file mode 100755
index 0000000..6db55a1
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/LogoutRequestType.java
@@ -0,0 +1,188 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import org.keycloak.dom.saml.v2.assertion.BaseIDAbstractType;
+import org.keycloak.dom.saml.v2.assertion.EncryptedElementType;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for LogoutRequestType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="LogoutRequestType">
+ * <complexContent>
+ * <extension base="{urn:oasis:names:tc:SAML:2.0:protocol}RequestAbstractType">
+ * <sequence>
+ * <choice>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}BaseID"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}NameID"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedID"/>
+ * </choice>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}SessionIndex" maxOccurs="unbounded" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="Reason" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * <attribute name="NotOnOrAfter" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class LogoutRequestType extends RequestAbstractType {
+
+ protected BaseIDAbstractType baseID;
+
+ protected NameIDType nameID;
+
+ protected EncryptedElementType encryptedID;
+
+ protected List<String> sessionIndex = new ArrayList<String>();
+
+ protected String reason;
+
+ protected XMLGregorianCalendar notOnOrAfter;
+
+ public LogoutRequestType(String id, XMLGregorianCalendar instant) {
+ super(id, instant);
+ }
+
+ /**
+ * Gets the value of the baseID property.
+ *
+ * @return possible object is {@link BaseIDAbstractType }
+ */
+ public BaseIDAbstractType getBaseID() {
+ return baseID;
+ }
+
+ /**
+ * Sets the value of the baseID property.
+ *
+ * @param value allowed object is {@link BaseIDAbstractType }
+ */
+ public void setBaseID(BaseIDAbstractType value) {
+ this.baseID = value;
+ }
+
+ /**
+ * Gets the value of the nameID property.
+ *
+ * @return possible object is {@link NameIDType }
+ */
+ public NameIDType getNameID() {
+ return nameID;
+ }
+
+ /**
+ * Sets the value of the nameID property.
+ *
+ * @param value allowed object is {@link NameIDType }
+ */
+ public void setNameID(NameIDType value) {
+ this.nameID = value;
+ }
+
+ /**
+ * Gets the value of the encryptedID property.
+ *
+ * @return possible object is {@link EncryptedElementType }
+ */
+ public EncryptedElementType getEncryptedID() {
+ return encryptedID;
+ }
+
+ /**
+ * Sets the value of the encryptedID property.
+ *
+ * @param value allowed object is {@link EncryptedElementType }
+ */
+ public void setEncryptedID(EncryptedElementType value) {
+ this.encryptedID = value;
+ }
+
+ /**
+ * Add session index
+ *
+ * @param index
+ */
+ public void addSessionIndex(String index) {
+ this.sessionIndex.add(index);
+ }
+
+ /**
+ * Remove session index
+ *
+ * @param index
+ */
+ public void removeSessionIndex(String index) {
+ this.sessionIndex.remove(index);
+ }
+
+ /**
+ * Gets the value of the sessionIndex property.
+ */
+ public List<String> getSessionIndex() {
+ return Collections.unmodifiableList(this.sessionIndex);
+ }
+
+ /**
+ * Gets the value of the reason property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getReason() {
+ return reason;
+ }
+
+ /**
+ * Sets the value of the reason property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setReason(String value) {
+ this.reason = value;
+ }
+
+ /**
+ * Gets the value of the notOnOrAfter property.
+ *
+ * @return possible object is {@link XMLGregorianCalendar }
+ */
+ public XMLGregorianCalendar getNotOnOrAfter() {
+ return notOnOrAfter;
+ }
+
+ /**
+ * Sets the value of the notOnOrAfter property.
+ *
+ * @param value allowed object is {@link XMLGregorianCalendar }
+ */
+ public void setNotOnOrAfter(XMLGregorianCalendar value) {
+ this.notOnOrAfter = value;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/ManageNameIDRequestType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/ManageNameIDRequestType.java
new file mode 100755
index 0000000..89952bb
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/ManageNameIDRequestType.java
@@ -0,0 +1,158 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import org.keycloak.dom.saml.v2.assertion.EncryptedElementType;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+/**
+ * <p>
+ * Java class for ManageNameIDRequestType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="ManageNameIDRequestType">
+ * <complexContent>
+ * <extension base="{urn:oasis:names:tc:SAML:2.0:protocol}RequestAbstractType">
+ * <sequence>
+ * <choice>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}NameID"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedID"/>
+ * </choice>
+ * <choice>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}NewID"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}NewEncryptedID"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}Terminate"/>
+ * </choice>
+ * </sequence>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class ManageNameIDRequestType extends RequestAbstractType {
+
+ protected NameIDType nameID;
+
+ protected EncryptedElementType encryptedID;
+
+ protected String newID;
+
+ protected EncryptedElementType newEncryptedID;
+
+ protected TerminateType terminate;
+
+ public ManageNameIDRequestType(String id, XMLGregorianCalendar instant) {
+ super(id, instant);
+ }
+
+ /**
+ * Gets the value of the nameID property.
+ *
+ * @return possible object is {@link NameIDType }
+ */
+ public NameIDType getNameID() {
+ return nameID;
+ }
+
+ /**
+ * Sets the value of the nameID property.
+ *
+ * @param value allowed object is {@link NameIDType }
+ */
+ public void setNameID(NameIDType value) {
+ this.nameID = value;
+ }
+
+ /**
+ * Gets the value of the encryptedID property.
+ *
+ * @return possible object is {@link EncryptedElementType }
+ */
+ public EncryptedElementType getEncryptedID() {
+ return encryptedID;
+ }
+
+ /**
+ * Sets the value of the encryptedID property.
+ *
+ * @param value allowed object is {@link EncryptedElementType }
+ */
+ public void setEncryptedID(EncryptedElementType value) {
+ this.encryptedID = value;
+ }
+
+ /**
+ * Gets the value of the newID property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getNewID() {
+ return newID;
+ }
+
+ /**
+ * Sets the value of the newID property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setNewID(String value) {
+ this.newID = value;
+ }
+
+ /**
+ * Gets the value of the newEncryptedID property.
+ *
+ * @return possible object is {@link EncryptedElementType }
+ */
+ public EncryptedElementType getNewEncryptedID() {
+ return newEncryptedID;
+ }
+
+ /**
+ * Sets the value of the newEncryptedID property.
+ *
+ * @param value allowed object is {@link EncryptedElementType }
+ */
+ public void setNewEncryptedID(EncryptedElementType value) {
+ this.newEncryptedID = value;
+ }
+
+ /**
+ * Gets the value of the terminate property.
+ *
+ * @return possible object is {@link TerminateType }
+ */
+ public TerminateType getTerminate() {
+ return terminate;
+ }
+
+ /**
+ * Sets the value of the terminate property.
+ *
+ * @param value allowed object is {@link TerminateType }
+ */
+ public void setTerminate(TerminateType value) {
+ this.terminate = value;
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDMappingRequestType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDMappingRequestType.java
new file mode 100755
index 0000000..bd5fe43
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDMappingRequestType.java
@@ -0,0 +1,135 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import org.keycloak.dom.saml.v2.assertion.BaseIDAbstractType;
+import org.keycloak.dom.saml.v2.assertion.EncryptedElementType;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+/**
+ * <p>
+ * Java class for NameIDMappingRequestType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="NameIDMappingRequestType">
+ * <complexContent>
+ * <extension base="{urn:oasis:names:tc:SAML:2.0:protocol}RequestAbstractType">
+ * <sequence>
+ * <choice>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}BaseID"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}NameID"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedID"/>
+ * </choice>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}NameIDPolicy"/>
+ * </sequence>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class NameIDMappingRequestType extends RequestAbstractType {
+
+ protected BaseIDAbstractType baseID;
+
+ protected NameIDType nameID;
+
+ protected EncryptedElementType encryptedID;
+
+ protected NameIDPolicyType nameIDPolicy;
+
+ public NameIDMappingRequestType(String id, XMLGregorianCalendar instant) {
+ super(id, instant);
+ }
+
+ /**
+ * Gets the value of the baseID property.
+ *
+ * @return possible object is {@link BaseIDAbstractType }
+ */
+ public BaseIDAbstractType getBaseID() {
+ return baseID;
+ }
+
+ /**
+ * Sets the value of the baseID property.
+ *
+ * @param value allowed object is {@link BaseIDAbstractType }
+ */
+ public void setBaseID(BaseIDAbstractType value) {
+ this.baseID = value;
+ }
+
+ /**
+ * Gets the value of the nameID property.
+ *
+ * @return possible object is {@link NameIDType }
+ */
+ public NameIDType getNameID() {
+ return nameID;
+ }
+
+ /**
+ * Sets the value of the nameID property.
+ *
+ * @param value allowed object is {@link NameIDType }
+ */
+ public void setNameID(NameIDType value) {
+ this.nameID = value;
+ }
+
+ /**
+ * Gets the value of the encryptedID property.
+ *
+ * @return possible object is {@link EncryptedElementType }
+ */
+ public EncryptedElementType getEncryptedID() {
+ return encryptedID;
+ }
+
+ /**
+ * Sets the value of the encryptedID property.
+ *
+ * @param value allowed object is {@link EncryptedElementType }
+ */
+ public void setEncryptedID(EncryptedElementType value) {
+ this.encryptedID = value;
+ }
+
+ /**
+ * Gets the value of the nameIDPolicy property.
+ *
+ * @return possible object is {@link NameIDPolicyType }
+ */
+ public NameIDPolicyType getNameIDPolicy() {
+ return nameIDPolicy;
+ }
+
+ /**
+ * Sets the value of the nameIDPolicy property.
+ *
+ * @param value allowed object is {@link NameIDPolicyType }
+ */
+ public void setNameIDPolicy(NameIDPolicyType value) {
+ this.nameIDPolicy = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDMappingResponseType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDMappingResponseType.java
new file mode 100755
index 0000000..dedc8ff
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDMappingResponseType.java
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import org.keycloak.dom.saml.v2.assertion.EncryptedElementType;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+/**
+ * <p>
+ * Java class for NameIDMappingResponseType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="NameIDMappingResponseType">
+ * <complexContent>
+ * <extension base="{urn:oasis:names:tc:SAML:2.0:protocol}StatusResponseType">
+ * <choice>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}NameID"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedID"/>
+ * </choice>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class NameIDMappingResponseType extends StatusResponseType {
+
+ protected NameIDType nameID;
+
+ protected EncryptedElementType encryptedID;
+
+ public NameIDMappingResponseType(String id, XMLGregorianCalendar issueInstant) {
+ super(id, issueInstant);
+ }
+
+ /**
+ * Gets the value of the nameID property.
+ *
+ * @return possible object is {@link NameIDType }
+ */
+ public NameIDType getNameID() {
+ return nameID;
+ }
+
+ /**
+ * Sets the value of the nameID property.
+ *
+ * @param value allowed object is {@link NameIDType }
+ */
+ public void setNameID(NameIDType value) {
+ this.nameID = value;
+ }
+
+ /**
+ * Gets the value of the encryptedID property.
+ *
+ * @return possible object is {@link EncryptedElementType }
+ */
+ public EncryptedElementType getEncryptedID() {
+ return encryptedID;
+ }
+
+ /**
+ * Sets the value of the encryptedID property.
+ *
+ * @param value allowed object is {@link EncryptedElementType }
+ */
+ public void setEncryptedID(EncryptedElementType value) {
+ this.encryptedID = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDPolicyType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDPolicyType.java
new file mode 100755
index 0000000..6383108
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/NameIDPolicyType.java
@@ -0,0 +1,100 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import java.net.URI;
+
+/**
+ * <p>
+ * Java class for NameIDPolicyType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="NameIDPolicyType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <attribute name="Format" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * <attribute name="SPNameQualifier" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * <attribute name="AllowCreate" type="{http://www.w3.org/2001/XMLSchema}boolean" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class NameIDPolicyType {
+
+ protected URI format;
+ protected String spNameQualifier;
+ protected Boolean allowCreate = Boolean.FALSE;
+
+ /**
+ * Gets the value of the format property.
+ *
+ * @return possible object is {@link String }
+ */
+ public URI getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the value of the format property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setFormat(URI value) {
+ this.format = value;
+ }
+
+ /**
+ * Gets the value of the spNameQualifier property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getSPNameQualifier() {
+ return spNameQualifier;
+ }
+
+ /**
+ * Sets the value of the spNameQualifier property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setSPNameQualifier(String value) {
+ this.spNameQualifier = value;
+ }
+
+ /**
+ * Gets the value of the allowCreate property.
+ *
+ * @return possible object is {@link Boolean }
+ */
+ public Boolean isAllowCreate() {
+ return allowCreate;
+ }
+
+ /**
+ * Sets the value of the allowCreate property.
+ *
+ * @param value allowed object is {@link Boolean }
+ */
+ public void setAllowCreate(Boolean value) {
+ this.allowCreate = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/RequestAbstractType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/RequestAbstractType.java
new file mode 100755
index 0000000..c670169
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/RequestAbstractType.java
@@ -0,0 +1,149 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import org.keycloak.dom.saml.common.CommonRequestAbstractType;
+import org.keycloak.dom.saml.v2.SAML2Object;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.net.URI;
+
+/**
+ * <p>
+ * Java class for RequestAbstractType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="RequestAbstractType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}Issuer" minOccurs="0"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}Signature" minOccurs="0"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}Extensions" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="ID" use="required" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * <attribute name="Version" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * <attribute name="IssueInstant" use="required" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ * <attribute name="Destination" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * <attribute name="Consent" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public abstract class RequestAbstractType extends CommonRequestAbstractType implements SAML2Object {
+
+ protected NameIDType issuer;
+
+ protected ExtensionsType extensions;
+
+ protected String version = "2.0";
+
+ protected URI destination;
+
+ protected String consent;
+
+ public RequestAbstractType(String id, XMLGregorianCalendar instant) {
+ super(id, instant);
+ }
+
+ /**
+ * Gets the value of the issuer property.
+ *
+ * @return possible object is {@link NameIDType }
+ */
+ public NameIDType getIssuer() {
+ return issuer;
+ }
+
+ /**
+ * Sets the value of the issuer property.
+ *
+ * @param value allowed object is {@link NameIDType }
+ */
+ public void setIssuer(NameIDType value) {
+ this.issuer = value;
+ }
+
+ /**
+ * Gets the value of the extensions property.
+ *
+ * @return possible object is {@link ExtensionsType }
+ */
+ public ExtensionsType getExtensions() {
+ return extensions;
+ }
+
+ /**
+ * Sets the value of the extensions property.
+ *
+ * @param value allowed object is {@link ExtensionsType }
+ */
+ public void setExtensions(ExtensionsType value) {
+ this.extensions = value;
+ }
+
+ /**
+ * Gets the value of the version property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * Gets the value of the destination property.
+ *
+ * @return possible object is {@link String }
+ */
+ public URI getDestination() {
+ return destination;
+ }
+
+ /**
+ * Sets the value of the destination property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setDestination(URI value) {
+ this.destination = value;
+ }
+
+ /**
+ * Gets the value of the consent property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getConsent() {
+ return consent;
+ }
+
+ /**
+ * Sets the value of the consent property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setConsent(String value) {
+ this.consent = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/RequestedAuthnContextType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/RequestedAuthnContextType.java
new file mode 100755
index 0000000..0aea25e
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/RequestedAuthnContextType.java
@@ -0,0 +1,135 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for RequestedAuthnContextType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="RequestedAuthnContextType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}AuthnContextClassRef" maxOccurs="unbounded"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}AuthnContextDeclRef" maxOccurs="unbounded"/>
+ * </choice>
+ * <attribute name="Comparison" type="{urn:oasis:names:tc:SAML:2.0:protocol}AuthnContextComparisonType" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class RequestedAuthnContextType {
+
+ protected List<String> authnContextClassRef = new ArrayList<String>();
+ protected List<String> authnContextDeclRef = new ArrayList<String>();
+ protected AuthnContextComparisonType comparison;
+
+ /**
+ * Add an authn Context class ref
+ *
+ * @param str
+ */
+ public void addAuthnContextClassRef(String str) {
+ this.authnContextClassRef.add(str);
+ }
+
+ /**
+ * Add authn context decl ref
+ *
+ * @param str
+ */
+ public void addAuthnContextDeclRef(String str) {
+ this.authnContextDeclRef.add(str);
+ }
+
+ /**
+ * Remove an authn Context class ref
+ *
+ * @param str
+ */
+ public void removeAuthnContextClassRef(String str) {
+ this.authnContextClassRef.remove(str);
+ }
+
+ /**
+ * remove authn context decl ref
+ *
+ * @param str
+ */
+ public void removeAuthnContextDeclRef(String str) {
+ this.authnContextDeclRef.remove(str);
+ }
+
+ /**
+ * Gets the value of the authnContextClassRef property.
+ */
+ public List<String> getAuthnContextClassRef() {
+ return Collections.unmodifiableList(this.authnContextClassRef);
+ }
+
+ /**
+ * Gets the value of the authnContextDeclRef property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make to
+ * the
+ * returned list will be present inside the JAXB object. This is why there is not a <CODE>set</CODE> method for the
+ * authnContextDeclRef property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ *
+ * <pre>
+ * getAuthnContextDeclRef().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link String }
+ */
+ public List<String> getAuthnContextDeclRef() {
+ return Collections.unmodifiableList(this.authnContextDeclRef);
+ }
+
+ /**
+ * Gets the value of the comparison property.
+ *
+ * @return possible object is {@link AuthnContextComparisonType }
+ */
+ public AuthnContextComparisonType getComparison() {
+ return comparison;
+ }
+
+ /**
+ * Sets the value of the comparison property.
+ *
+ * @param value allowed object is {@link AuthnContextComparisonType }
+ */
+ public void setComparison(AuthnContextComparisonType value) {
+ this.comparison = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/ResponseType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/ResponseType.java
new file mode 100755
index 0000000..fec0f13
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/ResponseType.java
@@ -0,0 +1,135 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for ResponseType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="ResponseType">
+ * <complexContent>
+ * <extension base="{urn:oasis:names:tc:SAML:2.0:protocol}StatusResponseType">
+ * <choice maxOccurs="unbounded" minOccurs="0">
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}Assertion"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedAssertion"/>
+ * </choice>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class ResponseType extends StatusResponseType {
+
+ protected List<RTChoiceType> assertions = new ArrayList<ResponseType.RTChoiceType>();
+
+ public ResponseType(String id, XMLGregorianCalendar issueInstant) {
+ super(id, issueInstant);
+ }
+
+ public ResponseType(StatusResponseType srt) {
+ super(srt);
+ }
+
+ /**
+ * Add an assertion
+ *
+ * @param choice
+ */
+ public void addAssertion(RTChoiceType choice) {
+ assertions.add(choice);
+ }
+
+ /**
+ * Remove an assertion
+ *
+ * @param choice
+ */
+ public void removeAssertion(RTChoiceType choice) {
+ assertions.remove(choice);
+ }
+
+ /**
+ * Replace the first assertion with the passed assertion
+ *
+ * @param id id of the old assertion
+ * @param newAssertion
+ */
+ public void replaceAssertion(String id, RTChoiceType newAssertion) {
+ int index = 0;
+ if (id != null && !id.isEmpty()) {
+ for (RTChoiceType assertion : assertions) {
+ if (assertion.getID().equals(id)) {
+ break;
+ }
+ index++;
+ }
+ }
+ assertions.remove(index);
+ assertions.add(index, newAssertion);
+ }
+
+ /**
+ * Gets a read only list of assertions
+ */
+ public List<RTChoiceType> getAssertions() {
+ return Collections.unmodifiableList(assertions);
+ }
+
+ public static class RTChoiceType {
+
+ private AssertionType assertion;
+
+ private EncryptedAssertionType encryptedAssertion;
+
+ private String id;
+
+ public RTChoiceType(AssertionType assertion) {
+ this.assertion = assertion;
+ this.id = assertion.getID();
+ }
+
+ public RTChoiceType(EncryptedAssertionType encryptedAssertion) {
+ this.encryptedAssertion = encryptedAssertion;
+
+ }
+
+ public AssertionType getAssertion() {
+ return assertion;
+ }
+
+ public EncryptedAssertionType getEncryptedAssertion() {
+ return encryptedAssertion;
+ }
+
+ public String getID() {
+ return id;
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/ScopingType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/ScopingType.java
new file mode 100755
index 0000000..bcd8060
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/ScopingType.java
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import java.math.BigInteger;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for ScopingType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="ScopingType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}IDPList" minOccurs="0"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}RequesterID" maxOccurs="unbounded" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="ProxyCount" type="{http://www.w3.org/2001/XMLSchema}nonNegativeInteger" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class ScopingType {
+
+ protected IDPListType idpList;
+ protected List<URI> requesterID = new ArrayList<URI>();
+
+ protected BigInteger proxyCount;
+
+ /**
+ * Gets the value of the idpList property.
+ *
+ * @return possible object is {@link IDPListType }
+ */
+ public IDPListType getIDPList() {
+ return idpList;
+ }
+
+ /**
+ * Sets the value of the idpList property.
+ *
+ * @param value allowed object is {@link IDPListType }
+ */
+ public void setIDPList(IDPListType value) {
+ this.idpList = value;
+ }
+
+ /**
+ * Gets the value of the requesterID property.
+ * <p>
+ * For example, to add a new item, do as follows:
+ *
+ * <pre>
+ * getRequesterID().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link String }
+ */
+ public List<URI> getRequesterID() {
+ return Collections.unmodifiableList(this.requesterID);
+ }
+
+ /**
+ * Add requester id
+ *
+ * @param uri
+ */
+ public void addRequesterID(URI uri) {
+ this.requesterID.add(uri);
+ }
+
+ /**
+ * Remove requester id
+ *
+ * @param uri
+ */
+ public void removeRequesterID(URI uri) {
+ this.requesterID.remove(uri);
+ }
+
+ /**
+ * Gets the value of the proxyCount property.
+ *
+ * @return possible object is {@link BigInteger }
+ */
+ public BigInteger getProxyCount() {
+ return proxyCount;
+ }
+
+ /**
+ * Sets the value of the proxyCount property.
+ *
+ * @param value allowed object is {@link BigInteger }
+ */
+ public void setProxyCount(BigInteger value) {
+ this.proxyCount = value;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/StatusCodeType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/StatusCodeType.java
new file mode 100755
index 0000000..826928a
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/StatusCodeType.java
@@ -0,0 +1,89 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import java.io.Serializable;
+import java.net.URI;
+
+/**
+ * <p>
+ * Java class for StatusCodeType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="StatusCodeType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}StatusCode" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="Value" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class StatusCodeType implements Serializable {
+
+ protected StatusCodeType statusCode;
+ protected URI value;
+
+ /**
+ * Gets the value of the statusCode property.
+ *
+ * @return possible object is {@link StatusCodeType }
+ */
+ public StatusCodeType getStatusCode() {
+ return statusCode;
+ }
+
+ /**
+ * Sets the value of the statusCode property.
+ *
+ * @param value allowed object is {@link StatusCodeType }
+ */
+ public void setStatusCode(StatusCodeType value) {
+ this.statusCode = value;
+ }
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return possible object is {@link String }
+ */
+ public URI getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setValue(URI value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "StatusCodeType [value=" + value + ", statusCode=" + statusCode + "]";
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/StatusResponseType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/StatusResponseType.java
new file mode 100755
index 0000000..12235b3
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/StatusResponseType.java
@@ -0,0 +1,185 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import org.keycloak.dom.saml.common.CommonResponseType;
+import org.keycloak.dom.saml.v2.SAML2Object;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+/**
+ * <p>
+ * Java class for StatusResponseType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="StatusResponseType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}Issuer" minOccurs="0"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}Signature" minOccurs="0"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}Extensions" minOccurs="0"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}Status"/>
+ * </sequence>
+ * <attribute name="ID" use="required" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * <attribute name="InResponseTo" type="{http://www.w3.org/2001/XMLSchema}NCName" />
+ * <attribute name="Version" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * <attribute name="IssueInstant" use="required" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ * <attribute name="Destination" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * <attribute name="Consent" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class StatusResponseType extends CommonResponseType implements SAML2Object {
+
+ protected NameIDType issuer;
+
+ protected ExtensionsType extensions;
+
+ protected StatusType status;
+
+ protected String id;
+
+ protected String version = "2.0";
+
+ protected XMLGregorianCalendar issueInstant;
+
+ protected String destination;
+
+ protected String consent;
+
+ public StatusResponseType(String id, XMLGregorianCalendar issueInstant) {
+ super(id, issueInstant);
+ }
+
+ public StatusResponseType(StatusResponseType srt) {
+ this(srt.getID(), srt.getIssueInstant());
+ this.issuer = srt.getIssuer();
+ this.signature = srt.getSignature();
+ this.extensions = srt.getExtensions();
+ this.status = srt.getStatus();
+ this.inResponseTo = srt.getInResponseTo();
+ this.destination = srt.getDestination();
+ this.consent = srt.getConsent();
+ }
+
+ /**
+ * Gets the value of the issuer property.
+ *
+ * @return possible object is {@link NameIDType }
+ */
+ public NameIDType getIssuer() {
+ return issuer;
+ }
+
+ /**
+ * Sets the value of the issuer property.
+ *
+ * @param value allowed object is {@link NameIDType }
+ */
+ public void setIssuer(NameIDType value) {
+ this.issuer = value;
+ }
+
+ /**
+ * Gets the value of the extensions property.
+ *
+ * @return possible object is {@link ExtensionsType }
+ */
+ public ExtensionsType getExtensions() {
+ return extensions;
+ }
+
+ /**
+ * Sets the value of the extensions property.
+ *
+ * @param value allowed object is {@link ExtensionsType }
+ */
+ public void setExtensions(ExtensionsType value) {
+ this.extensions = value;
+ }
+
+ /**
+ * Gets the value of the status property.
+ *
+ * @return possible object is {@link StatusType }
+ */
+ public StatusType getStatus() {
+ return status;
+ }
+
+ /**
+ * Sets the value of the status property.
+ *
+ * @param value allowed object is {@link StatusType }
+ */
+ public void setStatus(StatusType value) {
+ this.status = value;
+ }
+
+ /**
+ * Gets the value of the version property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * Gets the value of the destination property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getDestination() {
+ return destination;
+ }
+
+ /**
+ * Sets the value of the destination property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setDestination(String value) {
+ this.destination = value;
+ }
+
+ /**
+ * Gets the value of the consent property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getConsent() {
+ return consent;
+ }
+
+ /**
+ * Sets the value of the consent property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setConsent(String value) {
+ this.consent = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/StatusType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/StatusType.java
new file mode 100755
index 0000000..ec92dd4
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/StatusType.java
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * Java class for StatusType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="StatusType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}StatusCode"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}StatusMessage" minOccurs="0"/>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:protocol}StatusDetail" minOccurs="0"/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class StatusType implements Serializable {
+
+ protected String statusMessage;
+ protected StatusCodeType statusCode;
+ protected StatusDetailType statusDetail;
+
+ /**
+ * Gets the value of the statusCode property.
+ *
+ * @return possible object is {@link StatusCodeType }
+ */
+ public StatusCodeType getStatusCode() {
+ return statusCode;
+ }
+
+ /**
+ * Sets the value of the statusCode property.
+ *
+ * @param value allowed object is {@link StatusCodeType }
+ */
+ public void setStatusCode(StatusCodeType value) {
+ this.statusCode = value;
+ }
+
+ /**
+ * Gets the value of the statusMessage property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getStatusMessage() {
+ return statusMessage;
+ }
+
+ /**
+ * Sets the value of the statusMessage property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setStatusMessage(String value) {
+ this.statusMessage = value;
+ }
+
+ /**
+ * Gets the value of the statusDetail property.
+ *
+ * @return possible object is {@link StatusDetailType }
+ */
+ public StatusDetailType getStatusDetail() {
+ return statusDetail;
+ }
+
+ /**
+ * Sets the value of the statusDetail property.
+ *
+ * @param value allowed object is {@link StatusDetailType }
+ */
+ public void setStatusDetail(StatusDetailType value) {
+ this.statusDetail = value;
+ }
+
+ @Override
+ public String toString() {
+ return "StatusType [statusCode=" + statusCode + ", statusMessage=" + statusMessage + ", statusDetail=" + statusDetail + "]";
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/SubjectQueryAbstractType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/SubjectQueryAbstractType.java
new file mode 100755
index 0000000..857e3e7
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/SubjectQueryAbstractType.java
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+import org.keycloak.dom.saml.v2.assertion.SubjectType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+/**
+ * <p>
+ * Java class for SubjectQueryAbstractType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="SubjectQueryAbstractType">
+ * <complexContent>
+ * <extension base="{urn:oasis:names:tc:SAML:2.0:protocol}RequestAbstractType">
+ * <sequence>
+ * <element ref="{urn:oasis:names:tc:SAML:2.0:assertion}Subject"/>
+ * </sequence>
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public abstract class SubjectQueryAbstractType extends RequestAbstractType {
+
+ protected SubjectType subject;
+
+ public SubjectQueryAbstractType(String id, XMLGregorianCalendar instant) {
+ super(id, instant);
+ }
+
+ public void setSubject(SubjectType subject) {
+ this.subject = subject;
+ }
+
+ /**
+ * Gets the value of the subject property.
+ *
+ * @return possible object is {@link SubjectType }
+ */
+ public SubjectType getSubject() {
+ return subject;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/TerminateType.java b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/TerminateType.java
new file mode 100755
index 0000000..8a3890e
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/saml/v2/protocol/TerminateType.java
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.saml.v2.protocol;
+
+/**
+ * <p>
+ * Java class for TerminateType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="TerminateType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class TerminateType {
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/CanonicalizationMethodType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/CanonicalizationMethodType.java
new file mode 100755
index 0000000..6529ae0
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/CanonicalizationMethodType.java
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.net.URI;
+
+/**
+ * <p>
+ * Java class for CanonicalizationMethodType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="CanonicalizationMethodType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <any/>
+ * </sequence>
+ * <attribute name="Algorithm" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class CanonicalizationMethodType {
+
+ protected URI algorithm;
+ private Object content;
+
+ public CanonicalizationMethodType(URI algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ public void setContent(Object content) {
+ this.content = content;
+ }
+
+ public Object getContent() {
+ return this.content;
+ }
+
+ /**
+ * Gets the value of the algorithm property.
+ *
+ * @return possible object is {@link String }
+ */
+ public URI getAlgorithm() {
+ return algorithm;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/DigestMethodType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/DigestMethodType.java
new file mode 100755
index 0000000..1e8cb42
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/DigestMethodType.java
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.net.URI;
+
+/**
+ * <p>
+ * Java class for DigestMethodType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="DigestMethodType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <any/>
+ * </sequence>
+ * <attribute name="Algorithm" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class DigestMethodType {
+
+ protected URI algorithm;
+ private Object content;
+
+ public DigestMethodType(URI algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ public void setContent(Object content) {
+ this.content = content;
+ }
+
+ public Object getContent() {
+ return this.content;
+ }
+
+ /**
+ * Gets the value of the algorithm property.
+ *
+ * @return possible object is {@link URI }
+ */
+ public URI getAlgorithm() {
+ return algorithm;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/KeyInfoType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/KeyInfoType.java
new file mode 100755
index 0000000..d764fef
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/KeyInfoType.java
@@ -0,0 +1,86 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for KeyInfoType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="KeyInfoType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice maxOccurs="unbounded">
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}KeyName"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}KeyValue"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}RetrievalMethod"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}X509Data"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}PGPData"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}SPKIData"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}MgmtData"/>
+ * <any/>
+ * </choice>
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class KeyInfoType {
+
+ protected String id;
+
+ protected List<Object> contentList = new ArrayList<Object>();
+
+ public void addContent(Object content) {
+ this.contentList.add(content);
+ }
+
+ public void removeContent(Object content) {
+ this.contentList.remove(content);
+ }
+
+ public List<Object> getContent() {
+ return Collections.unmodifiableList(contentList);
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/KeyValueType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/KeyValueType.java
new file mode 100755
index 0000000..fdef5a5
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/KeyValueType.java
@@ -0,0 +1,44 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+
+/**
+ * <p>
+ * Java class for KeyValueType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="KeyValueType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}DSAKeyValue"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}RSAKeyValue"/>
+ * <any/>
+ * </choice>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public interface KeyValueType {
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/ManifestType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/ManifestType.java
new file mode 100755
index 0000000..f7040b9
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/ManifestType.java
@@ -0,0 +1,84 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for ManifestType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="ManifestType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}Reference" maxOccurs="unbounded"/>
+ * </sequence>
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class ManifestType {
+
+ protected List<ReferenceType> reference = new ArrayList<ReferenceType>();
+ protected String id;
+
+ public void addReference(ReferenceType ref) {
+ this.reference.add(ref);
+ }
+
+ public void removeReference(ReferenceType ref) {
+ this.reference.remove(ref);
+ }
+
+ /**
+ * Gets the value of the reference property.
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link ReferenceType }
+ */
+ public List<ReferenceType> getReference() {
+ return Collections.unmodifiableList(this.reference);
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/ObjectType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/ObjectType.java
new file mode 100755
index 0000000..e60ffd0
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/ObjectType.java
@@ -0,0 +1,123 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for ObjectType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="ObjectType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence maxOccurs="unbounded" minOccurs="0">
+ * <any/>
+ * </sequence>
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * <attribute name="MimeType" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * <attribute name="Encoding" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class ObjectType {
+
+ protected List<Object> content = new ArrayList<Object>();
+ protected String id;
+ protected String mimeType;
+ protected String encoding;
+
+ public void add(Object obj) {
+ this.content.add(obj);
+ }
+
+ public void remove(Object obj) {
+ this.content.remove(obj);
+ }
+
+ /**
+ * Gets the value of the content property.
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link org.w3c.dom.Element } {@link Object } {@link String }
+ */
+ public List<Object> getContent() {
+ return Collections.unmodifiableList(this.content);
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+
+ /**
+ * Gets the value of the mimeType property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ /**
+ * Sets the value of the mimeType property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setMimeType(String value) {
+ this.mimeType = value;
+ }
+
+ /**
+ * Gets the value of the encoding property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getEncoding() {
+ return encoding;
+ }
+
+ /**
+ * Sets the value of the encoding property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setEncoding(String value) {
+ this.encoding = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/package-info.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/package-info.java
new file mode 100755
index 0000000..73e4e41
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/PGPDataType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/PGPDataType.java
new file mode 100755
index 0000000..89084aa
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/PGPDataType.java
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for PGPDataType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="PGPDataType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice>
+ * <sequence>
+ * <element name="PGPKeyID" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ * <element name="PGPKeyPacket" type="{http://www.w3.org/2001/XMLSchema}base64Binary" minOccurs="0"/>
+ * <any/>
+ * </sequence>
+ * <sequence>
+ * <element name="PGPKeyPacket" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ * <any/>
+ * </sequence>
+ * </choice>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class PGPDataType {
+
+ protected List<Object> content = new ArrayList<Object>();
+
+ public void add(Object obj) {
+ this.content.add(obj);
+ }
+
+ public void remove(Object obj) {
+ this.content.remove(obj);
+ }
+
+ /**
+ * Gets the value of the content property.
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link org.w3c.dom.Element } {@link Object } {@link String }
+ */
+ public List<Object> getContent() {
+ return Collections.unmodifiableList(this.content);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/ReferenceType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/ReferenceType.java
new file mode 100755
index 0000000..ea95b05
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/ReferenceType.java
@@ -0,0 +1,160 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+/**
+ * <p>
+ * Java class for ReferenceType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="ReferenceType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}Transforms" minOccurs="0"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}DigestMethod"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}DigestValue"/>
+ * </sequence>
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * <attribute name="URI" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * <attribute name="Type" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class ReferenceType {
+
+ protected TransformsType transforms;
+ protected DigestMethodType digestMethod;
+ protected byte[] digestValue;
+ protected String id;
+ protected String uri;
+ protected String type;
+
+ /**
+ * Gets the value of the transforms property.
+ *
+ * @return possible object is {@link TransformsType }
+ */
+ public TransformsType getTransforms() {
+ return transforms;
+ }
+
+ /**
+ * Sets the value of the transforms property.
+ *
+ * @param value allowed object is {@link TransformsType }
+ */
+ public void setTransforms(TransformsType value) {
+ this.transforms = value;
+ }
+
+ /**
+ * Gets the value of the digestMethod property.
+ *
+ * @return possible object is {@link DigestMethodType }
+ */
+ public DigestMethodType getDigestMethod() {
+ return digestMethod;
+ }
+
+ /**
+ * Sets the value of the digestMethod property.
+ *
+ * @param value allowed object is {@link DigestMethodType }
+ */
+ public void setDigestMethod(DigestMethodType value) {
+ this.digestMethod = value;
+ }
+
+ /**
+ * Gets the value of the digestValue property.
+ *
+ * @return possible object is byte[]
+ */
+ public byte[] getDigestValue() {
+ return digestValue;
+ }
+
+ /**
+ * Sets the value of the digestValue property.
+ *
+ * @param value allowed object is byte[]
+ */
+ public void setDigestValue(byte[] value) {
+ this.digestValue = ((byte[]) value);
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+
+ /**
+ * Gets the value of the uri property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getURI() {
+ return uri;
+ }
+
+ /**
+ * Sets the value of the uri property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setURI(String value) {
+ this.uri = value;
+ }
+
+ /**
+ * Gets the value of the type property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Sets the value of the type property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setType(String value) {
+ this.type = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/RetrievalMethodType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/RetrievalMethodType.java
new file mode 100755
index 0000000..32c6974
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/RetrievalMethodType.java
@@ -0,0 +1,101 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+/**
+ * <p>
+ * Java class for RetrievalMethodType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="RetrievalMethodType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}Transforms" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="URI" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * <attribute name="Type" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class RetrievalMethodType {
+
+ protected TransformsType transforms;
+ protected String uri;
+ protected String type;
+
+ /**
+ * Gets the value of the transforms property.
+ *
+ * @return possible object is {@link TransformsType }
+ */
+ public TransformsType getTransforms() {
+ return transforms;
+ }
+
+ /**
+ * Sets the value of the transforms property.
+ *
+ * @param value allowed object is {@link TransformsType }
+ */
+ public void setTransforms(TransformsType value) {
+ this.transforms = value;
+ }
+
+ /**
+ * Gets the value of the uri property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getURI() {
+ return uri;
+ }
+
+ /**
+ * Sets the value of the uri property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setURI(String value) {
+ this.uri = value;
+ }
+
+ /**
+ * Gets the value of the type property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Sets the value of the type property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setType(String value) {
+ this.type = value;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/RSAKeyValueType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/RSAKeyValueType.java
new file mode 100755
index 0000000..0ded3fd
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/RSAKeyValueType.java
@@ -0,0 +1,164 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import org.keycloak.saml.common.constants.WSTrustConstants;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.Base64;
+
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.RSAPrivateKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+
+/**
+ * <p>
+ * Java class for RSAKeyValueType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="RSAKeyValueType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element name="Modulus" type="{http://www.w3.org/2000/09/xmldsig#}CryptoBinary"/>
+ * <element name="Exponent" type="{http://www.w3.org/2000/09/xmldsig#}CryptoBinary"/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class RSAKeyValueType implements KeyValueType {
+
+ protected byte[] modulus;
+ protected byte[] exponent;
+
+ /**
+ * Gets the value of the modulus property.
+ *
+ * @return possible object is byte[]
+ */
+ public byte[] getModulus() {
+ return modulus;
+ }
+
+ /**
+ * Sets the value of the modulus property.
+ *
+ * @param value allowed object is byte[]
+ */
+ public void setModulus(byte[] value) {
+ this.modulus = ((byte[]) value);
+ }
+
+ /**
+ * Gets the value of the exponent property.
+ *
+ * @return possible object is byte[]
+ */
+ public byte[] getExponent() {
+ return exponent;
+ }
+
+ /**
+ * Sets the value of the exponent property.
+ *
+ * @param value allowed object is byte[]
+ */
+ public void setExponent(byte[] value) {
+ this.exponent = ((byte[]) value);
+ }
+
+ /**
+ * Convert to the JDK representation of a RSA Public Key
+ *
+ * @return
+ *
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ */
+ public RSAPublicKey convertToPublicKey() throws ProcessingException {
+ BigInteger bigModulus = new BigInteger(1, massage(Base64.decode(new String(modulus))));
+ BigInteger bigEx = new BigInteger(1, massage(Base64.decode(new String(exponent))));
+
+ try {
+ KeyFactory rsaKeyFactory = KeyFactory.getInstance("rsa");
+ RSAPublicKeySpec kspec = new RSAPublicKeySpec(bigModulus, bigEx);
+ return (RSAPublicKey) rsaKeyFactory.generatePublic(kspec);
+ } catch (Exception e) {
+ throw new ProcessingException(e);
+ }
+ }
+
+ /**
+ * Convert to the JDK representation of a RSA Private Key
+ *
+ * @return
+ *
+ * @throws ProcessingException
+ */
+ public RSAPrivateKey convertToPrivateKey() throws ProcessingException {
+ BigInteger bigModulus = new BigInteger(1, massage(Base64.decode(new String(modulus))));
+ BigInteger bigEx = new BigInteger(1, massage(Base64.decode(new String(exponent))));
+
+ try {
+ KeyFactory rsaKeyFactory = KeyFactory.getInstance("rsa");
+ RSAPrivateKeySpec kspec = new RSAPrivateKeySpec(bigModulus, bigEx);
+ return (RSAPrivateKey) rsaKeyFactory.generatePrivate(kspec);
+ } catch (Exception e) {
+ throw new ProcessingException(e);
+ }
+ }
+
+ public String toString() {
+ String prefix = WSTrustConstants.XMLDSig.DSIG_PREFIX;
+ String colon = ":";
+ String left = "<";
+ String right = ">";
+ String slash = "/";
+
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(left).append(prefix).append(colon).append(WSTrustConstants.XMLDSig.RSA_KEYVALUE).append(right);
+
+ sb.append(left).append(prefix).append(colon).append(WSTrustConstants.XMLDSig.MODULUS).append(right);
+ sb.append(new String(getModulus()));
+ sb.append(left).append(slash).append(prefix).append(colon).append(WSTrustConstants.XMLDSig.MODULUS).append(right);
+
+ sb.append(left).append(prefix).append(colon).append(WSTrustConstants.XMLDSig.EXPONENT).append(right);
+ sb.append(new String(getExponent()));
+ sb.append(left).append(slash).append(prefix).append(colon).append(WSTrustConstants.XMLDSig.EXPONENT).append(right);
+
+ sb.append(left).append(slash).append(prefix).append(colon).append(WSTrustConstants.XMLDSig.RSA_KEYVALUE).append(right);
+ return sb.toString();
+ }
+
+ private byte[] massage(byte[] byteArray) {
+ if (byteArray[0] == 0) {
+ byte[] substring = new byte[byteArray.length - 1];
+ System.arraycopy(byteArray, 1, substring, 0, byteArray.length - 1);
+ return substring;
+ }
+ return byteArray;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignatureMethodType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignatureMethodType.java
new file mode 100755
index 0000000..9f2c4af
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignatureMethodType.java
@@ -0,0 +1,86 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for SignatureMethodType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="SignatureMethodType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element name="HMACOutputLength" type="{http://www.w3.org/2000/09/xmldsig#}HMACOutputLengthType"
+ * minOccurs="0"/>
+ * <any/>
+ * </sequence>
+ * <attribute name="Algorithm" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class SignatureMethodType {
+
+ protected List<Object> content = new ArrayList<Object>();
+ protected String algorithm;
+
+ public void add(Object obj) {
+ this.content.add(obj);
+ }
+
+ public void remove(Object obj) {
+ this.content.remove(obj);
+ }
+
+ /**
+ * Gets the value of the content property.
+ *
+ * {@link Object } {@link String }
+ */
+ public List<Object> getContent() {
+ return Collections.unmodifiableList(this.content);
+ }
+
+ /**
+ * Gets the value of the algorithm property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ /**
+ * Sets the value of the algorithm property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setAlgorithm(String value) {
+ this.algorithm = value;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignaturePropertiesType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignaturePropertiesType.java
new file mode 100755
index 0000000..9f38ffc
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignaturePropertiesType.java
@@ -0,0 +1,85 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for SignaturePropertiesType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="SignaturePropertiesType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}SignatureProperty" maxOccurs="unbounded"/>
+ * </sequence>
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class SignaturePropertiesType {
+
+ protected List<SignaturePropertyType> signatureProperty = new ArrayList<SignaturePropertyType>();
+ protected String id;
+
+ public void addSignatureProperty(SignaturePropertyType sig) {
+ this.signatureProperty.add(sig);
+ }
+
+ public void removeSignatureProperty(SignaturePropertyType sig) {
+ this.signatureProperty.remove(sig);
+ }
+
+ /**
+ * Gets the value of the signatureProperty property.
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link SignaturePropertyType }
+ */
+ public List<SignaturePropertyType> getSignatureProperty() {
+ return Collections.unmodifiableList(this.signatureProperty);
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignaturePropertyType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignaturePropertyType.java
new file mode 100755
index 0000000..25fd5ef
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignaturePropertyType.java
@@ -0,0 +1,95 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for SignaturePropertyType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="SignaturePropertyType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice maxOccurs="unbounded">
+ * <any/>
+ * </choice>
+ * <attribute name="Target" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class SignaturePropertyType {
+
+ protected List<Object> content = new ArrayList<Object>();
+ protected String target;
+ protected String id;
+
+ /**
+ * Gets the value of the content property.
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link org.w3c.dom.Element } {@link Object } {@link String }
+ */
+ public List<Object> getContent() {
+ return this.content;
+ }
+
+ /**
+ * Gets the value of the target property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getTarget() {
+ return target;
+ }
+
+ /**
+ * Sets the value of the target property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setTarget(String value) {
+ this.target = value;
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignatureType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignatureType.java
new file mode 100755
index 0000000..f8f38c1
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignatureType.java
@@ -0,0 +1,144 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for SignatureType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="SignatureType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}SignedInfo"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}SignatureValue"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}KeyInfo" minOccurs="0"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}Object" maxOccurs="unbounded" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class SignatureType {
+
+ protected SignedInfoType signedInfo;
+ protected SignatureValueType signatureValue;
+ protected KeyInfoType keyInfo;
+ protected List<ObjectType> object = new ArrayList<ObjectType>();
+ protected String id;
+
+ /**
+ * Gets the value of the signedInfo property.
+ *
+ * @return possible object is {@link SignedInfoType }
+ */
+ public SignedInfoType getSignedInfo() {
+ return signedInfo;
+ }
+
+ /**
+ * Sets the value of the signedInfo property.
+ *
+ * @param value allowed object is {@link SignedInfoType }
+ */
+ public void setSignedInfo(SignedInfoType value) {
+ this.signedInfo = value;
+ }
+
+ /**
+ * Gets the value of the signatureValue property.
+ *
+ * @return possible object is {@link SignatureValueType }
+ */
+ public SignatureValueType getSignatureValue() {
+ return signatureValue;
+ }
+
+ /**
+ * Sets the value of the signatureValue property.
+ *
+ * @param value allowed object is {@link SignatureValueType }
+ */
+ public void setSignatureValue(SignatureValueType value) {
+ this.signatureValue = value;
+ }
+
+ /**
+ * Gets the value of the keyInfo property.
+ *
+ * @return possible object is {@link KeyInfoType }
+ */
+ public KeyInfoType getKeyInfo() {
+ return keyInfo;
+ }
+
+ /**
+ * Sets the value of the keyInfo property.
+ *
+ * @param value allowed object is {@link KeyInfoType }
+ */
+ public void setKeyInfo(KeyInfoType value) {
+ this.keyInfo = value;
+ }
+
+ public void addObject(ObjectType obj) {
+ this.object.add(obj);
+ }
+
+ public void removeObject(ObjectType obj) {
+ this.object.remove(obj);
+ }
+
+ /**
+ * Gets the value of the object property.
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link ObjectType }
+ */
+ public List<ObjectType> getObject() {
+ return Collections.unmodifiableList(this.object);
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignatureValueType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignatureValueType.java
new file mode 100755
index 0000000..7faf77b
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignatureValueType.java
@@ -0,0 +1,77 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+/**
+ * <p>
+ * Java class for SignatureValueType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="SignatureValueType">
+ * <simpleContent>
+ * <extension base="<http://www.w3.org/2001/XMLSchema>base64Binary">
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * </extension>
+ * </simpleContent>
+ * </complexType>
+ * </pre>
+ */
+public class SignatureValueType {
+
+ protected byte[] value;
+ protected String id;
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return possible object is byte[]
+ */
+ public byte[] getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value allowed object is byte[]
+ */
+ public void setValue(byte[] value) {
+ this.value = ((byte[]) value);
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignedInfoType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignedInfoType.java
new file mode 100755
index 0000000..1d207f5
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SignedInfoType.java
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for SignedInfoType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="SignedInfoType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}CanonicalizationMethod"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}SignatureMethod"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}Reference" maxOccurs="unbounded"/>
+ * </sequence>
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class SignedInfoType {
+
+ protected CanonicalizationMethodType canonicalizationMethod;
+ protected SignatureMethodType signatureMethod;
+ protected List<ReferenceType> reference = new ArrayList<ReferenceType>();
+ protected String id;
+
+ /**
+ * Gets the value of the canonicalizationMethod property.
+ *
+ * @return possible object is {@link CanonicalizationMethodType }
+ */
+ public CanonicalizationMethodType getCanonicalizationMethod() {
+ return canonicalizationMethod;
+ }
+
+ /**
+ * Sets the value of the canonicalizationMethod property.
+ *
+ * @param value allowed object is {@link CanonicalizationMethodType }
+ */
+ public void setCanonicalizationMethod(CanonicalizationMethodType value) {
+ this.canonicalizationMethod = value;
+ }
+
+ /**
+ * Gets the value of the signatureMethod property.
+ *
+ * @return possible object is {@link SignatureMethodType }
+ */
+ public SignatureMethodType getSignatureMethod() {
+ return signatureMethod;
+ }
+
+ /**
+ * Sets the value of the signatureMethod property.
+ *
+ * @param value allowed object is {@link SignatureMethodType }
+ */
+ public void setSignatureMethod(SignatureMethodType value) {
+ this.signatureMethod = value;
+ }
+
+ public void add(ReferenceType ref) {
+ this.reference.add(ref);
+ }
+
+ public void remove(ReferenceType ref) {
+ this.reference.remove(ref);
+ }
+
+ /**
+ * Gets the value of the reference property.
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link ReferenceType }
+ */
+ public List<ReferenceType> getReference() {
+ return Collections.unmodifiableList(this.reference);
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SPKIDataType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SPKIDataType.java
new file mode 100755
index 0000000..90adf2d
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/SPKIDataType.java
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for SPKIDataType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="SPKIDataType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence maxOccurs="unbounded">
+ * <element name="SPKISexp" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ * <any/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class SPKIDataType {
+
+ protected List<Object> spkiSexpAndAny = new ArrayList<Object>();
+
+ public void addSPKI(Object obj) {
+ this.spkiSexpAndAny.add(obj);
+ }
+
+ public void removeSPKI(Object obj) {
+ this.spkiSexpAndAny.remove(obj);
+ }
+
+ /**
+ * Gets the value of the spkiSexpAndAny property.
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link org.w3c.dom.Element } {@link Object }
+ */
+ public List<Object> getSPKISexpAndAny() {
+ return Collections.unmodifiableList(this.spkiSexpAndAny);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/TransformsType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/TransformsType.java
new file mode 100755
index 0000000..1bda4d1
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/TransformsType.java
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for TransformsType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="TransformsType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}Transform" maxOccurs="unbounded"/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class TransformsType {
+
+ protected List<TransformType> transform = new ArrayList<TransformType>();
+
+ public void addTransformsType(TransformType tt) {
+ this.transform.add(tt);
+ }
+
+ public void removeTransformsType(TransformType tt) {
+ this.transform.remove(tt);
+ }
+
+ /**
+ * Gets the value of the transform property.
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link TransformType }
+ */
+ public List<TransformType> getTransform() {
+ return Collections.unmodifiableList(this.transform);
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/TransformType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/TransformType.java
new file mode 100755
index 0000000..d8601eb
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/TransformType.java
@@ -0,0 +1,82 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for TransformType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="TransformType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice maxOccurs="unbounded" minOccurs="0">
+ * <any/>
+ * <element name="XPath" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * </choice>
+ * <attribute name="Algorithm" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class TransformType {
+
+ protected List<Object> content = new ArrayList<Object>();
+ protected URI algorithm;
+
+ public TransformType(URI algorithm) {
+ this.algorithm = algorithm;
+ }
+
+ public void addTransform(Object obj) {
+ this.content.add(obj);
+ }
+
+ public void removeTransform(Object obj) {
+ this.content.remove(obj);
+ }
+
+ /**
+ * Gets the value of the content property.
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link org.w3c.dom.Element } {@link String } {@link Object }
+ */
+ public List<Object> getContent() {
+ return Collections.unmodifiableList(this.content);
+ }
+
+ /**
+ * Gets the value of the algorithm property.
+ *
+ * @return possible object is {@link String }
+ */
+ public URI getAlgorithm() {
+ return algorithm;
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/X509CertificateType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/X509CertificateType.java
new file mode 100755
index 0000000..303f753
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/X509CertificateType.java
@@ -0,0 +1,31 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+public class X509CertificateType {
+
+ private byte[] encodedCertificate;
+
+ public byte[] getEncodedCertificate() {
+ return this.encodedCertificate;
+ }
+
+ public void setEncodedCertificate(byte[] encodedCertificate) {
+ this.encodedCertificate = encodedCertificate;
+ }
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/X509DataType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/X509DataType.java
new file mode 100755
index 0000000..02d3255
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/X509DataType.java
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for X509DataType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="X509DataType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence maxOccurs="unbounded">
+ * <choice>
+ * <element name="X509IssuerSerial" type="{http://www.w3.org/2000/09/xmldsig#}X509IssuerSerialType"/>
+ * <element name="X509SKI" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ * <element name="X509SubjectName" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * <element name="X509Certificate" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ * <element name="X509CRL" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ * <any/>
+ * </choice>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class X509DataType {
+
+ protected List<Object> x509IssuerSerialOrX509SKIOrX509SubjectName = new ArrayList<Object>();
+
+ public void add(Object obj) {
+ this.x509IssuerSerialOrX509SKIOrX509SubjectName.add(obj);
+ }
+
+ public void remove(Object obj) {
+ this.x509IssuerSerialOrX509SKIOrX509SubjectName.remove(obj);
+ }
+
+ /**
+ * Gets the value of the x509IssuerSerialOrX509SKIOrX509SubjectName property.
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link org.w3c.dom.Element } {@link Object }
+ */
+ public List<Object> getDataObjects() {
+ return Collections.unmodifiableList(this.x509IssuerSerialOrX509SKIOrX509SubjectName);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/X509IssuerSerialType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/X509IssuerSerialType.java
new file mode 100755
index 0000000..d137cfa
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmldsig/X509IssuerSerialType.java
@@ -0,0 +1,82 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmldsig;
+
+import java.math.BigInteger;
+
+/**
+ * <p>
+ * Java class for X509IssuerSerialType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="X509IssuerSerialType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element name="X509IssuerName" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * <element name="X509SerialNumber" type="{http://www.w3.org/2001/XMLSchema}integer"/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class X509IssuerSerialType {
+
+ protected String x509IssuerName;
+ protected BigInteger x509SerialNumber;
+
+ /**
+ * Gets the value of the x509IssuerName property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getX509IssuerName() {
+ return x509IssuerName;
+ }
+
+ /**
+ * Sets the value of the x509IssuerName property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setX509IssuerName(String value) {
+ this.x509IssuerName = value;
+ }
+
+ /**
+ * Gets the value of the x509SerialNumber property.
+ *
+ * @return possible object is {@link BigInteger }
+ */
+ public BigInteger getX509SerialNumber() {
+ return x509SerialNumber;
+ }
+
+ /**
+ * Sets the value of the x509SerialNumber property.
+ *
+ * @param value allowed object is {@link BigInteger }
+ */
+ public void setX509SerialNumber(BigInteger value) {
+ this.x509SerialNumber = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/AgreementMethodType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/AgreementMethodType.java
new file mode 100755
index 0000000..fdba750
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/AgreementMethodType.java
@@ -0,0 +1,87 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType;
+
+/**
+ * <p>
+ * Java class for AgreementMethodType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="AgreementMethodType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element name="KA-Nonce" type="{http://www.w3.org/2001/XMLSchema}base64Binary" minOccurs="0"/>
+ * <any/>
+ * <element name="OriginatorKeyInfo" type="{http://www.w3.org/2000/09/xmldsig#}KeyInfoType" minOccurs="0"/>
+ * <element name="RecipientKeyInfo" type="{http://www.w3.org/2000/09/xmldsig#}KeyInfoType" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="Algorithm" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class AgreementMethodType {
+
+ protected String algorithm;
+
+ public static class AggrementMethod {
+
+ protected byte[] kANonce;
+ protected KeyInfoType originatorKeyInfo;
+ protected KeyInfoType recipientKeyInfo;
+
+ public AggrementMethod(byte[] kANonce, KeyInfoType originatorKeyInfo, KeyInfoType recipientKeyInfo) {
+ this.kANonce = kANonce;
+ this.originatorKeyInfo = originatorKeyInfo;
+ this.recipientKeyInfo = recipientKeyInfo;
+ }
+
+ public byte[] getkANonce() {
+ return kANonce;
+ }
+
+ public KeyInfoType getOriginatorKeyInfo() {
+ return originatorKeyInfo;
+ }
+
+ public KeyInfoType getRecipientKeyInfo() {
+ return recipientKeyInfo;
+ }
+ }
+
+ public AgreementMethodType(String algo) {
+ this.algorithm = algo;
+ }
+
+ /**
+ * Gets the value of the algorithm property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/CipherDataType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/CipherDataType.java
new file mode 100755
index 0000000..3cb220c
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/CipherDataType.java
@@ -0,0 +1,80 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+/**
+ * <p>
+ * Java class for CipherDataType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="CipherDataType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice>
+ * <element name="CipherValue" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ * <element ref="{http://www.w3.org/2001/04/xmlenc#}CipherReference"/>
+ * </choice>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class CipherDataType {
+
+ protected byte[] cipherValue;
+ protected CipherReferenceType cipherReference;
+
+ /**
+ * Gets the value of the cipherValue property.
+ *
+ * @return possible object is byte[]
+ */
+ public byte[] getCipherValue() {
+ return cipherValue;
+ }
+
+ /**
+ * Sets the value of the cipherValue property.
+ *
+ * @param value allowed object is byte[]
+ */
+ public void setCipherValue(byte[] value) {
+ this.cipherValue = ((byte[]) value);
+ }
+
+ /**
+ * Gets the value of the cipherReference property.
+ *
+ * @return possible object is {@link CipherReferenceType }
+ */
+ public CipherReferenceType getCipherReference() {
+ return cipherReference;
+ }
+
+ /**
+ * Sets the value of the cipherReference property.
+ *
+ * @param value allowed object is {@link CipherReferenceType }
+ */
+ public void setCipherReference(CipherReferenceType value) {
+ this.cipherReference = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/CipherReferenceType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/CipherReferenceType.java
new file mode 100755
index 0000000..2a2a9d8
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/CipherReferenceType.java
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+import java.net.URI;
+
+/**
+ * <p>
+ * Java class for CipherReferenceType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="CipherReferenceType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice>
+ * <element name="Transforms" type="{http://www.w3.org/2001/04/xmlenc#}TransformsType" minOccurs="0"/>
+ * </choice>
+ * <attribute name="URI" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class CipherReferenceType {
+
+ protected TransformsType transforms;
+ protected URI uri;
+
+ public CipherReferenceType(URI uri) {
+
+ }
+
+ /**
+ * Gets the value of the transforms property.
+ *
+ * @return possible object is {@link TransformsType }
+ */
+ public TransformsType getTransforms() {
+ return transforms;
+ }
+
+ /**
+ * Sets the value of the transforms property.
+ *
+ * @param value allowed object is {@link TransformsType }
+ */
+ public void setTransforms(TransformsType value) {
+ this.transforms = value;
+ }
+
+ /**
+ * Gets the value of the uri property.
+ *
+ * @return possible object is {@link String }
+ */
+ public URI getURI() {
+ return uri;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptedDataType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptedDataType.java
new file mode 100755
index 0000000..454b501
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptedDataType.java
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+/**
+ * <p>
+ * Java class for EncryptedDataType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="EncryptedDataType">
+ * <complexContent>
+ * <extension base="{http://www.w3.org/2001/04/xmlenc#}EncryptedType">
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class EncryptedDataType extends EncryptedType {
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptedKeyType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptedKeyType.java
new file mode 100755
index 0000000..e2b2c53
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptedKeyType.java
@@ -0,0 +1,102 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+/**
+ * <p>
+ * Java class for EncryptedKeyType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="EncryptedKeyType">
+ * <complexContent>
+ * <extension base="{http://www.w3.org/2001/04/xmlenc#}EncryptedType">
+ * <sequence>
+ * <element ref="{http://www.w3.org/2001/04/xmlenc#}ReferenceList" minOccurs="0"/>
+ * <element name="CarriedKeyName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="Recipient" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * </extension>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class EncryptedKeyType extends EncryptedType {
+
+ protected ReferenceList referenceList;
+ protected String carriedKeyName;
+ protected String recipient;
+
+ /**
+ * Gets the value of the referenceList property.
+ *
+ * @return possible object is {@link ReferenceList }
+ */
+ public ReferenceList getReferenceList() {
+ return referenceList;
+ }
+
+ /**
+ * Sets the value of the referenceList property.
+ *
+ * @param value allowed object is {@link ReferenceList }
+ */
+ public void setReferenceList(ReferenceList value) {
+ this.referenceList = value;
+ }
+
+ /**
+ * Gets the value of the carriedKeyName property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getCarriedKeyName() {
+ return carriedKeyName;
+ }
+
+ /**
+ * Sets the value of the carriedKeyName property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setCarriedKeyName(String value) {
+ this.carriedKeyName = value;
+ }
+
+ /**
+ * Gets the value of the recipient property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getRecipient() {
+ return recipient;
+ }
+
+ /**
+ * Sets the value of the recipient property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setRecipient(String value) {
+ this.recipient = value;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptedType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptedType.java
new file mode 100755
index 0000000..fecd4b0
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptedType.java
@@ -0,0 +1,204 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType;
+
+/**
+ * <p>
+ * Java class for EncryptedType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="EncryptedType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element name="EncryptionMethod" type="{http://www.w3.org/2001/04/xmlenc#}EncryptionMethodType"
+ * minOccurs="0"/>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}KeyInfo" minOccurs="0"/>
+ * <element ref="{http://www.w3.org/2001/04/xmlenc#}CipherData"/>
+ * <element ref="{http://www.w3.org/2001/04/xmlenc#}EncryptionProperties" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * <attribute name="Type" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * <attribute name="MimeType" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * <attribute name="Encoding" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public abstract class EncryptedType {
+
+ protected EncryptionMethodType encryptionMethod;
+ protected KeyInfoType keyInfo;
+ protected CipherDataType cipherData;
+ protected EncryptionPropertiesType encryptionProperties;
+ protected String id;
+ protected String type;
+ protected String mimeType;
+ protected String encoding;
+
+ /**
+ * Gets the value of the encryptionMethod property.
+ *
+ * @return possible object is {@link EncryptionMethodType }
+ */
+ public EncryptionMethodType getEncryptionMethod() {
+ return encryptionMethod;
+ }
+
+ /**
+ * Sets the value of the encryptionMethod property.
+ *
+ * @param value allowed object is {@link EncryptionMethodType }
+ */
+ public void setEncryptionMethod(EncryptionMethodType value) {
+ this.encryptionMethod = value;
+ }
+
+ /**
+ * Gets the value of the keyInfo property.
+ *
+ * @return possible object is {@link KeyInfoType }
+ */
+ public KeyInfoType getKeyInfo() {
+ return keyInfo;
+ }
+
+ /**
+ * Sets the value of the keyInfo property.
+ *
+ * @param value allowed object is {@link KeyInfoType }
+ */
+ public void setKeyInfo(KeyInfoType value) {
+ this.keyInfo = value;
+ }
+
+ /**
+ * Gets the value of the cipherData property.
+ *
+ * @return possible object is {@link CipherDataType }
+ */
+ public CipherDataType getCipherData() {
+ return cipherData;
+ }
+
+ /**
+ * Sets the value of the cipherData property.
+ *
+ * @param value allowed object is {@link CipherDataType }
+ */
+ public void setCipherData(CipherDataType value) {
+ this.cipherData = value;
+ }
+
+ /**
+ * Gets the value of the encryptionProperties property.
+ *
+ * @return possible object is {@link EncryptionPropertiesType }
+ */
+ public EncryptionPropertiesType getEncryptionProperties() {
+ return encryptionProperties;
+ }
+
+ /**
+ * Sets the value of the encryptionProperties property.
+ *
+ * @param value allowed object is {@link EncryptionPropertiesType }
+ */
+ public void setEncryptionProperties(EncryptionPropertiesType value) {
+ this.encryptionProperties = value;
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+
+ /**
+ * Gets the value of the type property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Sets the value of the type property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setType(String value) {
+ this.type = value;
+ }
+
+ /**
+ * Gets the value of the mimeType property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ /**
+ * Sets the value of the mimeType property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setMimeType(String value) {
+ this.mimeType = value;
+ }
+
+ /**
+ * Gets the value of the encoding property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getEncoding() {
+ return encoding;
+ }
+
+ /**
+ * Sets the value of the encoding property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setEncoding(String value) {
+ this.encoding = value;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionMethodType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionMethodType.java
new file mode 100755
index 0000000..0273ded
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionMethodType.java
@@ -0,0 +1,89 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+import java.math.BigInteger;
+
+/**
+ * <p>
+ * Java class for EncryptionMethodType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="EncryptionMethodType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element name="KeySize" type="{http://www.w3.org/2001/04/xmlenc#}KeySizeType" minOccurs="0"/>
+ * <element name="OAEPparams" type="{http://www.w3.org/2001/XMLSchema}base64Binary" minOccurs="0"/>
+ * <any/>
+ * </sequence>
+ * <attribute name="Algorithm" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class EncryptionMethodType {
+
+ protected String algorithm;
+
+ protected EncryptionMethod encryptionMethod;
+
+ public static class EncryptionMethod {
+
+ protected BigInteger keySize;
+ protected byte[] OAEPparams;
+
+ public EncryptionMethod(BigInteger bigInteger, byte[] oAEPparams) {
+ this.keySize = bigInteger;
+ OAEPparams = oAEPparams;
+ }
+
+ public BigInteger getKeySize() {
+ return keySize;
+ }
+
+ public byte[] getOAEPparams() {
+ return OAEPparams;
+ }
+ }
+
+ public EncryptionMethodType(String algo) {
+ this.algorithm = algo;
+ }
+
+ public EncryptionMethod getEncryptionMethod() {
+ return encryptionMethod;
+ }
+
+ public void setEncryptionMethod(EncryptionMethod encryptionMethod) {
+ this.encryptionMethod = encryptionMethod;
+ }
+
+ /**
+ * Gets the value of the algorithm property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getAlgorithm() {
+ return algorithm;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionPropertiesType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionPropertiesType.java
new file mode 100755
index 0000000..a91e14d
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionPropertiesType.java
@@ -0,0 +1,84 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for EncryptionPropertiesType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="EncryptionPropertiesType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://www.w3.org/2001/04/xmlenc#}EncryptionProperty" maxOccurs="unbounded"/>
+ * </sequence>
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class EncryptionPropertiesType {
+
+ protected List<EncryptionPropertyType> encryptionProperty = new ArrayList<EncryptionPropertyType>();
+ protected String id;
+
+ public void addEncryptionProperty(EncryptionPropertyType enc) {
+ this.encryptionProperty.add(enc);
+ }
+
+ public void removeEncryptionProperty(EncryptionPropertyType enc) {
+ this.encryptionProperty.remove(enc);
+ }
+
+ /**
+ * Gets the value of the encryptionProperty property.
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link EncryptionPropertyType }
+ */
+ public List<EncryptionPropertyType> getEncryptionProperty() {
+ return Collections.unmodifiableList(this.encryptionProperty);
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionPropertyType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionPropertyType.java
new file mode 100755
index 0000000..7f1725e
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/EncryptionPropertyType.java
@@ -0,0 +1,109 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+import javax.xml.namespace.QName;
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>
+ * Java class for EncryptionPropertyType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="EncryptionPropertyType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice maxOccurs="unbounded">
+ * <any/>
+ * </choice>
+ * <attribute name="Target" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * <attribute name="Id" type="{http://www.w3.org/2001/XMLSchema}ID" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class EncryptionPropertyType {
+
+ protected URI target;
+ protected String id;
+ private Map<QName, String> otherAttributes = new HashMap<QName, String>();
+
+ /**
+ * Gets the value of the target property.
+ *
+ * @return possible object is {@link URI }
+ */
+ public URI getTarget() {
+ return target;
+ }
+
+ /**
+ * Sets the value of the target property.
+ *
+ * @param value allowed object is {@link URI }
+ */
+ public void setTarget(URI value) {
+ this.target = value;
+ }
+
+ /**
+ * Gets the value of the id property.
+ *
+ * @return possible object is {@link String }
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Sets the value of the id property.
+ *
+ * @param value allowed object is {@link String }
+ */
+ public void setId(String value) {
+ this.id = value;
+ }
+
+ public void addOtherAttribute(QName key, String val) {
+ this.otherAttributes.put(key, val);
+ }
+
+ public void addOtherAttributes(Map<QName, String> otherMap) {
+ this.otherAttributes.putAll(otherMap);
+ }
+
+ public void removeOtherAttribute(QName key) {
+ this.otherAttributes.remove(key);
+ }
+
+ /**
+ * Gets a map that contains attributes that aren't bound to any typed property on this class.
+ *
+ * @return always non-null
+ */
+ public Map<QName, String> getOtherAttributes() {
+ return Collections.unmodifiableMap(otherAttributes);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/package-info.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/package-info.java
new file mode 100755
index 0000000..58e88e0
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/ReferenceList.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/ReferenceList.java
new file mode 100755
index 0000000..6c80a60
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/ReferenceList.java
@@ -0,0 +1,82 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for anonymous complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <choice maxOccurs="unbounded">
+ * <element name="DataReference" type="{http://www.w3.org/2001/04/xmlenc#}ReferenceType"/>
+ * <element name="KeyReference" type="{http://www.w3.org/2001/04/xmlenc#}ReferenceType"/>
+ * </choice>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class ReferenceList {
+
+ public static class References {
+
+ private ReferenceType dataReference;
+ private ReferenceType keyReference;
+
+ public References(ReferenceType dataReference, ReferenceType keyReference) {
+ this.dataReference = dataReference;
+ this.keyReference = keyReference;
+ }
+
+ public ReferenceType getDataReference() {
+ return dataReference;
+ }
+
+ public ReferenceType getKeyReference() {
+ return keyReference;
+ }
+ }
+
+ private List<References> referencesList = new ArrayList<References>();
+
+ public void add(References ref) {
+ this.referencesList.add(ref);
+ }
+
+ public void addAll(List<References> refs) {
+ this.referencesList.addAll(refs);
+ }
+
+ public void remove(References ref) {
+ this.referencesList.remove(ref);
+ }
+
+ public List<References> getReferences() {
+ return Collections.unmodifiableList(referencesList);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/ReferenceType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/ReferenceType.java
new file mode 100755
index 0000000..6cb791e
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/ReferenceType.java
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+import java.net.URI;
+
+/**
+ * <p>
+ * Java class for ReferenceType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="ReferenceType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <any/>
+ * </sequence>
+ * <attribute name="URI" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class ReferenceType {
+
+ protected URI uri;
+
+ public Object reference;
+
+ public ReferenceType(URI uri) {
+ this.uri = uri;
+ }
+
+ public Object getReference() {
+ return reference;
+ }
+
+ public void setReference(Object reference) {
+ this.reference = reference;
+ }
+
+ /**
+ * Gets the value of the uri property.
+ *
+ * @return possible object is {@link URI }
+ */
+ public URI getURI() {
+ return uri;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/TransformsType.java b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/TransformsType.java
new file mode 100755
index 0000000..19c3f54
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/dom/xmlsec/w3/xmlenc/TransformsType.java
@@ -0,0 +1,69 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.dom.xmlsec.w3.xmlenc;
+
+import org.keycloak.dom.xmlsec.w3.xmldsig.TransformType;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <p>
+ * Java class for TransformsType complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="TransformsType">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://www.w3.org/2000/09/xmldsig#}Transform" maxOccurs="unbounded"/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ */
+public class TransformsType {
+
+ protected List<TransformType> transform = new ArrayList<TransformType>();
+
+ public void add(TransformType tt) {
+ this.transform.add(tt);
+ }
+
+ public void addAll(List<TransformType> ttlist) {
+ this.transform.addAll(ttlist);
+ }
+
+ public void remove(TransformType tt) {
+ this.transform.remove(tt);
+ }
+
+ /**
+ * Gets the value of the transform property.
+ * <p>
+ * Objects of the following type(s) are allowed in the list {@link TransformType }
+ */
+ public List<TransformType> getTransform() {
+ return Collections.unmodifiableList(this.transform);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/constants/GeneralConstants.java b/saml-core/src/main/java/org/keycloak/saml/common/constants/GeneralConstants.java
new file mode 100755
index 0000000..7a7acb3
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/constants/GeneralConstants.java
@@ -0,0 +1,155 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.saml.common.constants;
+
+
+/**
+ * Constants
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Oct 8, 2009
+ */
+public interface GeneralConstants {
+ String ASSERTIONS_VALIDITY = "ASSERTIONS_VALIDITY";
+ String CLOCK_SKEW = "CLOCK_SKEW";
+
+ String ASSERTION_ID = "ASSERTION_ID";
+
+ String ASSERTION = "ASSERTION";
+
+ String ATTRIBUTES = "ATTRIBUTES";
+
+ String ATTRIBUTE_KEYS = "ATTRIBUTE_KEYS";
+
+ String ATTRIBUTE_CHOOSE_FRIENDLY_NAME = "ATTRIBUTE_CHOOSE_FRIENDLY_NAME";
+
+ String ATTIBUTE_MANAGER = "ATTRIBUTE_MANAGER";
+
+ String AUDIT_ENABLE = "picketlink.audit.enable";
+
+ String AUDIT_HELPER = "AUDIT_HELPER";
+
+ String AUDIT_SECURITY_DOMAIN = "picketlink.audit.securitydomain";
+
+ String CONFIGURATION = "CONFIGURATION";
+
+ String CONFIG_FILE_LOCATION = "/WEB-INF/picketlink.xml";
+
+ String CONFIG_PROVIDER = "CONFIG_PROVIDER";
+
+ String CONTEXT_PATH = "CONTEXT_PATH";
+
+ String DEPRECATED_CONFIG_FILE_LOCATION = "/WEB-INF/picketlink-idfed.xml";
+
+ String LOCAL_LOGOUT = "LLO";
+
+ String GLOBAL_LOGOUT = "GLO";
+
+ String HANDLER_CONFIG_FILE_LOCATION = "/WEB-INF/picketlink-handlers.xml";
+
+ String IDENTITY_SERVER = "IDENTITY_SERVER";
+
+ String IDENTITY_PARTICIPANT_STACK = "IDENTITY_PARTICIPANT_STACK";
+
+ String IGNORE_SIGNATURES = "IGNORE_SIGNATURES";
+
+ String KEYPAIR = "KEYPAIR";
+
+ String LOGIN_TYPE = "LOGIN_TYPE";
+
+ String LOGOUT_PAGE = "LOGOUT_PAGE";
+
+ String LOGOUT_PAGE_NAME = "/logout.jsp";
+
+ String NAMEID_FORMAT = "NAMEID_FORMAT";
+
+ String PRINCIPAL_ID = "picketlink.principal";
+
+ String RELAY_STATE = "RelayState";
+
+ String ROLES = "ROLES";
+
+ String ROLES_ID = "picketlink.roles";
+
+ String ROLE_GENERATOR = "ROLE_GENERATOR";
+
+ String ROLE_VALIDATOR = "ROLE_VALIDATOR";
+
+ String ROLE_VALIDATOR_IGNORE = "ROLE_VALIDATOR_IGNORE";
+
+ String SAML_REQUEST_KEY = "SAMLRequest";
+
+ String SAML_RESPONSE_KEY = "SAMLResponse";
+
+ String SAML_SIG_ALG_REQUEST_KEY = "SigAlg";
+
+ String SAML_SIGNATURE_REQUEST_KEY = "Signature";
+
+ String SAML_IDP_STRICT_POST_BINDING = "SAML_IDP_STRICT_POST_BINDING";
+
+ // Should JAXP Factory operations cache the TCCL and revert after operation?
+ String TCCL_JAXP = "picketlink.jaxp.tccl";
+
+ String TIMEZONE = "picketlink.timezone";
+
+ String TIMEZONE_DEFAULT = "TIMEZONE_DEFAULT";
+
+ String DECRYPTING_KEY = "DECRYPTING_KEY";
+
+ String SP_SSO_METADATA_DESCRIPTOR = "SP_SSO_METADATA_DESCRIPTOR";
+
+ String IDP_SSO_METADATA_DESCRIPTOR = "IDP_SSO_METADATA_DESCRIPTOR";
+
+ String SSO_METADATA_DESCRIPTOR = "SSO_METADATA_DESCRIPTOR";
+
+ String SENDER_PUBLIC_KEY = "SENDER_PUBLIC_KEY";
+
+ String SIGN_OUTGOING_MESSAGES = "SIGN_OUTGOING_MESSAGES";
+
+ String SUPPORTS_SIGNATURES = "SUPPORTS_SIGNATURES";
+
+ String SESSION_ATTRIBUTE_MAP = "SESSION_ATTRIBUTE_MAP";
+
+ String USERNAME_FIELD = "JBID_USERNAME";
+
+ String PASS_FIELD = "JBID_PASSWORD";
+
+ String AUTH_REQUEST_ID = "AUTH_REQUEST_ID";
+ String ERROR_PAGE_NAME = "/error.jsp";
+ String SAML_ENC_KEY_SIZE = "SAML_ENC_KEY_SIZE";
+ String SAML_ENC_ALGORITHM = "SAML_ENC_ALGORITHM";
+
+ /**
+ * <p>{@link SAML2AuthenticationHandler} configuration option to set the assertion into the {@link
+ * HttpSession}.</p>
+ */
+ String ASSERTION_SESSION_ATTRIBUTE_NAME = "ASSERTION_SESSION_ATTRIBUTE_NAME";
+
+ String X509CERTIFICATE = "X509CERTIFICATE";
+
+ String AUTHN_CONTEXT_CLASSES = "AUTHN_CONTEXT_CLASSES";
+ String REQUESTED_AUTHN_CONTEXT_COMPARISON = "REQUESTED_AUTHN_CONTEXT_COMPARISON";
+
+ String BASE64_ENCODE_WSTRUST_SECRET_KEY = "picketlink.wstrust.base64_encode_wstrust_secret_key";
+
+ String HTTP_HEADER_X_REQUESTED_WITH = "X-Requested-With";
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/constants/JBossSAMLConstants.java b/saml-core/src/main/java/org/keycloak/saml/common/constants/JBossSAMLConstants.java
new file mode 100755
index 0000000..219042b
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/constants/JBossSAMLConstants.java
@@ -0,0 +1,80 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.constants;
+
+/**
+ * SAML Constants
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 10, 2008
+ */
+public enum JBossSAMLConstants {
+ ADDRESS("Address"), ADDITIONAL_METADATA_LOCATION("AdditionalMetadataLocation"), AFFILIATION_DESCRIPTOR(
+ "AffiliationDescriptor"), ALLOW_CREATE("AllowCreate"), ARTIFACT("Artifact"), ARTIFACT_RESOLVE("ArtifactResolve"), ARTIFACT_RESPONSE(
+ "ArtifactResponse"), ARTIFACT_RESOLUTION_SERVICE("ArtifactResolutionService"), ASSERTION("Assertion"), ASSERTION_CONSUMER_SERVICE(
+ "AssertionConsumerService"), ASSERTION_CONSUMER_SERVICE_URL("AssertionConsumerServiceURL"), ASSERTION_CONSUMER_SERVICE_INDEX(
+ "AssertionConsumerServiceIndex"), ASSERTION_ID_REQUEST_SERVICE("AssertionIDRequestService"), ATTRIBUTE("Attribute"), ATTRIBUTE_QUERY(
+ "AttributeQuery"), ATTRIBUTE_AUTHORITY_DESCRIPTOR("AttributeAuthorityDescriptor"), ATTRIBUTE_CONSUMING_SERVICE(
+ "AttributeConsumingService"), ATTRIBUTE_CONSUMING_SERVICE_INDEX("AttributeConsumingServiceIndex"), ATTRIBUTE_SERVICE(
+ "AttributeService"), ATTRIBUTE_STATEMENT("AttributeStatement"), ATTRIBUTE_VALUE("AttributeValue"), AUDIENCE(
+ "Audience"), AUDIENCE_RESTRICTION("AudienceRestriction"), AUTHN_CONTEXT("AuthnContext"), AUTHENTICATING_AUTHORITY(
+ "AuthenticatingAuthority"), AUTHN_AUTHORITY_DESCRIPTOR("AuthnAuthorityDescriptor"), AUTHN_CONTEXT_CLASS_REF(
+ "AuthnContextClassRef"), AUTHN_CONTEXT_DECLARATION("AuthnContextDecl"), AUTHN_CONTEXT_DECLARATION_REF(
+ "AuthnContextDeclRef"), AUTHN_INSTANT("AuthnInstant"), AUTHN_REQUEST("AuthnRequest"), AUTHN_STATEMENT(
+ "AuthnStatement"), AUTHN_REQUESTS_SIGNED("AuthnRequestsSigned"), BASEID("BaseID"), BINDING("Binding"), CACHE_DURATION(
+ "cacheDuration"), COMPANY("Company"), CONDITIONS("Conditions"), COMPARISON("Comparison"), CONSENT("Consent"), CONTACT_PERSON("ContactPerson"), CONTACT_TYPE(
+ "contactType"), DESTINATION("Destination"), DNS_NAME("DNSName"), EMAIL_ADDRESS("EmailAddress"), ENCODING("Encoding"), ENCRYPTED_ASSERTION(
+ "EncryptedAssertion"), ENCRYPTED_ID("EncryptedID"), ENTITY_ID("entityID"), ENTITY_DESCRIPTOR("EntityDescriptor"), ENTITIES_DESCRIPTOR(
+ "EntitiesDescriptor"), EXTENSIONS("Extensions"), FORMAT("Format"), FRIENDLY_NAME("FriendlyName"), FORCE_AUTHN(
+ "ForceAuthn"), GIVEN_NAME("GivenName"), ID("ID"), IDP_SSO_DESCRIPTOR("IDPSSODescriptor"), INDEX("index"), INPUT_CONTEXT_ONLY(
+ "InputContextOnly"), IN_RESPONSE_TO("InResponseTo"), ISDEFAULT("isDefault"), IS_REQUIRED("isRequired"), IS_PASSIVE(
+ "IsPassive"), ISSUE_INSTANT("IssueInstant"), ISSUER("Issuer"), KEY_DESCRIPTOR("KeyDescriptor"), KEY_INFO("KeyInfo"), ENCRYPTION_METHOD("EncryptionMethod"), LANG(
+ "lang"), LANG_EN("en"), LOCATION("Location"), LOGOUT_REQUEST("LogoutRequest"), LOGOUT_RESPONSE("LogoutResponse"), MANAGE_NAMEID_SERVICE(
+ "ManageNameIDService"), METADATA_MIME("application/samlmetadata+xml"), METHOD("Method"), NAME("Name"), NAME_FORMAT(
+ "NameFormat"), NAMEID("NameID"), NAMEID_FORMAT("NameIDFormat"), NAMEID_MAPPING_SERVICE("NameIDMappingService"), NAMEID_POLICY(
+ "NameIDPolicy"), NAME_QUALIFIER("NameQualifier"), NOT_BEFORE("NotBefore"), NOT_ON_OR_AFTER("NotOnOrAfter"), ORGANIZATION(
+ "Organization"), ORGANIZATION_NAME("OrganizationName"), ORGANIZATION_DISPLAY_NAME("OrganizationDisplayName"), ORGANIZATION_URL(
+ "OrganizationURL"), PDP_DESCRIPTOR("PDPDescriptor"), PROTOCOL_BINDING("ProtocolBinding"), PROTOCOL_SUPPORT_ENUMERATION(
+ "protocolSupportEnumeration"), PROVIDER_NAME("ProviderName"), REQUESTED_AUTHN_CONTEXT("RequestedAuthnContext"), REASON(
+ "Reason"), RECIPIENT("Recipient"), REQUEST("Request"), REQUESTED_ATTRIBUTE("RequestedAttribute"), REQUEST_ABSTRACT(
+ "RequestAbstract"), RESPONSE("Response"), RESPONSE_LOCATION("ResponseLocation"), RETURN_CONTEXT("ReturnContext"), SESSION_INDEX(
+ "SessionIndex"), SERVICE_NAME("ServiceName"), SERVICE_DESCRIPTION("ServiceDescription"), SP_PROVIDED_ID(
+ "SPProvidedID"), SP_NAME_QUALIFIER("SPNameQualifier"), SP_SSO_DESCRIPTOR("SPSSODescriptor"), SIGNATURE("Signature"), 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"), SINGLE_SIGNON_SERVICE(
+ "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;
+
+ private JBossSAMLConstants(String val) {
+ this.name = val;
+ }
+
+ public String get() {
+ return this.name;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/constants/JBossSAMLURIConstants.java b/saml-core/src/main/java/org/keycloak/saml/common/constants/JBossSAMLURIConstants.java
new file mode 100755
index 0000000..ad7bee5
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/constants/JBossSAMLURIConstants.java
@@ -0,0 +1,132 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.constants;
+
+/**
+ * Define the constants based on URI
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 10, 2008
+ */
+public enum JBossSAMLURIConstants {
+ AC_PASSWORD_PROTECTED_TRANSPORT("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"), AC_PASSWORD(
+ "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"), AC_TLS_CLIENT(
+ "urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient"), AC_PREVIOUS_SESSION(
+ "urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession"), AC_UNSPECIFIED(
+ "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified"), 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(
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"), 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_GIVEN_NAME(
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"), CLAIMS_NAME(
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"), CLAIMS_USER_PRINCIPAL_NAME_2005(
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"), CLAIMS_USER_PRINCIPAL_NAME(
+ "http://schemas.xmlsoap.org/claims/UPN"), CLAIMS_COMMON_NAME("http://schemas.xmlsoap.org/claims/CommonName"), CLAIMS_GROUP(
+ "http://schemas.xmlsoap.org/claims/Group"), CLAIMS_ROLE(
+ "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"), CLAIMS_SURNAME(
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"), CLAIMS_PRIVATE_ID(
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier"), CLAIMS_NAME_IDENTIFIER(
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"), CLAIMS_AUTHENTICATION_METHOD(
+ "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod"), CLAIMS_DENY_ONLY_GROUP_SID(
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid"), CLAIMS_DENY_ONLY_PRIMARY_SID(
+ "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid"), CLAIMS_DENY_ONLY_PRIMARY_GROUP_SID(
+ "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid"), CLAIMS_GROUP_SID(
+ "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid"), CLAIMS_PRIMARY_GROUP_SID(
+ "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid"), CLAIMS_PRIMARY_SID(
+ "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"), CLAIMS_WINDOWS_ACCOUNT_NAME(
+ "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"), CLAIMS_PUID(
+ "http://schemas.xmlsoap.org/claims/PUID"),
+
+ 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(
+ "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(
+ "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"), NAMEID_FORMAT_UNSPECIFIED(
+ "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"), NAMEID_FORMAT_EMAIL(
+ "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"), NAMEID_FORMAT_X509SUBJECTNAME(
+ "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName"), NAMEID_FORMAT_WINDOWS_DOMAIN_NAME(
+ "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName"), NAMEID_FORMAT_KERBEROS(
+ "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos"), NAMEID_FORMAT_ENTITY(
+ "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"),
+
+ PROTOCOL_NSURI("urn:oasis:names:tc:SAML:2.0:protocol"),
+ ECP_PROFILE("urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp"),
+ PAOS_BINDING("urn:liberty:paos:2003-08"),
+
+ SIGNATURE_DSA_SHA1("http://www.w3.org/2000/09/xmldsig#dsa-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_SOAP_BINDING("urn:oasis:names:tc:SAML:2.0:bindings:SOAP"),
+ SAML_HTTP_REDIRECT_BINDING("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"),
+
+ SAML_11_NS("urn:oasis:names:tc:SAML:1.0:assertion"),
+
+ 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(
+ "urn:oasis:names:tc:SAML:2.0:status:InvalidAttrnameOrValue"), STATUS_INVALID_NAMEIDPOLICY(
+ "urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy"), STATUS_NOAUTHN_CTX(
+ "urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext"), STATUS_NO_AVAILABLE_IDP(
+ "urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP"), STATUS_NO_PASSIVE(
+ "urn:oasis:names:tc:SAML:2.0:status:NoPassive"), STATUS_NO_SUPPORTED_IDP(
+ "urn:oasis:names:tc:SAML:2.0:status:NoSupportedIDP"), STATUS_PARTIAL_LOGOUT(
+ "urn:oasis:names:tc:SAML:2.0:status:PartialLogout"), STATUS_PROXYCOUNT_EXCEEDED(
+ "urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded"), STATUS_REQUEST_DENIED(
+ "urn:oasis:names:tc:SAML:2.0:status:RequestDenied"), STATUS_REQUEST_UNSUPPORTED(
+ "urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported"), STATUS_REQUEST_VERSION_DEPRECATED(
+ "urn:oasis:names:tc:SAML:2.0:status:RequestVersionDeprecated"), STATUS_REQUEST_VERSION_2HIGH(
+ "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooHigh"), STATUS_REQUEST_VERSION_2LOW(
+ "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooLow"), STATUS_RESOURCE_NOT_RECOGNIZED(
+ "urn:oasis:names:tc:SAML:2.0:status:ResourceNotRecognized"), STATUS_2MANY_RESPONSES(
+ "urn:oasis:names:tc:SAML:2.0:status:TooManyResponses"), STATUS_UNKNOWN_ATTR_PROFILE(
+ "urn:oasis:names:tc:SAML:2.0:status:UnknownAttributeProfile"), STATUS_UNKNOWN_PRINCIPAL(
+ "urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal"), 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(
+ "urn:oasis:names:tc:SAML:2.0:status:Responder"), 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(
+ "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(
+ "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(
+ "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 JBossSAMLURIConstants(String uristr) {
+ this.uri = uristr;
+ }
+
+ public String get() {
+ return this.uri;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/constants/PicketLinkCommonConstants.java b/saml-core/src/main/java/org/keycloak/saml/common/constants/PicketLinkCommonConstants.java
new file mode 100755
index 0000000..62162ca
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/constants/PicketLinkCommonConstants.java
@@ -0,0 +1,30 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.constants;
+
+/**
+ * Common Constants
+ * @author anil saldhana
+ * @since Jan 28, 2013
+ */
+public interface PicketLinkCommonConstants {
+
+ String PBE_ALGORITHM = "PBEwithMD5andDES";
+ // Prefix to indicate a particular configuration property value is masked
+ String PASS_MASK_PREFIX = "MASK-";
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/constants/SAMLAuthenticationContextClass.java b/saml-core/src/main/java/org/keycloak/saml/common/constants/SAMLAuthenticationContextClass.java
new file mode 100755
index 0000000..284bd73
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/constants/SAMLAuthenticationContextClass.java
@@ -0,0 +1,63 @@
+package org.keycloak.saml.common.constants;
+
+/**
+ * <p>A enum that maps a alias for each SAML Authentication Context Class.</p>
+ *
+ * @author pedroigor
+ */
+public enum SAMLAuthenticationContextClass {
+
+ INTERNET_PROTOCOL("internetProtocol", "urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocol"),
+ INTERNET_PROTOCOL_PASSWORD("internetProtocolPassword", "urn:oasis:names:tc:SAML:2.0:ac:classes:InternetProtocolPassword"),
+ KERBEROS("kerberos", "urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos"),
+ MOBILE_ONE_FACTOR_UNREGISTERED("mobileOneFactorUnregistered", "urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorUnregistered"),
+ MOBILE_TWO_FACTOR_UNREGISTERED("mobileTwoFactorUnregistered", "urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorUnregistered"),
+ MOBILE_ONE_FACTOR_CONTRACT("mobileOneFactorContract", "urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorContract"),
+ MOBILE_TWO_FACTOR_CONTRACT("mobileTwoFactorContract", "urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorContract"),
+ PASSWORD("password", "urn:oasis:names:tc:SAML:2.0:ac:classes:password"),
+ PASSWORD_PROTECTED_TRANSPORT("passwordProtectedTransport", "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"),
+ PREVIOUS_SESSION("previousSession", "urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession"),
+ X509("X509", "urn:oasis:names:tc:SAML:2.0:ac:classes:X509"),
+ PGP("PGP", "urn:oasis:names:tc:SAML:2.0:ac:classes:PGP"),
+ SPKI("SPKI", "urn:oasis:names:tc:SAML:2.0:ac:classes:SPKI"),
+ XMLDSig("XMLDSig", "urn:oasis:names:tc:SAML:2.0:ac:classes:XMLDSig"),
+ SMARTCARD("smartcard", "urn:oasis:names:tc:SAML:2.0:ac:classes:Smartcard"),
+ SMARTCARD_PKI("smartcardPKI", "urn:oasis:names:tc:SAML:2.0:ac:classes:SmartcardPKI"),
+ SOFTWARE_PKI("softwarePKI", "urn:oasis:names:tc:SAML:2.0:ac:classes:SoftwarePKI"),
+ TELEPHONY("telephony", "urn:oasis:names:tc:SAML:2.0:ac:classes:Telephony"),
+ NOMAD_TELEPHONY("nomadTelephony", "urn:oasis:names:tc:SAML:2.0:ac:classes:NomadTelephony"),
+ PERSONAL_TELEPHONY("personalTelephony", "urn:oasis:names:tc:SAML:2.0:ac:classes:PersonalTelephony"),
+ AUTHENTICATED_TELEPHONY("authenticatedTelephony", "urn:oasis:names:tc:SAML:2.0:ac:classes:AuthenticatedTelephony"),
+ SECURE_REMOTE_PASSWORD("secureRemotePassword", "urn:oasis:names:tc:SAML:2.0:ac:classes:SecureRemotePassword"),
+ TLSClient("TLSClient", "urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient"),
+ TIME_SYNC_TOKEN("timeSyncToken", "urn:oasis:names:tc:SAML:2.0:ac:classes:TimeSyncToken"),
+ UNSPECIFIED("unspecified", "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified");
+
+ private final String alias;
+ private final String fqn;
+
+ SAMLAuthenticationContextClass(final String alias, final String fqn) {
+ this.alias = alias;
+ this.fqn = fqn;
+ }
+
+ public String getAlias() {
+ return this.alias;
+ }
+
+ public String getFqn() {
+ return this.fqn;
+ }
+
+ public static SAMLAuthenticationContextClass forAlias(String alias) {
+ if (alias != null) {
+ for (SAMLAuthenticationContextClass contextClass: values()) {
+ if (contextClass.getAlias().equals(alias.trim())) {
+ return contextClass;
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/constants/WSTrustConstants.java b/saml-core/src/main/java/org/keycloak/saml/common/constants/WSTrustConstants.java
new file mode 100755
index 0000000..33e86ca
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/constants/WSTrustConstants.java
@@ -0,0 +1,246 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.saml.common.constants;
+
+import javax.xml.namespace.QName;
+
+/**
+ * <p> This class defines the constants used throughout the WS-Trust implementation code. </p>
+ *
+ * @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
+ * @author <a href="mailto:asaldhan@redhat.com">Anil Saldhana</a>
+ */
+public interface WSTrustConstants {
+
+ String BASE_NAMESPACE = "http://docs.oasis-open.org/ws-sx/ws-trust/200512";
+
+ String PREFIX = "wst";
+
+ // WS-Trust request types
+ String BATCH_ISSUE_REQUEST = BASE_NAMESPACE + "/BatchIssue";
+
+ String ISSUE_REQUEST = BASE_NAMESPACE + "/Issue";
+
+ String RENEW_REQUEST = BASE_NAMESPACE + "/Renew";
+
+ String CANCEL_REQUEST = BASE_NAMESPACE + "/Cancel";
+
+ String VALIDATE_REQUEST = BASE_NAMESPACE + "/Validate";
+
+ String BATCH_VALIDATE_REQUEST = BASE_NAMESPACE + "/BatchValidate";
+
+ // WS-Trust validation constants.
+ String STATUS_TYPE = BASE_NAMESPACE + "/RSTR/Status";
+
+ String STATUS_CODE_VALID = BASE_NAMESPACE + "/status/valid";
+
+ String STATUS_CODE_INVALID = BASE_NAMESPACE + "/status/invalid";
+
+ // WS-Trust key types.
+ String KEY_TYPE_BEARER = BASE_NAMESPACE + "/Bearer";
+
+ String KEY_TYPE_SYMMETRIC = BASE_NAMESPACE + "/SymmetricKey";
+
+ String KEY_TYPE_PUBLIC = BASE_NAMESPACE + "/PublicKey";
+
+ // WS-Trust binary secret types.
+ String BS_TYPE_ASYMMETRIC = BASE_NAMESPACE + "/AsymmetricKey";
+
+ String BS_TYPE_SYMMETRIC = BASE_NAMESPACE + "/SymmetricKey";
+
+ String BS_TYPE_NONCE = BASE_NAMESPACE + "/Nonce";
+
+ // WS-Trust computed key types.
+ String CK_PSHA1 = BASE_NAMESPACE + "/CK/PSHA1";
+
+ // WSS namespaces values.
+ String WSA_NS = "http://www.w3.org/2005/08/addressing";
+
+ String WSP_NS = "http://schemas.xmlsoap.org/ws/2004/09/policy";
+
+ String WSP_15_NS = "http://www.w3.org/ns/ws-policy";
+
+ String WSU_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
+
+ String WSSE_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
+
+ String WSSE11_NS = "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd";
+
+ String XENC_NS = "http://www.w3.org/2001/04/xmlenc#";
+
+ String DSIG_NS = "http://www.w3.org/2000/09/xmldsig#";
+
+ String SAML2_ASSERTION_NS = "urn:oasis:names:tc:SAML:2.0:assertion";
+
+ // WSS Fault codes
+ QName SECURITY_TOKEN_UNAVAILABLE = new QName(WSSE_NS, "SecurityTokenUnavailable");
+
+ QName INVALID_SECURITY_TOKEN = new QName(WSSE_NS, "InvalidSecurityToken");
+
+ QName INVALID_SECURITY = new QName(WSSE_NS, "InvalidSecurity");
+
+ QName FAILED_AUTHENTICATION = new QName(WSSE_NS, "FailedAuthentication");
+
+ // Token Types
+ String RSTR_STATUS_TOKEN_TYPE = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/Status";
+
+ // Element Names
+ String BINARY_SECRET = "BinarySecret";
+
+ String CREATED = "Created";
+
+ String COMPUTED_KEY_ALGORITHM = "ComputedKeyAlgorithm";
+
+ String ENTROPY = "Entropy";
+
+ String EXPIRES = "Expires";
+
+ String ISSUER = "Issuer";
+
+ String ON_BEHALF_OF = "OnBehalfOf";
+
+ String COMPUTED_KEY = "ComputedKey";
+
+ String KEY_SIZE = "KeySize";
+
+ String KEY_TYPE = "KeyType";
+
+ String LIFETIME = "Lifetime";
+
+ String RENEWING = "Renewing";
+
+ String RST = "RequestSecurityToken";
+
+ String RSTR = "RequestSecurityTokenResponse";
+
+ String RST_COLLECTION = "RequestSecurityTokenCollection";
+
+ String RSTR_COLLECTION = "RequestSecurityTokenResponseCollection";
+
+ String REQUESTED_TOKEN = "RequestedSecurityToken";
+
+ String REQUESTED_TOKEN_CANCELLED = "RequestedTokenCancelled";
+
+ String REQUESTED_PROOF_TOKEN = "RequestedProofToken";
+
+ String REQUESTED_ATTACHED_REFERENCE = "RequestedAttachedReference";
+
+ String REQUESTED_UNATTACHED_REFERENCE = "RequestedUnattachedReference";
+
+ String REQUEST_TYPE = "RequestType";
+
+ String TOKEN_TYPE = "TokenType";
+
+ String CANCEL_TARGET = "CancelTarget";
+
+ String RENEW_TARGET = "RenewTarget";
+
+ String SECONDARY_PARAMETERS = "SecondaryParameters";
+
+ String VALIDATE_TARGET = "ValidateTarget";
+
+ String USE_KEY = "UseKey";
+
+ String STATUS = "Status";
+
+ String CODE = "Code";
+
+ String REASON = "Reason";
+
+ // Attribute Names
+ String ALLOW = "Allow";
+
+ String OK = "OK";
+
+ String RST_CONTEXT = "Context";
+
+ String TYPE = "Type";
+
+ String VALUE_TYPE = "ValueType";
+
+ public interface XMLDSig {
+
+ String DSIG_NS = "http://www.w3.org/2000/09/xmldsig#";
+
+ String EXPONENT = "Exponent";
+
+ String KEYINFO = "KeyInfo";
+
+ String KEYVALUE = "KeyValue";
+
+ String MODULUS = "Modulus";
+
+ String DSIG_PREFIX = "ds";
+
+ String RSA_KEYVALUE = "RSAKeyValue";
+
+ String DSA_KEYVALUE = "DSAKeyValue";
+
+ String X509DATA = "X509Data";
+
+ String X509CERT = "X509Certificate";
+
+ String P = "P";
+ String Q = "Q";
+ String G = "G";
+ String Y = "Y";
+ String SEED = "Seed";
+ String PGEN_COUNTER = "PgenCounter";
+ }
+
+ public interface XMLEnc {
+
+ String XMLENC_NS = "http://www.w3.org/2001/04/xmlenc#";
+
+ String ENCRYPTED_KEY = "EncryptedKey";
+ }
+
+ public interface WSSE {
+
+ String ID = "Id";
+
+ String KEY_IDENTIFIER = "KeyIdentifier";
+
+ String KEY_IDENTIFIER_VALUETYPE_SAML = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID";
+
+ String REFERENCE = "Reference";
+
+ String PREFIX = "wsse";
+
+ String PREFIX_11 = "wsse11";
+
+ // http://www.ws-i.org/Profiles/KerberosTokenProfile-1.0.html#Kerberos_Security_Token_URI
+ String KERBEROS = "http://docs.oasis-open.org/wss/2005/xx/oasis-2005xx-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ";
+
+ String SECURITY_TOKEN_REFERENCE = "SecurityTokenReference";
+
+ String BINARY_SECURITY_TOKEN = "BinarySecurityToken";
+
+ String USERNAME_TOKEN = "UsernameToken";
+
+ String URI = "URI";
+
+ String VALUE_TYPE = "ValueType";
+
+ String ENCODING_TYPE = "EncodingType";
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/ErrorCodes.java b/saml-core/src/main/java/org/keycloak/saml/common/ErrorCodes.java
new file mode 100755
index 0000000..70fc27d
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/ErrorCodes.java
@@ -0,0 +1,206 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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;
+
+/**
+ * Error Codes for PicketLink https://docs.jboss.org/author/display/PLINK/PicketLink+Error+Codes
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Aug 4, 2011
+ */
+public interface ErrorCodes {
+
+ String ASSERTION_RENEWAL_EXCEPTION = "PL00103:Assertion Renewal Exception:";
+
+ String AUDIT_MANAGER_NULL = "PL00028: Audit Manager Is Not Set";
+
+ String AUTHENTICATOR_DOES_NOT_HANDLE_ENC = "PL00027: Authenticator does not handle encryption";
+
+ String AUTHN_REQUEST_ID_VERIFICATION_FAILED = "PL00104:Authn Request ID verification failed:";
+
+ String CLASS_NOT_LOADED = "PL00085: Class Not Loaded:";
+
+ String CANNOT_CREATE_INSTANCE = "PL00086: Cannot create instance of:";
+
+ String DOM_MISSING_DOC_ELEMENT = "PL00098: Missing Document Element:";
+
+ String DOM_MISSING_ELEMENT = "PL00099: Missing Element:";
+
+ String ENCRYPTION_PROCESS_FAILURE = "PL00101: Encryption Process Failure:";
+
+ String EXPIRED_ASSERTION = "PL00079: Assertion has expired:";
+
+ String EXPECTED_XSI = "PL00072: Parser: Expected xsi:type";
+
+ String EXPECTED_TAG = "PL00066: Parser : Expected start tag:";
+
+ String EXPECTED_TEXT_VALUE = "PL00071: Parser: Expected text value:";
+
+ String EXPECTED_END_TAG = "PL00066: Parser : Expected end tag:";
+
+ String FAILED_PARSING = "PL00067: Parsing has failed:";
+
+ String FILE_NOT_LOCATED = "PL00075: File could not be located :";
+
+ String IDP_AUTH_FAILED = "PL00015: IDP Authentication Failed:";
+
+ String IDP_WEBBROWSER_VALVE_ALREADY_STARTED = "PL00021: IDPWebBrowserSSOValve already Started";
+
+ String IDP_WEBBROWSER_VALVE_CONF_FILE_MISSING = "PL00017: Configuration File missing:";
+
+ String IDP_WEBBROWSER_VALVE_NOT_STARTED = "PL00024: IDPWebBrowserSSOValve NotStarted";
+
+ String ILLEGAL_METHOD_CALLED = "PL00020: Illegal Method Called";
+
+ String INVALID_ASSERTION = "PL00080: Invalid Assertion:";
+
+ String INVALID_DIGITAL_SIGNATURE = "PL00009: Invalid Digital Signature:";
+
+ String INJECTED_VALUE_MISSING = "PL00077: Injected Value Missing:";
+
+ String ISSUER_INFO_MISSING_STATUS_CODE = "PL00085: IssuerInfo missing status code :";
+
+ String KEYSTOREKEYMGR_DOMAIN_ALIAS_MISSING = "PL00058: KeyStoreKeyManager : Domain Alias missing for :";
+
+ String KEYSTOREKEYMGR_NULL_ALIAS = "PL00059: KeyStoreKeyManager : Alias is null";
+
+ String KEYSTOREKEYMGR_NULL_KEYSTORE = "PL00055: KeyStoreKeyManager : KeyStore is null";
+
+ String KEYSTOREKEYMGR_NULL_SIGNING_KEYPASS = "PL00057: KeyStoreKeyManager :: Signing Key Pass is null";
+
+ String KEYSTOREKEYMGR_NULL_ENCRYPTION_KEYPASS = "PL00189: KeyStoreKeyManager :: Encryption Key Pass is null";
+
+ String KEYSTOREKEYMGR_KEYSTORE_NOT_LOCATED = "PL00056: KeyStoreKeyManager: Keystore not located:";
+
+ String NOT_EQUAL = "PL00094: Not equal:";
+
+ String NOT_IMPLEMENTED_YET = "PL00082: Not Implemented Yet: ";
+
+ String NOT_SERIALIZABLE = "PL00093: Not Serializable:";
+
+ String NULL_ARGUMENT = "PL00078: Null Parameter:";
+
+ String NULL_ASSERTION = "PL00054: Assertion is null";
+
+ String NULL_ISSUE_INSTANT = "PL00088: Null IssueInstant";
+
+ String NULL_INPUT_STREAM = "PL00060: Input Stream is null";
+
+ String NULL_START_ELEMENT = "PL00068: Parser : Start Element is null";
+
+ String NULL_VALUE = "PL00092: Null Value:";
+
+ String OPTION_NOT_SET = "PL00076: Option not set:";
+
+ String PARSING_ERROR = "PL00074: Parsing Error:";
+
+ String PRINCIPAL_NOT_FOUND = "PL00022: Principal Not Found";
+
+ String PROCESSING_EXCEPTION = "PL00102: Processing Exception:";
+
+ String REQD_ATTRIBUTE = "PL00063: Parser: Required attribute missing: ";
+
+ String RESOURCE_NOT_FOUND = "PL00018: Resource not found:";
+
+ String SAML2STSLM_CONF_FILE_MISSING = "PL00039: SAML2STSLoginModule: Failed to validate assertion: STS configuration file not specified";
+
+ String SAML2STSLM_UNABLE_DECODE_PWD = "PL00047: SAML2STSLoginModule: Unable to decode password:";
+
+ String SERVICE_PROVIDER_CONF_FILE_MISSING = "PL00025: Service Provider:: Configuration File missing:";
+
+ String SERVICE_PROVIDER_NOT_CATALINA_RESPONSE = "PL00026: Response was not of type catalina response";
+
+ String SERVICE_PROVIDER_SERVER_EXCEPTION = "PL00032: Service Provider :: Server Exception";
+
+ String SHOULD_NOT_BE_THE_SAME = "PL00016: Should not be the same:";
+
+ String SIGNING_PROCESS_FAILURE = "PL00100: Signing Process Failure:";
+
+ String STS_CLIENT_PUBLIC_KEY_ERROR = "PL00008: Unable to locate client public key";
+
+ String STS_CONFIGURATION_NOT_SET = "PL00014: Configuration is not set";
+
+ String STS_CONFIGURATION_FILE_PARSING_ERROR = "PL00005: Error parsing the configuration file:";
+
+ String STS_CONFIGURATION_EXCEPTION = "PL00002: Encountered configuration exception:";
+
+ String STS_COMBINED_SECRET_KEY_ERROR = "PL00006: Error generating combined secret key:";
+
+ String STS_EXCEPTION_HANDLING_TOKEN_REQ = "PL00003: Exception in handling token request: ";
+
+ String STS_NO_TOKEN_PROVIDER = "PL00013: No Security Token Provider found in configuration:[";
+
+ String STS_INVALID_TOKEN_REQUEST = "PL00001: Invalid security token request";
+
+ String STS_INVALID_REQUEST_TYPE = "PL00001: Invalid request type: ";
+
+ String STS_PUBLIC_KEY_ERROR = "PL00010: Error obtaining public key for service: ";
+
+ String STS_PUBLIC_KEY_CERT = "PL00012: Error obtaining public key certificate:";
+
+ String STS_RESPONSE_WRITING_ERROR = "PL00004: Error writing response: ";
+
+ String STS_SIGNING_KEYPAIR_ERROR = "PL00011: Error obtaining signing key pair:";
+
+ String STS_UNABLE_TO_CONSTRUCT_KEYMGR = "PL00007: Unable to construct the key manager:";
+
+ String SYSTEM_PROPERTY_MISSING = "PL00087: System Property missing:";
+
+ String TRUST_MANAGER_MISSING = "PL000023: Trust Key Manager Missing";
+
+ String UNABLE_PARSING_NULL_TOKEN = "PL00073: Parser: Unable to parse token request: security token is null";
+
+ String UNABLE_LOCAL_AUTH = "PL00035: Unable to fallback on local auth:";
+
+ String UNKNOWN_END_ELEMENT = "PL00061: Parser: Unknown End Element:";
+
+ String UNKNOWN_OBJECT_TYPE = "PL00089: Unknown Object Type:";
+
+ String UNKNOWN_START_ELEMENT = "PL00064: Parser: Unknown Start Element: ";
+
+ String UNKNOWN_SIG_ALGO = "PL00090: Unknown Signature Algorithm:";
+
+ String UNKNOWN_ENC_ALGO = "PL00097: Unknown Encryption Algorithm:";
+
+ String UNKNOWN_TAG = "PL00062: Parser : Unknown tag:";
+
+ String UNKNOWN_XSI = "PL0065: Parser : Unknown xsi:type=";
+
+ String UNSUPPORTED_TYPE = "PL00069: Parser: Type not supported:";
+
+ String VALIDATION_CHECK_FAILED = "PL00019: Validation check failed";
+
+ String WRITER_INVALID_KEYINFO_NULL_CONTENT = "PL00091: Writer: Invalid KeyInfo object: content cannot be empty";
+
+ String WRITER_NULL_VALUE = "PL00083: Writer: Null Value:";
+
+ String WRITER_SHOULD_START_ELEMENT = "PL00096: Writer: Should have been a StartElement";
+
+ String WRITER_UNKNOWN_TYPE = "PL00081: Writer: Unknown Type:";
+
+ String WRITER_UNSUPPORTED_ATTRIB_VALUE = "PL00084: Writer: Unsupported Attribute Value:";
+
+ String WRONG_TYPE = "PL00095: Wrong type:";
+
+ String SOAP_MESSAGE_DUMP_ERROR = "PL00104: Error while dumping SOAP message:";
+
+ String LOCAL_VALIDATION_SEC_DOMAIN_MUST_BE_SPECIFIED = "PL00105: When using local validation 'localValidationSecurityDomain' must be specified.";
+
+ String COMPRESSION_ENABLED_SAML_CRED = "When compression is enabled, received credential should be SamlCredential, but got ";
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ConfigurationException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ConfigurationException.java
new file mode 100755
index 0000000..4a377b0
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ConfigurationException.java
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Exception indicating an issue with the configuration
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since May 22, 2009
+ */
+public class ConfigurationException extends GeneralSecurityException {
+
+ public ConfigurationException() {
+ super();
+ }
+
+ public ConfigurationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ConfigurationException(String message) {
+ super(message);
+ }
+
+ public ConfigurationException(Throwable cause) {
+ super(cause);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/AssertionExpiredException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/AssertionExpiredException.java
new file mode 100755
index 0000000..746c072
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/AssertionExpiredException.java
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions.fed;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Security Exception indicating expiration of SAML2 assertion
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 12, 2008
+ */
+public class AssertionExpiredException extends GeneralSecurityException {
+
+ protected String id;
+
+ public AssertionExpiredException() {
+ }
+
+ public AssertionExpiredException(String message, Throwable cause) {
+ }
+
+ public AssertionExpiredException(String msg) {
+ super(msg);
+ }
+
+ public AssertionExpiredException(Throwable cause) {
+ super(cause);
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/IssueInstantMissingException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/IssueInstantMissingException.java
new file mode 100755
index 0000000..e8cbd56
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/IssueInstantMissingException.java
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions.fed;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Exception indicating that the IssueInstant is missing
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jun 3, 2009
+ */
+public class IssueInstantMissingException extends GeneralSecurityException {
+
+ public IssueInstantMissingException() {
+ super();
+ }
+
+ public IssueInstantMissingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public IssueInstantMissingException(String msg) {
+ super(msg);
+ }
+
+ public IssueInstantMissingException(Throwable cause) {
+ super(cause);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/IssuerNotTrustedException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/IssuerNotTrustedException.java
new file mode 100755
index 0000000..02820ee
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/IssuerNotTrustedException.java
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions.fed;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Exception indicating that the issuer is not trusted
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jan 26, 2009
+ */
+public class IssuerNotTrustedException extends GeneralSecurityException {
+
+ public IssuerNotTrustedException() {
+ super();
+ }
+
+ public IssuerNotTrustedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public IssuerNotTrustedException(String msg) {
+ super(msg);
+ }
+
+ public IssuerNotTrustedException(Throwable cause) {
+ super(cause);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/SignatureValidationException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/SignatureValidationException.java
new file mode 100755
index 0000000..bfafecd
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/SignatureValidationException.java
@@ -0,0 +1,44 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions.fed;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Indicates the failure of signature validation
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jul 28, 2011
+ */
+public class SignatureValidationException extends GeneralSecurityException {
+
+ public SignatureValidationException() {
+ }
+
+ public SignatureValidationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public SignatureValidationException(String msg) {
+ super(msg);
+ }
+
+ public SignatureValidationException(Throwable cause) {
+ super(cause);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/WSTrustException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/WSTrustException.java
new file mode 100755
index 0000000..937ebb6
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/fed/WSTrustException.java
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions.fed;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * <p>
+ * Exception used to convey that an error has happened when handling a WS-Trust request message.
+ * </p>
+ *
+ * @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
+ */
+public class WSTrustException extends GeneralSecurityException {
+
+ /**
+ * <p>
+ * Creates an instance of {@code WSTrustException} using the specified error message.
+ * </p>
+ *
+ * @param message the error message.
+ */
+ public WSTrustException(String message) {
+ super(message);
+ }
+
+ /**
+ * <p>
+ * Creates an instance of {@code WSTrustException} using the specified error message and cause.
+ * </p>
+ *
+ * @param message the error message.
+ * @param cause a {@code Throwable} representing the cause of the error.
+ */
+ public WSTrustException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * <p>
+ * Creates an instance of {@code WSTrustException} using the specified {@link Throwable}.
+ * </p>
+ *
+ * @param message the error message.
+ */
+ public WSTrustException(Throwable t) {
+ super(t);
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/NotImplementedException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/NotImplementedException.java
new file mode 100755
index 0000000..e49603a
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/NotImplementedException.java
@@ -0,0 +1,36 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.saml.common.exceptions;
+
+/**
+ * <p>An exception that indicates that something is not ready for use. Usually, this exception is thrown from methods not
+ * fully implemented or tested but available for invocation.</p>
+ *
+ * @author Pedro Igor
+ */
+public class NotImplementedException extends PicketLinkException {
+
+ public NotImplementedException(String message) {
+ super(message);
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ParsingException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ParsingException.java
new file mode 100755
index 0000000..ea1fa2b
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ParsingException.java
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions;
+
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import java.security.GeneralSecurityException;
+
+/**
+ * General Exception indicating parsing exception
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since May 22, 2009
+ */
+public class ParsingException extends GeneralSecurityException {
+
+ private Location location;
+
+ public ParsingException() {
+ super();
+ }
+
+ public ParsingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ParsingException(String message) {
+ super(message);
+ }
+
+ public ParsingException(Throwable cause) {
+ super(cause);
+ }
+
+ public ParsingException(XMLStreamException xmle) {
+ super(xmle);
+ location = xmle.getLocation();
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ @Override
+ public String toString() {
+ return "ParsingException [location=" + location + "]" + super.toString();
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/PicketLinkException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/PicketLinkException.java
new file mode 100755
index 0000000..799e377
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/PicketLinkException.java
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions;
+
+/**
+ * <p>Any exception that is raised by the security module extends from this runtime exception class, making it easy for
+ * other modules and extensions to catch all security-related exceptions in a single catch block, if need be.
+ * </p>
+ *
+ * <p>This class is used as the root instead of {@link SecurityException} to avoid confusion and potential conflicts. Eg.: many other
+ * frameworks and products (eg.: JEE containers) relies on the {@link SecurityException} to perform some special handling.</p>
+ */
+public class PicketLinkException extends RuntimeException {
+
+ public PicketLinkException() {
+ super();
+ }
+
+ public PicketLinkException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public PicketLinkException(String message) {
+ super(message);
+ }
+
+ public PicketLinkException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ProcessingException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ProcessingException.java
new file mode 100755
index 0000000..2b88e2f
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/ProcessingException.java
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Exception to indicate a server processing error
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since May 22, 2009
+ */
+public class ProcessingException extends GeneralSecurityException {
+
+ public ProcessingException() {
+ super();
+ }
+
+ public ProcessingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ProcessingException(String message) {
+ super(message);
+ }
+
+ public ProcessingException(Throwable cause) {
+ super(cause);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/TrustKeyConfigurationException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/TrustKeyConfigurationException.java
new file mode 100755
index 0000000..7f88085
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/TrustKeyConfigurationException.java
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions;
+
+/**
+ * ConfigurationException in the TrustKeyManager
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since May 22, 2009
+ */
+public class TrustKeyConfigurationException extends ConfigurationException {
+
+ public TrustKeyConfigurationException() {
+ super();
+ }
+
+ public TrustKeyConfigurationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TrustKeyConfigurationException(String message) {
+ super(message);
+ }
+
+ public TrustKeyConfigurationException(Throwable cause) {
+ super(cause);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/exceptions/TrustKeyProcessingException.java b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/TrustKeyProcessingException.java
new file mode 100755
index 0000000..b900f0e
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/exceptions/TrustKeyProcessingException.java
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions;
+
+/**
+ * Processing Exception in the trust key manager
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since May 22, 2009
+ */
+public class TrustKeyProcessingException extends ProcessingException {
+
+ public TrustKeyProcessingException() {
+ super();
+ }
+
+ public TrustKeyProcessingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TrustKeyProcessingException(String message) {
+ super(message);
+ }
+
+ public TrustKeyProcessingException(Throwable cause) {
+ super(cause);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/parsers/AbstractParser.java b/saml-core/src/main/java/org/keycloak/saml/common/parsers/AbstractParser.java
new file mode 100755
index 0000000..dc25f17
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/parsers/AbstractParser.java
@@ -0,0 +1,141 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.constants.GeneralConstants;
+import org.keycloak.saml.common.exceptions.ParsingException;
+import org.keycloak.saml.common.util.StaxParserUtil;
+import org.keycloak.saml.common.util.SystemPropertiesUtil;
+
+import javax.xml.stream.EventFilter;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Characters;
+import javax.xml.stream.events.XMLEvent;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Base class for parsers
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Oct 12, 2010
+ */
+public abstract class AbstractParser implements ParserNamespaceSupport {
+
+ protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * Get the JAXP {@link XMLInputFactory}
+ *
+ * @return
+ */
+ protected XMLInputFactory getXMLInputFactory() {
+ boolean tccl_jaxp = SystemPropertiesUtil.getSystemProperty(GeneralConstants.TCCL_JAXP, "false")
+ .equalsIgnoreCase("true");
+ ClassLoader prevTCCL = getTCCL();
+ try {
+ if (tccl_jaxp) {
+ setTCCL(getClass().getClassLoader());
+ }
+ return XMLInputFactory.newInstance();
+ } finally {
+ if (tccl_jaxp) {
+ setTCCL(prevTCCL);
+ }
+ }
+ }
+
+ /**
+ * Parse an InputStream for payload
+ *
+ * @param configStream
+ *
+ * @return
+ *
+ * @throws {@link IllegalArgumentException}
+ * @throws {@link IllegalArgumentException} when the configStream is null
+ */
+ public Object parse(InputStream configStream) throws ParsingException {
+ XMLEventReader xmlEventReader = createEventReader(configStream);
+ return parse(xmlEventReader);
+ }
+
+ public XMLEventReader createEventReader(InputStream configStream) throws ParsingException {
+ if (configStream == null)
+ throw logger.nullArgumentError("InputStream");
+
+ XMLInputFactory xmlInputFactory = getXMLInputFactory();
+
+ XMLEventReader xmlEventReader = StaxParserUtil.getXMLEventReader(configStream);
+
+ try {
+ xmlEventReader = xmlInputFactory.createFilteredReader(xmlEventReader, new EventFilter() {
+ public boolean accept(XMLEvent xmlEvent) {
+ // We are going to disregard characters that are new line and whitespace
+ if (xmlEvent.isCharacters()) {
+ Characters chars = xmlEvent.asCharacters();
+ String data = chars.getData();
+ data = valid(data) ? data.trim() : null;
+ return valid(data);
+ } else {
+ return xmlEvent.isStartElement() || xmlEvent.isEndElement();
+ }
+ }
+
+ private boolean valid(String str) {
+ return str != null && str.length() > 0;
+ }
+ });
+ } catch (XMLStreamException e) {
+ throw logger.parserException(e);
+ }
+
+ return xmlEventReader;
+ }
+
+ private ClassLoader getTCCL() {
+ if (System.getSecurityManager() != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ } else {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ }
+
+ private void setTCCL(final ClassLoader paramCl) {
+ if (System.getSecurityManager() != null) {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ Thread.currentThread().setContextClassLoader(paramCl);
+ return null;
+ }
+ });
+ } else {
+ Thread.currentThread().setContextClassLoader(paramCl);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/parsers/ParserNamespaceSupport.java b/saml-core/src/main/java/org/keycloak/saml/common/parsers/ParserNamespaceSupport.java
new file mode 100755
index 0000000..197143c
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/parsers/ParserNamespaceSupport.java
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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 javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventReader;
+
+/**
+ * <p>
+ * 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 {
+ /**
+ * Parse the event stream
+ *
+ * @param xmlEventReader
+ * @return
+ * @throws ParsingException
+ */
+ Object parse(XMLEventReader xmlEventReader) throws ParsingException;
+
+ /**
+ * Returns whether the parser supports parsing a particular namespace
+ *
+ * @param qname
+ * @return
+ */
+ boolean supports(QName qname);
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/PicketLinkLoggerFactory.java b/saml-core/src/main/java/org/keycloak/saml/common/PicketLinkLoggerFactory.java
new file mode 100755
index 0000000..6461eaa
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/PicketLinkLoggerFactory.java
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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;
+
+/**
+ * <p> Factory class to create {@link PicketLinkLogger} instances. </p> <p> The logger instances are created based on
+ * the following patterns: <br/> <ul> <li>Tries to load a class with the same full qualified name of {@link
+ * PicketLinkLogger} plus the "Impl" suffix;</li> <li>If no class is found fallback to the {@link
+ * DefaultPicketLinkLogger} as the default logger implementation.</li> </ul> </p>
+ *
+ * @author <a href="mailto:psilva@redhat.com">Pedro Silva</a>
+ */
+public final class PicketLinkLoggerFactory {
+
+ private static PicketLinkLogger LOGGER;
+
+ static {
+ try {
+ LOGGER = (PicketLinkLogger) Class.forName(PicketLinkLogger.class.getName() + "Impl").newInstance();
+ } catch (Exception e) {
+ // if no implementation is found uses the default implementation.
+ LOGGER = new DefaultPicketLinkLogger();
+ }
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.usingLoggerImplementation(LOGGER.getClass().getName());
+ }
+ }
+
+ /**
+ * <p>Returns a {@link PicketLinkLogger} instance.</p>
+ *
+ * @return
+ */
+ public static PicketLinkLogger getLogger() {
+ return LOGGER;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/util/SecurityActions.java b/saml-core/src/main/java/org/keycloak/saml/common/util/SecurityActions.java
new file mode 100755
index 0000000..24bd70b
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/util/SecurityActions.java
@@ -0,0 +1,221 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 9, 2008
+ */
+class SecurityActions {
+
+ /**
+ * <p> Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
+ * the specified {@link Class}, if not found it will try to load from using TCL. </p>
+ *
+ * @param theClass
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ });
+ } else {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ }
+
+ /**
+ * <p> Loads a class from the specified {@link ClassLoader} using the <code>fullQualifiedName</code> supplied. </p>
+ *
+ * @param classLoader
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ });
+ } else {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Load a resource based on the passed {@link Class} classloader. Failing which try with the Thread Context CL
+ *
+ * @param clazz
+ * @param resourceName
+ *
+ * @return
+ */
+ static URL loadResource(final Class<?> clazz, final String resourceName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<URL>() {
+ public URL run() {
+ URL url = null;
+ ClassLoader clazzLoader = clazz.getClassLoader();
+ url = clazzLoader.getResource(resourceName);
+
+ if (url == null) {
+ clazzLoader = Thread.currentThread().getContextClassLoader();
+ url = clazzLoader.getResource(resourceName);
+ }
+
+ return url;
+ }
+ });
+ } else {
+ URL url = null;
+ ClassLoader clazzLoader = clazz.getClassLoader();
+ url = clazzLoader.getResource(resourceName);
+
+ if (url == null) {
+ clazzLoader = Thread.currentThread().getContextClassLoader();
+ url = clazzLoader.getResource(resourceName);
+ }
+
+ return url;
+ }
+ }
+
+ /**
+ * Set the system property
+ *
+ * @param key
+ * @param defaultValue
+ *
+ * @return
+ */
+ static void setSystemProperty(final String key, final String value) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ System.setProperty(key, value);
+ return null;
+ }
+ });
+ } else {
+ System.setProperty(key, value);
+ }
+ }
+
+ /**
+ * <p>Returns a system property value using the specified <code>key</code>. If not found the
+ * <code>defaultValue</code> will be returned.</p>
+ *
+ * @param key
+ * @param defaultValue
+ *
+ * @return
+ */
+ static String getSystemProperty(final String key, final String defaultValue) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(key, defaultValue);
+ }
+ });
+ } else {
+ return System.getProperty(key, defaultValue);
+ }
+ }
+
+ /**
+ * Get the Thread Context ClassLoader
+ *
+ * @return
+ */
+ static ClassLoader getTCCL() {
+ if (System.getSecurityManager() != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ } else {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ }
+
+ /**
+ * Set the Thread Context ClassLoader
+ *
+ * @param paramCl
+ */
+ static void setTCCL(final ClassLoader paramCl) {
+ if (System.getSecurityManager() != null) {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ Thread.currentThread().setContextClassLoader(paramCl);
+ return null;
+ }
+ });
+ } else {
+
+ Thread.currentThread().setContextClassLoader(paramCl);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/util/StaxUtil.java b/saml-core/src/main/java/org/keycloak/saml/common/util/StaxUtil.java
new file mode 100755
index 0000000..be4ef43
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/util/StaxUtil.java
@@ -0,0 +1,447 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.Result;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.Stack;
+
+/**
+ * Utility class that deals with StAX
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Oct 19, 2010
+ */
+public class StaxUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ private static ThreadLocal<Stack<String>> registeredNSStack = new ThreadLocal<Stack<String>>();
+
+ /**
+ * Flush the stream writer
+ *
+ * @param writer
+ *
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ */
+ public static void flush(XMLStreamWriter writer) throws ProcessingException {
+ try {
+ writer.flush();
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Get an {@code XMLEventWriter}
+ *
+ * @param outStream
+ *
+ * @return
+ *
+ * @throws ProcessingException
+ */
+ public static XMLEventWriter getXMLEventWriter(final OutputStream outStream) throws ProcessingException {
+ XMLOutputFactory xmlOutputFactory = getXMLOutputFactory();
+ try {
+ return xmlOutputFactory.createXMLEventWriter(outStream, "UTF-8");
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Get an {@code XMLStreamWriter}
+ *
+ * @param outStream
+ *
+ * @return
+ *
+ * @throws ProcessingException
+ */
+ public static XMLStreamWriter getXMLStreamWriter(final OutputStream outStream) throws ProcessingException {
+ XMLOutputFactory xmlOutputFactory = getXMLOutputFactory();
+ try {
+ return xmlOutputFactory.createXMLStreamWriter(outStream, "UTF-8");
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Get an {@code XMLStreamWriter}
+ *
+ * @param writer {@code Writer}
+ *
+ * @return
+ *
+ * @throws ProcessingException
+ */
+ public static XMLStreamWriter getXMLStreamWriter(final Writer writer) throws ProcessingException {
+ XMLOutputFactory xmlOutputFactory = getXMLOutputFactory();
+ try {
+ return xmlOutputFactory.createXMLStreamWriter(writer);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ public static XMLStreamWriter getXMLStreamWriter(final Result result) throws ProcessingException {
+ XMLOutputFactory factory = getXMLOutputFactory();
+ try {
+ return factory.createXMLStreamWriter(result);
+ } catch (XMLStreamException xe) {
+ throw logger.processingError(xe);
+ }
+ }
+
+ /**
+ * Set a prefix
+ *
+ * @param writer
+ * @param prefix
+ * @param nsURI
+ *
+ * @throws ProcessingException
+ */
+ public static void setPrefix(XMLStreamWriter writer, String prefix, String nsURI) throws ProcessingException {
+ try {
+ writer.setPrefix(prefix, nsURI);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Write an attribute
+ *
+ * @param writer
+ * @param attributeName QName of the attribute
+ * @param attributeValue
+ *
+ * @throws ProcessingException
+ */
+ public static void writeAttribute(XMLStreamWriter writer, String attributeName, QName attributeValue)
+ throws ProcessingException {
+ writeAttribute(writer, attributeName, attributeValue.toString());
+ }
+
+ /**
+ * Write an attribute
+ *
+ * @param writer
+ * @param attributeName QName of the attribute
+ * @param attributeValue
+ *
+ * @throws ProcessingException
+ */
+ public static void writeAttribute(XMLStreamWriter writer, QName attributeName, String attributeValue)
+ throws ProcessingException {
+ try {
+ writer.writeAttribute(attributeName.getPrefix(), attributeName.getNamespaceURI(), attributeName.getLocalPart(),
+ attributeValue);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Write an xml attribute
+ *
+ * @param writer
+ * @param localName localpart
+ * @param value value of the attribute
+ *
+ * @throws ProcessingException
+ */
+ public static void writeAttribute(XMLStreamWriter writer, String localName, String value) throws ProcessingException {
+ try {
+ writer.writeAttribute(localName, value);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Write an xml attribute
+ *
+ * @param writer
+ * @param localName localpart
+ * @param type typically xsi:type
+ * @param value value of the attribute
+ *
+ * @throws ProcessingException
+ */
+ public static void writeAttribute(XMLStreamWriter writer, String localName, String type, String value)
+ throws ProcessingException {
+ try {
+ writer.writeAttribute(localName, type, value);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Write an xml attribute
+ *
+ * @param writer
+ * @param prefix prefix for the attribute
+ * @param localName localpart
+ * @param type typically xsi:type
+ * @param value value of the attribute
+ *
+ * @throws ProcessingException
+ */
+ public static void writeAttribute(XMLStreamWriter writer, String prefix, String localName, String type, String value)
+ throws ProcessingException {
+ try {
+ writer.writeAttribute(prefix, localName, type, value);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Write a string as text node
+ *
+ * @param writer
+ * @param value
+ *
+ * @throws ProcessingException
+ */
+ public static void writeCharacters(XMLStreamWriter writer, String value) throws ProcessingException {
+ try {
+ writer.writeCharacters(value);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Write a string as text node
+ *
+ * @param writer
+ * @param value
+ *
+ * @throws ProcessingException
+ */
+ public static void writeCData(XMLStreamWriter writer, String value) throws ProcessingException {
+ try {
+ writer.writeCData(value);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Write the default namespace
+ *
+ * @param writer
+ * @param ns
+ *
+ * @throws ProcessingException
+ */
+ public static void writeDefaultNameSpace(XMLStreamWriter writer, String ns) throws ProcessingException {
+ try {
+ writer.writeDefaultNamespace(ns);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Write a DOM Node to the stream
+ *
+ * @param writer
+ * @param node
+ *
+ * @throws ProcessingException
+ */
+ public static void writeDOMNode(XMLStreamWriter writer, Node node) throws ProcessingException {
+ try {
+ short nodeType = node.getNodeType();
+
+ switch (nodeType) {
+ case Node.ELEMENT_NODE:
+ writeDOMElement(writer, (Element) node);
+ break;
+ case Node.TEXT_NODE:
+ writer.writeCharacters(node.getNodeValue());
+ break;
+ case Node.COMMENT_NODE:
+ writer.writeComment(node.getNodeValue());
+ break;
+ case Node.CDATA_SECTION_NODE:
+ writer.writeCData(node.getNodeValue());
+ break;
+ default:
+ // Don't care
+ }
+ } catch (DOMException e) {
+ throw logger.processingError(e);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Write DOM Element to the stream
+ *
+ * @param writer
+ * @param domElement
+ *
+ * @throws ProcessingException
+ */
+ public static void writeDOMElement(XMLStreamWriter writer, Element domElement) throws ProcessingException {
+ if (registeredNSStack.get() == null) {
+ registeredNSStack.set(new Stack<String>());
+ }
+ String domElementPrefix = domElement.getPrefix();
+
+ if (domElementPrefix == null) {
+ domElementPrefix = "";
+ }
+
+ String domElementNS = domElement.getNamespaceURI();
+ if (domElementNS == null) {
+ domElementNS = "";
+ }
+
+ writeStartElement(writer, domElementPrefix, domElement.getLocalName(), domElementNS);
+
+ // Should we register namespace
+ if (domElementPrefix != "" && !registeredNSStack.get().contains(domElementNS)) {
+ // writeNameSpace(writer, domElementPrefix, domElementNS );
+ registeredNSStack.get().push(domElementNS);
+ } else if (domElementPrefix == "" && domElementNS != null) {
+ writeNameSpace(writer, "xmlns", domElementNS);
+ }
+
+ // Deal with Attributes
+ NamedNodeMap attrs = domElement.getAttributes();
+ for (int i = 0, len = attrs.getLength(); i < len; ++i) {
+ Attr attr = (Attr) attrs.item(i);
+ String attributePrefix = attr.getPrefix();
+ String attribLocalName = attr.getLocalName();
+ String attribValue = attr.getValue();
+
+ if (attributePrefix == null || attributePrefix.length() == 0) {
+ if (!("xmlns".equals(attribLocalName))) {
+ writeAttribute(writer, attribLocalName, attribValue);
+ }
+ } else {
+ if ("xmlns".equals(attributePrefix)) {
+ writeNameSpace(writer, attribLocalName, attribValue);
+ } else {
+ writeAttribute(writer, new QName(attr.getNamespaceURI(), attribLocalName, attributePrefix), attribValue);
+ }
+ }
+ }
+
+ for (Node child = domElement.getFirstChild(); child != null; child = child.getNextSibling()) {
+ writeDOMNode(writer, child);
+ }
+
+ writeEndElement(writer);
+ }
+
+ /**
+ * Write a namespace
+ *
+ * @param writer
+ * @param prefix prefix
+ * @param ns Namespace URI
+ *
+ * @throws ProcessingException
+ */
+ public static void writeNameSpace(XMLStreamWriter writer, String prefix, String ns) throws ProcessingException {
+ try {
+ writer.writeNamespace(prefix, ns);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * Write a start element
+ *
+ * @param writer
+ * @param prefix
+ * @param localPart
+ * @param ns
+ *
+ * @throws ProcessingException
+ */
+ public static void writeStartElement(XMLStreamWriter writer, String prefix, String localPart, String ns)
+ throws ProcessingException {
+ try {
+ writer.writeStartElement(prefix, localPart, ns);
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ /**
+ * <p> Write an end element. The stream writer keeps track of which start element needs to be closed with an end
+ * tag. </p>
+ *
+ * @param writer
+ *
+ * @throws ProcessingException
+ */
+ public static void writeEndElement(XMLStreamWriter writer) throws ProcessingException {
+ try {
+ writer.writeEndElement();
+ } catch (XMLStreamException e) {
+ throw logger.processingError(e);
+ }
+ }
+
+ private static XMLOutputFactory getXMLOutputFactory() {
+ boolean tccl_jaxp = SystemPropertiesUtil.getSystemProperty(GeneralConstants.TCCL_JAXP, "false")
+ .equalsIgnoreCase("true");
+ ClassLoader prevTCCL = SecurityActions.getTCCL();
+ try {
+ if (tccl_jaxp) {
+ SecurityActions.setTCCL(StaxUtil.class.getClassLoader());
+ }
+ return XMLOutputFactory.newInstance();
+ } finally {
+ if (tccl_jaxp) {
+ SecurityActions.setTCCL(prevTCCL);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java b/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java
new file mode 100755
index 0000000..3db64c2
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/util/StringUtil.java
@@ -0,0 +1,199 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.saml.common.constants.PicketLinkCommonConstants;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.PBEParameterSpec;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Utility dealing with Strings
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Oct 21, 2009
+ */
+public class StringUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * Check whether the passed string is null or empty
+ *
+ * @param str
+ *
+ * @return
+ */
+ public static boolean isNotNull(String str) {
+ return str != null && !"".equals(str.trim());
+ }
+
+ /**
+ * Check whether the string is null or empty
+ *
+ * @param str
+ *
+ * @return
+ */
+ public static boolean isNullOrEmpty(String str) {
+ return str == null || str.isEmpty();
+ }
+
+ /**
+ * <p>
+ * Get the system property value if the string is of the format ${sysproperty}
+ * </p>
+ * <p>
+ * You can insert default value when the system property is not set, by separating it at the beginning with ::
+ * </p>
+ * <p>
+ * <b>Examples:</b>
+ * </p>
+ *
+ * <p>
+ * ${idp} should resolve to a value if the system property "idp" is set.
+ * </p>
+ * <p>
+ * ${idp::http://localhost:8080} will resolve to http://localhost:8080 if the system property "idp" is not set.
+ * </p>
+ *
+ * @param str
+ *
+ * @return
+ */
+ public static String getSystemPropertyAsString(String str) {
+ if (str == null)
+ throw logger.nullArgumentError("str");
+ if (str.contains("${")) {
+ Pattern pattern = Pattern.compile("\\$\\{([^}]+)}");
+ Matcher matcher = pattern.matcher(str);
+
+ StringBuffer buffer = new StringBuffer();
+ String sysPropertyValue = null;
+
+ while (matcher.find()) {
+ String subString = matcher.group(1);
+ String defaultValue = "";
+
+ // Look for default value
+ if (subString.contains("::")) {
+ int index = subString.indexOf("::");
+ defaultValue = subString.substring(index + 2);
+ subString = subString.substring(0, index);
+ }
+ sysPropertyValue = SecurityActions.getSystemProperty(subString, defaultValue);
+ if (sysPropertyValue.isEmpty()) {
+ throw logger.systemPropertyMissingError(matcher.group(1));
+ }else{
+ // sanitize the value before we use append-and-replace
+ sysPropertyValue = Matcher.quoteReplacement(sysPropertyValue);
+ }
+ matcher.appendReplacement(buffer, sysPropertyValue);
+ }
+
+ matcher.appendTail(buffer);
+ str = buffer.toString();
+ }
+ return str;
+ }
+
+ /**
+ * Match two strings else throw a {@link RuntimeException}
+ *
+ * @param first
+ * @param second
+ */
+ public static void match(String first, String second) {
+ if (first.equals(second) == false)
+ throw logger.notEqualError(first, second);
+ }
+
+ /**
+ * Given a comma separated string, get the tokens as a {@link List}
+ *
+ * @param str
+ *
+ * @return
+ */
+ public static List<String> tokenize(String str) {
+ return tokenize(str, ",");
+ }
+
+ /**
+ * Given a delimited string, get the tokens as a {@link List}
+ *
+ * @param str
+ * @param delimiter the delimiter
+ *
+ * @return
+ */
+ public static List<String> tokenize(String str, String delimiter) {
+ List<String> list = new ArrayList<String>();
+ StringTokenizer tokenizer = new StringTokenizer(str, delimiter);
+ while (tokenizer.hasMoreTokens()) {
+ list.add(tokenizer.nextToken());
+ }
+ return list;
+ }
+
+ /**
+ * Given a string that is comma delimited and contains key-value pairs
+ *
+ * @param keyValuePairString
+ *
+ * @return
+ */
+ public static Map<String, String> tokenizeKeyValuePair(String keyValuePairString) {
+ Map<String, String> map = new HashMap<String, String>();
+
+ List<String> tokens = tokenize(keyValuePairString);
+ for (String token : tokens) {
+ int location = token.indexOf('=');
+ map.put(token.substring(0, location), token.substring(location + 1));
+ }
+ return map;
+ }
+
+ public static String[] split(String toSplit, String delimiter) {
+ if (delimiter.length() != 1) {
+ throw new IllegalArgumentException("Delimiter can only be one character in length");
+ }
+
+ int offset = toSplit.indexOf(delimiter);
+
+ if (offset < 0) {
+ return null;
+ }
+
+ String beforeDelimiter = toSplit.substring(0, offset);
+ String afterDelimiter = toSplit.substring(offset + 1);
+
+ return new String[]{beforeDelimiter, afterDelimiter};
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/common/util/SystemPropertiesUtil.java b/saml-core/src/main/java/org/keycloak/saml/common/util/SystemPropertiesUtil.java
new file mode 100755
index 0000000..28dd35c
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/common/util/SystemPropertiesUtil.java
@@ -0,0 +1,64 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import javax.xml.XMLConstants;
+
+/**
+ * Utility dealing with the system properties at the JVM level for PicketLink
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jul 1, 2011
+ */
+public class SystemPropertiesUtil {
+ static {
+ // XML Signature
+ String xmlSec = "org.apache.xml.security.ignoreLineBreaks";
+ if (StringUtil.isNullOrEmpty(SecurityActions.getSystemProperty(xmlSec, ""))) {
+ SecurityActions.setSystemProperty(xmlSec, "true");
+ }
+
+ // For JAXP Validation
+ String schemaFactoryProperty = "javax.xml.validation.SchemaFactory:" + XMLConstants.W3C_XML_SCHEMA_NS_URI;
+ if (StringUtil.isNullOrEmpty(SecurityActions.getSystemProperty(schemaFactoryProperty, ""))) {
+ SecurityActions.setSystemProperty(schemaFactoryProperty, "org.apache.xerces.jaxp.validation.XMLSchemaFactory");
+ }
+
+ // For the XACML Engine
+ String xacmlValidation = "org.jboss.security.xacml.schema.validation";
+ if (StringUtil.isNullOrEmpty(SecurityActions.getSystemProperty(xacmlValidation, ""))) {
+ SecurityActions.setSystemProperty(xacmlValidation, "false");
+ }
+ };
+
+ /**
+ * No-op call such that the default system properties are set
+ */
+ public static void ensure() {
+ }
+
+ /**
+ * Get the System Property
+ * @param key key of the system property
+ * @param defaultValue default value to be returned if the system property is not set
+ * @return
+ */
+ public static String getSystemProperty(final String key, final String defaultValue){
+ return SecurityActions.getSystemProperty(key,defaultValue);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java
new file mode 100755
index 0000000..906d908
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SAML2Request.java
@@ -0,0 +1,336 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.api.saml.v2.request;
+
+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.util.DocumentUtil;
+import org.keycloak.saml.common.util.StaxUtil;
+import org.keycloak.dom.saml.v2.SAML2Object;
+import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
+import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
+import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.keycloak.saml.processing.core.saml.v2.writers.SAMLRequestWriter;
+import org.keycloak.saml.processing.core.saml.v2.writers.SAMLResponseWriter;
+import org.keycloak.saml.processing.core.util.JAXPValidationUtil;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
+import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
+import org.keycloak.dom.saml.v2.protocol.NameIDPolicyType;
+import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.w3c.dom.Document;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URL;
+
+/**
+ * API for SAML2 Request
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jan 5, 2009
+ */
+public class SAML2Request {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ private SAMLDocumentHolder samlDocumentHolder = null;
+
+ private String nameIDFormat = JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get();
+
+ /**
+ * Set the NameIDFormat
+ *
+ * @param nameIDFormat
+ */
+ public void setNameIDFormat(String nameIDFormat) {
+ this.nameIDFormat = nameIDFormat;
+ }
+
+ /**
+ * Create an authentication request
+ *
+ * @param id
+ * @param assertionConsumerURL
+ * @param destination
+ * @param issuerValue
+ *
+ * @return
+ *
+ * @throws ConfigurationException
+ */
+ public AuthnRequestType createAuthnRequestType(String id, String assertionConsumerURL, String destination,
+ String issuerValue) throws ConfigurationException {
+ XMLGregorianCalendar issueInstant = XMLTimeUtil.getIssueInstant();
+
+ AuthnRequestType authnRequest = new AuthnRequestType(id, issueInstant);
+ authnRequest.setAssertionConsumerServiceURL(URI.create(assertionConsumerURL));
+ authnRequest.setProtocolBinding(URI.create(JBossSAMLConstants.HTTP_POST_BINDING.get()));
+ if (destination != null) {
+ authnRequest.setDestination(URI.create(destination));
+ }
+
+ // Create an issuer
+ NameIDType issuer = new NameIDType();
+ issuer.setValue(issuerValue);
+
+ authnRequest.setIssuer(issuer);
+
+ // Create a default NameIDPolicy
+ NameIDPolicyType nameIDPolicy = new NameIDPolicyType();
+ nameIDPolicy.setAllowCreate(Boolean.TRUE);
+ nameIDPolicy.setFormat(URI.create(this.nameIDFormat));
+
+ authnRequest.setNameIDPolicy(nameIDPolicy);
+
+ return authnRequest;
+ }
+
+ /**
+ * Get AuthnRequestType from a file
+ *
+ * @param fileName file with the serialized AuthnRequestType
+ *
+ * @return AuthnRequestType
+ *
+ * @throws ParsingException
+ * @throws ProcessingException
+ * @throws ConfigurationException
+ * @throws IllegalArgumentException if the input fileName is null IllegalStateException if the InputStream from the
+ * fileName
+ * is null
+ */
+ public AuthnRequestType getAuthnRequestType(String fileName) throws ConfigurationException, ProcessingException,
+ ParsingException {
+ if (fileName == null)
+ throw logger.nullArgumentError("fileName");
+ URL resourceURL = SecurityActions.loadResource(getClass(), fileName);
+ if (resourceURL == null)
+ throw logger.resourceNotFound(fileName);
+
+ InputStream is = null;
+ try {
+ is = resourceURL.openStream();
+ } catch (IOException e) {
+ throw logger.processingError(e);
+ }
+ return getAuthnRequestType(is);
+ }
+
+ /**
+ * Get the Underlying SAML2Object from the input stream
+ *
+ * @param is
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws ParsingException
+ */
+ public SAML2Object getSAML2ObjectFromStream(InputStream is) throws ConfigurationException, ParsingException,
+ ProcessingException {
+ if (is == null)
+ throw logger.nullArgumentError("InputStream");
+
+ Document samlDocument = DocumentUtil.getDocument(is);
+
+ SAMLParser samlParser = new SAMLParser();
+ JAXPValidationUtil.checkSchemaValidation(samlDocument);
+ SAML2Object requestType = (SAML2Object) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
+
+ samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
+ return requestType;
+ }
+
+ /**
+ * Get a Request Type from Input Stream
+ *
+ * @param is
+ *
+ * @return
+ *
+ * @throws ProcessingException
+ * @throws ConfigurationException
+ * @throws
+ * @throws IllegalArgumentException inputstream is null
+ */
+ public RequestAbstractType getRequestType(InputStream is) throws ParsingException, ConfigurationException,
+ ProcessingException {
+ if (is == null)
+ throw logger.nullArgumentError("InputStream");
+
+ Document samlDocument = DocumentUtil.getDocument(is);
+
+ SAMLParser samlParser = new SAMLParser();
+ JAXPValidationUtil.checkSchemaValidation(samlDocument);
+ RequestAbstractType requestType = (RequestAbstractType) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
+
+ samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
+ return requestType;
+ }
+
+ /**
+ * Get the AuthnRequestType from an input stream
+ *
+ * @param is Inputstream containing the AuthnRequest
+ *
+ * @return
+ *
+ * @throws ParsingException
+ * @throws ProcessingException
+ * @throws ConfigurationException
+ * @throws IllegalArgumentException inputstream is null
+ */
+ public AuthnRequestType getAuthnRequestType(InputStream is) throws ConfigurationException, ProcessingException,
+ ParsingException {
+ if (is == null)
+ throw logger.nullArgumentError("InputStream");
+
+ Document samlDocument = DocumentUtil.getDocument(is);
+
+ SAMLParser samlParser = new SAMLParser();
+ JAXPValidationUtil.checkSchemaValidation(samlDocument);
+
+ AuthnRequestType requestType = (AuthnRequestType) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
+ samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
+ return requestType;
+ }
+
+ /**
+ * Get the parsed {@code SAMLDocumentHolder}
+ *
+ * @return
+ */
+ public SAMLDocumentHolder getSamlDocumentHolder() {
+ return samlDocumentHolder;
+ }
+
+ /**
+ * Create a Logout Request
+ *
+ * @param issuer
+ *
+ * @return
+ *
+ * @throws ConfigurationException
+ */
+ public LogoutRequestType createLogoutRequest(String issuer) throws ConfigurationException {
+ LogoutRequestType lrt = new LogoutRequestType(IDGenerator.create("ID_"), XMLTimeUtil.getIssueInstant());
+
+ // Create an issuer
+ NameIDType issuerNameID = new NameIDType();
+ issuerNameID.setValue(issuer);
+
+ lrt.setIssuer(issuerNameID);
+
+ return lrt;
+ }
+
+ /**
+ * Return the DOM object
+ *
+ * @param rat
+ *
+ * @return
+ *
+ * @throws ProcessingException
+ * @throws ParsingException
+ * @throws ConfigurationException
+ */
+ public Document convert(RequestAbstractType rat) throws ProcessingException, ConfigurationException, ParsingException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ SAMLRequestWriter writer = new SAMLRequestWriter(StaxUtil.getXMLStreamWriter(bos));
+ if (rat instanceof AuthnRequestType) {
+ writer.write((AuthnRequestType) rat);
+ } else if (rat instanceof LogoutRequestType) {
+ writer.write((LogoutRequestType) rat);
+ }
+
+ return DocumentUtil.getDocument(new String(bos.toByteArray()));
+ }
+
+ /**
+ * Convert a SAML2 Response into a Document
+ *
+ * @param responseType
+ *
+ * @return
+ *
+ * @throws ProcessingException
+ * @throws ParsingException
+ * @throws ConfigurationException
+ */
+ public Document convert(ResponseType responseType) throws ProcessingException, ParsingException, ConfigurationException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ SAMLResponseWriter writer = new SAMLResponseWriter(StaxUtil.getXMLStreamWriter(baos));
+ writer.write(responseType);
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(baos.toByteArray());
+ return DocumentUtil.getDocument(bis);
+ }
+
+ /**
+ * Marshall the AuthnRequestType to an output stream
+ *
+ * @param requestType
+ * @param os
+ *
+ * @throws ProcessingException
+ */
+ public void marshall(RequestAbstractType requestType, OutputStream os) throws ProcessingException {
+ SAMLRequestWriter samlRequestWriter = new SAMLRequestWriter(StaxUtil.getXMLStreamWriter(os));
+ if (requestType instanceof AuthnRequestType) {
+ samlRequestWriter.write((AuthnRequestType) requestType);
+ } else if (requestType instanceof LogoutRequestType) {
+ samlRequestWriter.write((LogoutRequestType) requestType);
+ } else
+ throw logger.unsupportedType(requestType.getClass().getName());
+ }
+
+ /**
+ * Marshall the AuthnRequestType to a writer
+ *
+ * @param requestType
+ * @param writer
+ *
+ * @throws ProcessingException
+ */
+ public void marshall(RequestAbstractType requestType, Writer writer) throws ProcessingException {
+ SAMLRequestWriter samlRequestWriter = new SAMLRequestWriter(StaxUtil.getXMLStreamWriter(writer));
+ if (requestType instanceof AuthnRequestType) {
+ samlRequestWriter.write((AuthnRequestType) requestType);
+ } else if (requestType instanceof LogoutRequestType) {
+ samlRequestWriter.write((LogoutRequestType) requestType);
+ } else
+ throw logger.unsupportedType(requestType.getClass().getName());
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SecurityActions.java b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SecurityActions.java
new file mode 100755
index 0000000..b384af8
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/request/SecurityActions.java
@@ -0,0 +1,166 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.api.saml.v2.request;
+
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 9, 2008
+ */
+class SecurityActions {
+
+ /**
+ * <p>
+ * Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
+ * the
+ * specified {@link Class}, if not found it will try to load from using TCL.
+ * </p>
+ *
+ * @param theClass
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ });
+ } else {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ }
+
+ /**
+ * <p>
+ * Loads a class from the specified {@link ClassLoader} using the <code>fullQualifiedName</code> supplied.
+ * </p>
+ *
+ * @param classLoader
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ });
+ } else {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ }
+
+ /**
+ * <p>Returns a system property value using the specified <code>key</code>. If not found the
+ * <code>defaultValue</code> will be returned.</p>
+ *
+ * @param key
+ * @param defaultValue
+ *
+ * @return
+ */
+ static String getSystemProperty(final String key, final String defaultValue) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(key, defaultValue);
+ }
+ });
+ } else {
+ return System.getProperty(key, defaultValue);
+ }
+ }
+
+ /**
+ * Load a resource based on the passed {@link Class} classloader. Failing which try with the Thread Context CL
+ *
+ * @param clazz
+ * @param resourceName
+ *
+ * @return
+ */
+ static URL loadResource(final Class<?> clazz, final String resourceName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<URL>() {
+ public URL run() {
+ URL url = null;
+ ClassLoader clazzLoader = clazz.getClassLoader();
+ url = clazzLoader.getResource(resourceName);
+
+ if (url == null) {
+ clazzLoader = Thread.currentThread().getContextClassLoader();
+ url = clazzLoader.getResource(resourceName);
+ }
+
+ return url;
+ }
+ });
+ } else {
+ URL url = null;
+ ClassLoader clazzLoader = clazz.getClassLoader();
+ url = clazzLoader.getResource(resourceName);
+
+ if (url == null) {
+ clazzLoader = Thread.currentThread().getContextClassLoader();
+ url = clazzLoader.getResource(resourceName);
+ }
+
+ return url;
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/response/SecurityActions.java b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/response/SecurityActions.java
new file mode 100755
index 0000000..6cd7266
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/response/SecurityActions.java
@@ -0,0 +1,122 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.api.saml.v2.response;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ */
+class SecurityActions {
+
+ /**
+ * <p>
+ * Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
+ * the
+ * specified {@link Class}, if not found it will try to load from using TCL.
+ * </p>
+ *
+ * @param theClass
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ });
+ } else {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ }
+
+ /**
+ * <p>
+ * Loads a class from the specified {@link ClassLoader} using the <code>fullQualifiedName</code> supplied.
+ * </p>
+ *
+ * @param classLoader
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ });
+ } else {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ }
+
+ /**
+ * <p>Returns a system property value using the specified <code>key</code>. If not found the
+ * <code>defaultValue</code> will be returned.</p>
+ *
+ * @param key
+ * @param defaultValue
+ *
+ * @return
+ */
+ static String getSystemProperty(final String key, final String defaultValue) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(key, defaultValue);
+ }
+ });
+ } else {
+ return System.getProperty(key, defaultValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java
new file mode 100755
index 0000000..b4cf8a5
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/api/saml/v2/sig/SAML2Signature.java
@@ -0,0 +1,238 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.api.saml.v2.sig;
+
+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.ProcessingException;
+import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
+import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.util.SignatureUtilTransferObject;
+import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
+import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.crypto.MarshalException;
+import javax.xml.crypto.dsig.DigestMethod;
+import javax.xml.crypto.dsig.SignatureMethod;
+import javax.xml.crypto.dsig.XMLSignatureException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.xpath.XPathException;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+
+/**
+ * Class that deals with SAML2 Signature
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @author alessio.soldano@jboss.com
+ * @since May 26, 2009
+ */
+public class SAML2Signature {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ private static final String ID_ATTRIBUTE_NAME = "ID";
+
+ private String signatureMethod = SignatureMethod.RSA_SHA1;
+
+ private String digestMethod = DigestMethod.SHA1;
+
+ private Node sibling;
+
+ /**
+ * Set the X509Certificate if X509Data is needed in signed info
+ */
+ private X509Certificate x509Certificate;
+
+ public String getSignatureMethod() {
+ return signatureMethod;
+ }
+
+ public void setSignatureMethod(String signatureMethod) {
+ this.signatureMethod = signatureMethod;
+ }
+
+ public String getDigestMethod() {
+ return digestMethod;
+ }
+
+ public void setDigestMethod(String digestMethod) {
+ this.digestMethod = digestMethod;
+ }
+
+ public void setNextSibling(Node sibling) {
+ this.sibling = sibling;
+ }
+
+ /**
+ * Set to false, if you do not want to include keyinfo in the signature
+ *
+ * @param val
+ *
+ * @since v2.0.1
+ */
+ public void setSignatureIncludeKeyInfo(boolean val) {
+ if (!val) {
+ XMLSignatureUtil.setIncludeKeyInfoInSignature(false);
+ }
+ }
+
+ /**
+ * Set the {@link X509Certificate} if you desire
+ * to have the SignedInfo have X509 Data
+ *
+ * This method needs to be called before any of the sign methods.
+ *
+ * @param x509Certificate
+ *
+ * @since v2.5.0
+ */
+ public void setX509Certificate(X509Certificate x509Certificate) {
+ this.x509Certificate = x509Certificate;
+ }
+
+ /**
+ * Sign an Document at the root
+ *
+ * @param keyPair Key Pair
+ *
+ * @return
+ *
+ * @throws ParserConfigurationException
+ * @throws XMLSignatureException
+ * @throws MarshalException
+ * @throws GeneralSecurityException
+ */
+ public Document sign(Document doc, String referenceID, KeyPair keyPair, String canonicalizationMethodType) throws ParserConfigurationException,
+ GeneralSecurityException, MarshalException, XMLSignatureException {
+ String referenceURI = "#" + referenceID;
+
+ configureIdAttribute(doc);
+
+ if (sibling != null) {
+ SignatureUtilTransferObject dto = new SignatureUtilTransferObject();
+ dto.setDocumentToBeSigned(doc);
+ dto.setKeyPair(keyPair);
+ dto.setDigestMethod(digestMethod);
+ dto.setSignatureMethod(signatureMethod);
+ dto.setReferenceURI(referenceURI);
+ dto.setNextSibling(sibling);
+
+ if (x509Certificate != null) {
+ dto.setX509Certificate(x509Certificate);
+ }
+
+ return XMLSignatureUtil.sign(dto, canonicalizationMethodType);
+ }
+ return XMLSignatureUtil.sign(doc, keyPair, digestMethod, signatureMethod, referenceURI, canonicalizationMethodType);
+ }
+
+ /**
+ * Sign a SAML Document
+ *
+ * @param samlDocument
+ * @param keypair
+ *
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ */
+ public void signSAMLDocument(Document samlDocument, KeyPair keypair, String canonicalizationMethodType) throws ProcessingException {
+ // Get the ID from the root
+ String id = samlDocument.getDocumentElement().getAttribute(ID_ATTRIBUTE_NAME);
+ try {
+ sign(samlDocument, id, keypair, canonicalizationMethodType);
+ } catch (Exception e) {
+ throw new ProcessingException(logger.signatureError(e));
+ }
+ }
+
+ /**
+ * Validate the SAML2 Document
+ *
+ * @param signedDocument
+ * @param publicKey
+ *
+ * @return
+ *
+ * @throws ProcessingException
+ */
+ public boolean validate(Document signedDocument, PublicKey publicKey) throws ProcessingException {
+ try {
+ configureIdAttribute(signedDocument);
+ return XMLSignatureUtil.validate(signedDocument, publicKey);
+ } catch (MarshalException me) {
+ throw new ProcessingException(logger.signatureError(me));
+ } catch (XMLSignatureException xse) {
+ throw new ProcessingException(logger.signatureError(xse));
+ }
+ }
+
+ /**
+ * Given a {@link Document}, find the {@link Node} which is the sibling of the Issuer element
+ *
+ * @param doc
+ *
+ * @return
+ */
+ public Node getNextSiblingOfIssuer(Document doc) {
+ // Find the sibling of Issuer
+ NodeList nl = doc.getElementsByTagNameNS(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get());
+ if (nl.getLength() > 0) {
+ Node issuer = nl.item(0);
+
+ return issuer.getNextSibling();
+ }
+ return null;
+ }
+
+ /**
+ * <p>
+ * Sets the IDness of the ID attribute. Santuario 1.5.1 does not assumes IDness based on attribute names anymore.
+ * This
+ * method should be called before signing/validating a saml document.
+ * </p>
+ *
+ * @param document SAML document to have its ID attribute configured.
+ */
+ private void configureIdAttribute(Document document) {
+ // Estabilish the IDness of the ID attribute.
+ document.getDocumentElement().setIdAttribute(ID_ATTRIBUTE_NAME, true);
+
+ NodeList nodes = document.getElementsByTagNameNS(JBossSAMLURIConstants.ASSERTION_NSURI.get(),
+ JBossSAMLConstants.ASSERTION.get());
+
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Node n = nodes.item(i);
+ if (n instanceof Element) {
+ ((Element) n).setIdAttribute(ID_ATTRIBUTE_NAME, true);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/api/util/DeflateUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/api/util/DeflateUtil.java
new file mode 100755
index 0000000..eee41bb
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/api/util/DeflateUtil.java
@@ -0,0 +1,80 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.api.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.Deflater;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
+/**
+ * Encoder of saml messages based on DEFLATE compression
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 11, 2008
+ */
+public class DeflateUtil {
+
+ /**
+ * Apply DEFLATE encoding
+ *
+ * @param message
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static byte[] encode(byte[] message) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Deflater deflater = new Deflater(Deflater.DEFLATED, true);
+ DeflaterOutputStream deflaterStream = new DeflaterOutputStream(baos, deflater);
+ deflaterStream.write(message);
+ deflaterStream.finish();
+
+ return baos.toByteArray();
+ }
+
+ /**
+ * Apply DEFLATE encoding
+ *
+ * @param message
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static byte[] encode(String message) throws IOException {
+ return encode(message.getBytes());
+ }
+
+ /**
+ * DEFLATE decoding
+ *
+ * @param msgToDecode the message that needs decoding
+ *
+ * @return
+ */
+ public static InputStream decode(byte[] msgToDecode) {
+ ByteArrayInputStream bais = new ByteArrayInputStream(msgToDecode);
+ return new InflaterInputStream(bais, new Inflater(true));
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/constants/AttributeConstants.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/constants/AttributeConstants.java
new file mode 100755
index 0000000..97fe7c1
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/constants/AttributeConstants.java
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.constants;
+
+/**
+ * Constants for attributes
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Aug 31, 2009
+ */
+public interface AttributeConstants {
+
+ String ROLES = "roles";
+
+ /**
+ * Default identifier in the saml2 attribute statements to indicate role *
+ */
+ String ROLE_IDENTIFIER_ASSERTION = "Role";
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/constants/PicketLinkFederationConstants.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/constants/PicketLinkFederationConstants.java
new file mode 100755
index 0000000..29d5058
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/constants/PicketLinkFederationConstants.java
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.constants;
+
+/**
+ * Constants useful to the JBoss Identity Federation project
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Feb 23, 2009
+ */
+public interface PicketLinkFederationConstants {
+
+ /**
+ * Flag to indicate whether JAXB Schema Validation is turned on
+ */
+ String JAXB_SCHEMA_VALIDATION = "org.picketlink.jaxb.schema.validation";
+
+ String SCHEMA_IDFED = "schema/config/picketlink-fed.xsd";
+ String SCHEMA_IDFED_HANDLER = "schema/config/picketlink-fed-handler.xsd";
+ String DSA_SIGNATURE_ALGORITHM = "SHA1withDSA";
+ String RSA_SIGNATURE_ALGORITHM = "SHA1withRSA";
+
+ // File Based Meta data Configuration Constants
+ String SERIALIZATION_EXTENSION = ".SER";
+ String FILE_STORE_DIRECTORY = "/picketlink-store";
+ String IDP_PROPERTIES = "/identityproviders.properties";
+ String SP_PROPERTIES = "/serviceproviders.properties";
+
+ String SALT = "salt";
+ String ITERATION_COUNT = "iterationCount";
+
+ String PBE_ALGORITHM = "PBEwithMD5andDES";
+ // Prefix to indicate a particular configuration property value is masked
+ String PASS_MASK_PREFIX = "MASK-";
+
+ RuntimePermission RUNTIME_PERMISSION_CORE = new RuntimePermission("org.picketlink.core");
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/AbstractDescriptorParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/AbstractDescriptorParser.java
new file mode 100755
index 0000000..bf1031c
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/AbstractDescriptorParser.java
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.exceptions.ParsingException;
+import org.keycloak.saml.common.parsers.AbstractParser;
+
+import javax.xml.stream.EventFilter;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Characters;
+import javax.xml.stream.events.XMLEvent;
+
+/**
+ * <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 {
+
+ XMLInputFactory xmlInputFactory = getXMLInputFactory();
+
+ try {
+ xmlEventReader = xmlInputFactory.createFilteredReader(xmlEventReader, new EventFilter() {
+ public boolean accept(XMLEvent xmlEvent) {
+ // We are going to disregard characters that are new line and whitespace
+ if (xmlEvent.isCharacters()) {
+ Characters chars = xmlEvent.asCharacters();
+ String data = chars.getData();
+ data = valid(data) ? data.trim() : null;
+ return valid(data);
+ } else {
+ return xmlEvent.isStartElement() || xmlEvent.isEndElement();
+ }
+ }
+
+ private boolean valid(String str) {
+ return str != null && str.length() > 0;
+ }
+ });
+ return xmlEventReader;
+ } catch (XMLStreamException e) {
+ throw new ParsingException(e);
+ }
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java
new file mode 100755
index 0000000..ad174b3
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/metadata/SAMLEntitiesDescriptorParser.java
@@ -0,0 +1,123 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.ExtensionsType;
+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 Entities Descriptor
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jan 31, 2011
+ */
+public class SAMLEntitiesDescriptorParser extends AbstractDescriptorParser implements ParserNamespaceSupport {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ private final String EDT = JBossSAMLConstants.ENTITIES_DESCRIPTOR.get();
+
+ public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
+
+ xmlEventReader = filterWhiteSpaceCharacters(xmlEventReader);
+
+ StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ StaxParserUtil.validate(startElement, EDT);
+
+ EntitiesDescriptorType entitiesDescriptorType = new EntitiesDescriptorType();
+
+ // Parse the attributes
+ Attribute validUntil = startElement.getAttributeByName(new QName(JBossSAMLConstants.VALID_UNTIL.get()));
+ if (validUntil != null) {
+ String validUntilValue = StaxParserUtil.getAttributeValue(validUntil);
+ entitiesDescriptorType.setValidUntil(XMLTimeUtil.parse(validUntilValue));
+ }
+
+ Attribute id = startElement.getAttributeByName(new QName(JBossSAMLConstants.ID.get()));
+ if (id != null) {
+ entitiesDescriptorType.setID(StaxParserUtil.getAttributeValue(id));
+ }
+
+ Attribute name = startElement.getAttributeByName(new QName(JBossSAMLConstants.NAME.get()));
+ if (name != null) {
+ entitiesDescriptorType.setName(StaxParserUtil.getAttributeValue(name));
+ }
+
+ Attribute cacheDuration = startElement.getAttributeByName(new QName(JBossSAMLConstants.CACHE_DURATION.get()));
+ if (cacheDuration != null) {
+ entitiesDescriptorType
+ .setCacheDuration(XMLTimeUtil.parseAsDuration(StaxParserUtil.getAttributeValue(cacheDuration)));
+ }
+
+ // Get the Child Elements
+ while (xmlEventReader.hasNext()) {
+ XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
+ if (xmlEvent instanceof EndElement) {
+ StaxParserUtil.validate((EndElement) xmlEvent, EDT);
+ StaxParserUtil.getNextEndElement(xmlEventReader);
+ break;
+ }
+ startElement = (StartElement) xmlEvent;
+ String localPart = startElement.getName().getLocalPart();
+
+ if (JBossSAMLConstants.ENTITY_DESCRIPTOR.get().equals(localPart)) {
+ SAMLEntityDescriptorParser entityParser = new SAMLEntityDescriptorParser();
+ entitiesDescriptorType.addEntityDescriptor(entityParser.parse(xmlEventReader));
+ } else if (JBossSAMLConstants.EXTENSIONS.get().equalsIgnoreCase(localPart)) {
+ entitiesDescriptorType.setExtensions(parseExtensions(xmlEventReader));
+ } else if (JBossSAMLConstants.ENTITIES_DESCRIPTOR.get().equalsIgnoreCase(localPart)) {
+ SAMLEntitiesDescriptorParser parser = new SAMLEntitiesDescriptorParser();
+ entitiesDescriptorType.addEntityDescriptor(parser.parse(xmlEventReader));
+ } else if (localPart.equals(JBossSAMLConstants.SIGNATURE.get())) {
+ entitiesDescriptorType.setSignature(StaxParserUtil.getDOMElement(xmlEventReader));
+ } else
+ throw logger.parserUnknownTag(localPart, startElement.getLocation());
+ }
+ return entitiesDescriptorType;
+ }
+
+ 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 {
+ ExtensionsType extensions = new ExtensionsType();
+ Element extElement = StaxParserUtil.getDOMElement(xmlEventReader);
+ extensions.setElement(extElement);
+ return extensions;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11AssertionParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11AssertionParser.java
new file mode 100755
index 0000000..a16c511
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11AssertionParser.java
@@ -0,0 +1,178 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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.common.util.StringUtil;
+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.v2.util.XMLTimeUtil;
+import org.keycloak.dom.saml.v1.assertion.SAML11AssertionType;
+import org.keycloak.dom.saml.v1.assertion.SAML11AttributeStatementType;
+import org.keycloak.dom.saml.v1.assertion.SAML11AuthenticationStatementType;
+import org.keycloak.dom.saml.v1.assertion.SAML11AuthorizationDecisionStatementType;
+import org.keycloak.dom.saml.v1.assertion.SAML11ConditionsType;
+import org.keycloak.dom.saml.v1.assertion.SAML11SubjectStatementType;
+import org.keycloak.dom.saml.v1.assertion.SAML11SubjectType;
+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;
+
+/**
+ * Parse the saml assertion
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Oct 12, 2010
+ */
+public class SAML11AssertionParser implements ParserNamespaceSupport {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ private final String ASSERTION = JBossSAMLConstants.ASSERTION.get();
+
+ public SAML11AssertionType fromElement(Element element) throws ConfigurationException, ProcessingException,
+ ParsingException {
+ XMLEventReader xmlEventReader = StaxParserUtil.getXMLEventReader(DocumentUtil.getNodeAsStream(element));
+ return (SAML11AssertionType) parse(xmlEventReader);
+ }
+
+ /**
+ * @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
+ */
+ public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
+ StartElement startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
+
+ startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+
+ // Special case: Encrypted Assertion
+ StaxParserUtil.validate(startElement, ASSERTION);
+ SAML11AssertionType assertion = parseBaseAttributes(startElement);
+
+ Attribute issuerAttribute = startElement.getAttributeByName(new QName(SAML11Constants.ISSUER));
+ String issuer = StaxParserUtil.getAttributeValue(issuerAttribute);
+ assertion.setIssuer(issuer);
+
+ // 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 logger.parserUnknownEndElement(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));
+ } else if (JBossSAMLConstants.ISSUER.get().equalsIgnoreCase(tag)) {
+ startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ issuer = StaxParserUtil.getElementText(xmlEventReader);
+
+ assertion.setIssuer(issuer);
+ } else if (JBossSAMLConstants.SUBJECT.get().equalsIgnoreCase(tag)) {
+ SAML11SubjectParser subjectParser = new SAML11SubjectParser();
+ SAML11SubjectType subject = (SAML11SubjectType) subjectParser.parse(xmlEventReader);
+ SAML11SubjectStatementType subStat = new SAML11SubjectStatementType();
+ subStat.setSubject(subject);
+ } else if (JBossSAMLConstants.CONDITIONS.get().equalsIgnoreCase(tag)) {
+ startElement = (StartElement) xmlEvent;
+
+ SAML11ConditionsType conditions = SAML11ParserUtil.parseSAML11Conditions(xmlEventReader);
+ assertion.setConditions(conditions);
+ } else if (SAML11Constants.AUTHENTICATION_STATEMENT.equals(tag)) {
+ startElement = (StartElement) xmlEvent;
+ SAML11AuthenticationStatementType authStat = SAML11ParserUtil.parseAuthenticationStatement(xmlEventReader);
+ assertion.add(authStat);
+ } else if (SAML11Constants.ATTRIBUTE_STATEMENT.equalsIgnoreCase(tag)) {
+ SAML11AttributeStatementType attributeStatementType = SAML11ParserUtil
+ .parseSAML11AttributeStatement(xmlEventReader);
+ assertion.add(attributeStatementType);
+ } else if (SAML11Constants.AUTHORIZATION_DECISION_STATEMENT.equalsIgnoreCase(tag)) {
+ SAML11AuthorizationDecisionStatementType authzStat = SAML11ParserUtil
+ .parseSAML11AuthorizationDecisionStatement(xmlEventReader);
+ assertion.add(authzStat);
+ } else
+ throw logger.parserUnknownTag(tag, 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 SAML11AssertionType parseBaseAttributes(StartElement nextElement) throws ParsingException {
+ Attribute idAttribute = nextElement.getAttributeByName(new QName(SAML11Constants.ASSERTIONID));
+ if (idAttribute == null)
+ throw logger.parserRequiredAttribute("AssertionID");
+ String id = StaxParserUtil.getAttributeValue(idAttribute);
+
+ Attribute majVersionAttribute = nextElement.getAttributeByName(new QName(SAML11Constants.MAJOR_VERSION));
+ String majVersion = StaxParserUtil.getAttributeValue(majVersionAttribute);
+ StringUtil.match("1", majVersion);
+
+ Attribute minVersionAttribute = nextElement.getAttributeByName(new QName(SAML11Constants.MINOR_VERSION));
+ String minVersion = StaxParserUtil.getAttributeValue(minVersionAttribute);
+ StringUtil.match("1", minVersion);
+
+ Attribute issueInstantAttribute = nextElement.getAttributeByName(new QName(JBossSAMLConstants.ISSUE_INSTANT.get()));
+ XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(issueInstantAttribute));
+
+ return new SAML11AssertionType(id, issueInstant);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11RequestParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11RequestParser.java
new file mode 100755
index 0000000..6abf6c6
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11RequestParser.java
@@ -0,0 +1,116 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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;
+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.v2.util.XMLTimeUtil;
+import org.keycloak.dom.saml.v1.protocol.SAML11AttributeQueryType;
+import org.keycloak.dom.saml.v1.protocol.SAML11AuthenticationQueryType;
+import org.keycloak.dom.saml.v1.protocol.SAML11AuthorizationDecisionQueryType;
+import org.keycloak.dom.saml.v1.protocol.SAML11RequestType;
+
+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;
+
+/**
+ * Parse the SAML2 AuthnRequest
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since June 24, 2011
+ */
+public class SAML11RequestParser implements ParserNamespaceSupport {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ protected SAML11RequestType parseRequiredAttributes(StartElement startElement) throws ParsingException {
+ Attribute idAttr = startElement.getAttributeByName(new QName(SAML11Constants.REQUEST_ID));
+ if (idAttr == null)
+ throw logger.parserRequiredAttribute(SAML11Constants.REQUEST_ID);
+
+ String id = StaxParserUtil.getAttributeValue(idAttr);
+
+ Attribute issueInstantAttr = startElement.getAttributeByName(new QName(SAML11Constants.ISSUE_INSTANT));
+ if (issueInstantAttr == null)
+ throw logger.parserRequiredAttribute(SAML11Constants.ISSUE_INSTANT);
+ XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(issueInstantAttr));
+ return new SAML11RequestType(id, issueInstant);
+ }
+
+ /**
+ * @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
+ */
+ public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
+ // Get the startelement
+ StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ StaxParserUtil.validate(startElement, SAML11Constants.REQUEST);
+
+ SAML11RequestType request = parseRequiredAttributes(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 (SAML11Constants.ATTRIBUTE_QUERY.equals(elementName)) {
+ startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ SAML11AttributeQueryType query = SAML11ParserUtil.parseSAML11AttributeQuery(xmlEventReader);
+ request.setQuery(query);
+ } else if (SAML11Constants.AUTHENTICATION_QUERY.equals(elementName)) {
+ startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ SAML11AuthenticationQueryType query = SAML11ParserUtil.parseSAML11AuthenticationQuery(xmlEventReader);
+ request.setQuery(query);
+ } else if (SAML11Constants.ASSERTION_ARTIFACT.equals(elementName)) {
+ startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ request.addAssertionArtifact(StaxParserUtil.getElementText(xmlEventReader));
+ } else if (SAML11Constants.AUTHORIZATION_DECISION_QUERY.equals(elementName)) {
+ startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ SAML11AuthorizationDecisionQueryType query = SAML11ParserUtil
+ .parseSAML11AuthorizationDecisionQueryType(xmlEventReader);
+ request.setQuery(query);
+ } else if (elementName.equals(JBossSAMLConstants.SIGNATURE.get())) {
+ request.setSignature(StaxParserUtil.getDOMElement(xmlEventReader));
+ } else if (SAML11Constants.ASSERTION_ID_REF.equals(elementName)) {
+ startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ request.addAssertionIDRef(StaxParserUtil.getElementText(xmlEventReader));
+ } else
+ throw logger.parserUnknownStartElement(elementName, startElement.getLocation());
+ }
+ return request;
+ }
+
+ /**
+ * @see {@link ParserNamespaceSupport#supports(QName)}
+ */
+ public boolean supports(QName qname) {
+ return JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(qname.getNamespaceURI());
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11ResponseParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11ResponseParser.java
new file mode 100755
index 0000000..8807834
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11ResponseParser.java
@@ -0,0 +1,189 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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.parsers.ParserNamespaceSupport;
+import org.keycloak.saml.common.util.StaxParserUtil;
+import org.keycloak.saml.processing.core.saml.v1.SAML11Constants;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.keycloak.dom.saml.v1.assertion.SAML11AssertionType;
+import org.keycloak.dom.saml.v1.protocol.SAML11ResponseType;
+import org.keycloak.dom.saml.v1.protocol.SAML11StatusCodeType;
+import org.keycloak.dom.saml.v1.protocol.SAML11StatusType;
+import org.keycloak.dom.saml.v2.protocol.StatusDetailType;
+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;
+
+/**
+ * Parse the SAML 11 Response
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since 23 June 2011
+ */
+public class SAML11ResponseParser implements ParserNamespaceSupport {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ 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);
+
+ Attribute idAttr = startElement.getAttributeByName(new QName(SAML11Constants.RESPONSE_ID));
+ if (idAttr == null)
+ throw logger.parserRequiredAttribute(SAML11Constants.RESPONSE_ID);
+ String id = StaxParserUtil.getAttributeValue(idAttr);
+
+ Attribute issueInstant = startElement.getAttributeByName(new QName(SAML11Constants.ISSUE_INSTANT));
+ if (issueInstant == null)
+ throw logger.parserRequiredAttribute(SAML11Constants.ISSUE_INSTANT);
+ XMLGregorianCalendar issueInstantVal = XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(issueInstant));
+
+ SAML11ResponseType response = new SAML11ResponseType(id, issueInstantVal);
+
+ 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.SIGNATURE.get().equals(elementName)) {
+ Element sig = StaxParserUtil.getDOMElement(xmlEventReader);
+ response.setSignature(sig);
+ } else if (JBossSAMLConstants.ASSERTION.get().equals(elementName)) {
+ SAML11AssertionParser assertionParser = new SAML11AssertionParser();
+ response.add((SAML11AssertionType) assertionParser.parse(xmlEventReader));
+ } else if (JBossSAMLConstants.STATUS.get().equals(elementName)) {
+ response.setStatus(parseStatus(xmlEventReader));
+ } else
+ throw logger.parserUnknownStartElement(elementName, startElement.getLocation());
+ }
+
+ return response;
+ }
+
+ /**
+ * Parse the status element
+ *
+ * @param xmlEventReader
+ *
+ * @return
+ *
+ * @throws ParsingException
+ */
+ protected SAML11StatusType parseStatus(XMLEventReader xmlEventReader) throws ParsingException {
+ // Get the Start Element
+ StartElement startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ String STATUS = JBossSAMLConstants.STATUS.get();
+ StaxParserUtil.validate(startElement, STATUS);
+
+ SAML11StatusType status = new SAML11StatusType();
+
+ while (xmlEventReader.hasNext()) {
+ startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
+
+ if (startElement == null)
+ break;
+
+ QName startElementName = startElement.getName();
+ String elementTag = startElementName.getLocalPart();
+
+ SAML11StatusCodeType statusCode = null;
+
+ 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 = new SAML11StatusCodeType(new QName(StaxParserUtil.getAttributeValue(valueAttr)));
+ }
+ status.setStatusCode(statusCode);
+
+ // Peek at the next start element to see if it is status code
+ startElement = StaxParserUtil.peekNextStartElement(xmlEventReader);
+ elementTag = startElement.getName().getLocalPart();
+ if (JBossSAMLConstants.STATUS_CODE.get().equals(elementTag)) {
+ SAML11StatusCodeType subStatusCodeType = null;
+ startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ Attribute subValueAttr = startElement.getAttributeByName(new QName("Value"));
+ if (subValueAttr != null) {
+ subStatusCodeType = new SAML11StatusCodeType(new QName(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;
+ }
+
+ /**
+ * @see {@link ParserNamespaceSupport#supports(QName)}
+ */
+ public boolean supports(QName qname) {
+ return SAML11Constants.PROTOCOL_11_NSURI.equals(qname.getNamespaceURI()) && RESPONSE.equals(qname.getLocalPart());
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11SubjectParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11SubjectParser.java
new file mode 100755
index 0000000..be38ea8
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAML11SubjectParser.java
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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;
+import org.keycloak.saml.processing.core.parsers.util.SAML11ParserUtil;
+import org.keycloak.saml.processing.core.saml.v1.SAML11Constants;
+import org.keycloak.dom.saml.v1.assertion.SAML11NameIdentifierType;
+import org.keycloak.dom.saml.v1.assertion.SAML11SubjectConfirmationType;
+import org.keycloak.dom.saml.v1.assertion.SAML11SubjectType;
+import org.keycloak.dom.saml.v1.assertion.SAML11SubjectType.SAML11SubjectTypeChoice;
+
+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 saml subject
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Oct 12, 2010
+ */
+public class SAML11SubjectParser implements ParserNamespaceSupport {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
+ */
+ public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
+ StaxParserUtil.getNextEvent(xmlEventReader);
+
+ SAML11SubjectType subject = new SAML11SubjectType();
+
+ // 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 (SAML11Constants.NAME_IDENTIFIER.equalsIgnoreCase(tag)) {
+ peekedElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ String val = StaxParserUtil.getElementText(xmlEventReader);
+ SAML11NameIdentifierType nameID = new SAML11NameIdentifierType(val);
+ Attribute formatAtt = peekedElement.getAttributeByName(new QName(SAML11Constants.FORMAT));
+ if (formatAtt != null) {
+ nameID.setFormat(URI.create(StaxParserUtil.getAttributeValue(formatAtt)));
+ }
+
+ Attribute nameQAtt = peekedElement.getAttributeByName(new QName(SAML11Constants.NAME_QUALIFIER));
+ if (nameQAtt != null) {
+ nameID.setNameQualifier(StaxParserUtil.getAttributeValue(nameQAtt));
+ }
+
+ SAML11SubjectTypeChoice subChoice = new SAML11SubjectTypeChoice(nameID);
+ subject.setChoice(subChoice);
+ } else if (JBossSAMLConstants.SUBJECT_CONFIRMATION.get().equalsIgnoreCase(tag)) {
+ SAML11SubjectConfirmationType subjectConfirmationType = SAML11ParserUtil
+ .parseSAML11SubjectConfirmation(xmlEventReader);
+ subject.setSubjectConfirmation(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());
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLArtifactResolveParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLArtifactResolveParser.java
new file mode 100755
index 0000000..47ed782
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLArtifactResolveParser.java
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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.dom.saml.v2.protocol.ArtifactResolveType;
+
+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
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLArtifactResponseParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLArtifactResponseParser.java
new file mode 100755
index 0000000..8c28b77
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLArtifactResponseParser.java
@@ -0,0 +1,111 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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.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.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.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;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAssertionParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAssertionParser.java
new file mode 100755
index 0000000..8825448
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAssertionParser.java
@@ -0,0 +1,174 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.common.ErrorCodes;
+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.common.util.StringUtil;
+import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+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.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;
+
+/**
+ * Parse the saml assertion
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Oct 12, 2010
+ */
+public class SAMLAssertionParser implements ParserNamespaceSupport {
+
+ 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.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 {
+ Attribute idAttribute = nextElement.getAttributeByName(new QName(JBossSAMLConstants.ID.get()));
+ String id = StaxParserUtil.getAttributeValue(idAttribute);
+
+ Attribute versionAttribute = nextElement.getAttributeByName(new QName(JBossSAMLConstants.VERSION.get()));
+ String version = StaxParserUtil.getAttributeValue(versionAttribute);
+ StringUtil.match(JBossSAMLConstants.VERSION_2_0.get(), version);
+
+ Attribute issueInstantAttribute = nextElement.getAttributeByName(new QName(JBossSAMLConstants.ISSUE_INSTANT.get()));
+ XMLGregorianCalendar issueInstant = XMLTimeUtil.parse(StaxParserUtil.getAttributeValue(issueInstantAttribute));
+
+ return new AssertionType(id, issueInstant);
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAttributeQueryParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAttributeQueryParser.java
new file mode 100755
index 0000000..7c1d38c
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAttributeQueryParser.java
@@ -0,0 +1,92 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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 org.keycloak.dom.saml.v2.protocol.AttributeQueryType;
+
+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
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAuthNRequestParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAuthNRequestParser.java
new file mode 100755
index 0000000..55a5cfd
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLAuthNRequestParser.java
@@ -0,0 +1,212 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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.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 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
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLConditionsParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLConditionsParser.java
new file mode 100755
index 0000000..c9d44e4
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLConditionsParser.java
@@ -0,0 +1,174 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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 org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType;
+import org.keycloak.dom.saml.v2.assertion.ConditionsType;
+import org.keycloak.dom.saml.v2.assertion.OneTimeUseType;
+
+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;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParser.java
new file mode 100755
index 0000000..24c80f7
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParser.java
@@ -0,0 +1,129 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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.AbstractParser;
+import org.keycloak.saml.common.util.StaxParserUtil;
+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.saml.v1.SAML11Constants;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+/**
+ * Parse SAML payload
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Oct 12, 2010
+ */
+public class SAMLParser extends AbstractParser {
+
+ /**
+ * @see {@link org.keycloak.saml.common.parsers.ParserNamespaceSupport#parse(XMLEventReader)}
+ */
+ public Object parse(XMLEventReader xmlEventReader) throws ParsingException {
+ while (xmlEventReader.hasNext()) {
+ XMLEvent xmlEvent = StaxParserUtil.peek(xmlEventReader);
+
+ if (xmlEvent instanceof StartElement) {
+ StartElement startElement = (StartElement) xmlEvent;
+ QName startElementName = startElement.getName();
+ String nsURI = startElementName.getNamespaceURI();
+
+ String localPart = startElementName.getLocalPart();
+
+ String elementName = StaxParserUtil.getStartElementName(startElement);
+
+ if (elementName.equalsIgnoreCase(JBossSAMLConstants.ASSERTION.get())
+ || elementName.equals(JBossSAMLConstants.ENCRYPTED_ASSERTION.get())) {
+ if (nsURI.equals(SAML11Constants.ASSERTION_11_NSURI)) {
+ SAML11AssertionParser saml11AssertionParser = new SAML11AssertionParser();
+ return saml11AssertionParser.parse(xmlEventReader);
+ }
+ SAMLAssertionParser assertionParser = new SAMLAssertionParser();
+ return assertionParser.parse(xmlEventReader);
+ } else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
+ && JBossSAMLConstants.AUTHN_REQUEST.get().equals(startElementName.getLocalPart())) {
+ SAMLAuthNRequestParser authNRequestParser = new SAMLAuthNRequestParser();
+ return authNRequestParser.parse(xmlEventReader);
+ } else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
+ && JBossSAMLConstants.LOGOUT_REQUEST.get().equals(startElementName.getLocalPart())) {
+ SAMLSloRequestParser sloParser = new SAMLSloRequestParser();
+ return sloParser.parse(xmlEventReader);
+ } else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
+ && JBossSAMLConstants.LOGOUT_RESPONSE.get().equals(startElementName.getLocalPart())) {
+ SAMLSloResponseParser sloParser = new SAMLSloResponseParser();
+ return sloParser.parse(xmlEventReader);
+ } else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
+ && JBossSAMLConstants.RESPONSE.get().equals(startElementName.getLocalPart())) {
+ SAMLResponseParser responseParser = new SAMLResponseParser();
+ return responseParser.parse(xmlEventReader);
+ } else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
+ && JBossSAMLConstants.REQUEST_ABSTRACT.get().equals(startElementName.getLocalPart())) {
+ String xsiTypeValue = StaxParserUtil.getXSITypeValue(startElement);
+ throw new RuntimeException(ErrorCodes.UNKNOWN_XSI + xsiTypeValue);
+ } else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
+ && JBossSAMLConstants.ARTIFACT_RESOLVE.get().equals(startElementName.getLocalPart())) {
+ SAMLArtifactResolveParser artifactResolverParser = new SAMLArtifactResolveParser();
+ return artifactResolverParser.parse(xmlEventReader);
+ } else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
+ && JBossSAMLConstants.ARTIFACT_RESPONSE.get().equals(startElementName.getLocalPart())) {
+ SAMLArtifactResponseParser responseParser = new SAMLArtifactResponseParser();
+ return responseParser.parse(xmlEventReader);
+ } else if (JBossSAMLURIConstants.PROTOCOL_NSURI.get().equals(nsURI)
+ && JBossSAMLConstants.ATTRIBUTE_QUERY.get().equals(startElementName.getLocalPart())) {
+ SAMLAttributeQueryParser responseParser = new SAMLAttributeQueryParser();
+ return responseParser.parse(xmlEventReader);
+ } else if (JBossSAMLConstants.ENTITY_DESCRIPTOR.get().equals(localPart)) {
+ SAMLEntityDescriptorParser entityDescriptorParser = new SAMLEntityDescriptorParser();
+ return entityDescriptorParser.parse(xmlEventReader);
+ } else if (JBossSAMLConstants.ENTITIES_DESCRIPTOR.get().equals(localPart)) {
+ SAMLEntitiesDescriptorParser entityDescriptorParser = new SAMLEntitiesDescriptorParser();
+ return entityDescriptorParser.parse(xmlEventReader);
+ } else if (SAML11Constants.PROTOCOL_11_NSURI.equals(nsURI)
+ && JBossSAMLConstants.RESPONSE.get().equals(startElementName.getLocalPart())) {
+ SAML11ResponseParser responseParser = new SAML11ResponseParser();
+ return responseParser.parse(xmlEventReader);
+ } else if (SAML11Constants.PROTOCOL_11_NSURI.equals(nsURI)
+ && SAML11Constants.REQUEST.equals(startElementName.getLocalPart())) {
+ SAML11RequestParser reqParser = new SAML11RequestParser();
+ return reqParser.parse(xmlEventReader);
+ } else
+ throw new RuntimeException(ErrorCodes.UNKNOWN_START_ELEMENT + elementName + "::location="
+ + startElement.getLocation());
+ } else {
+ StaxParserUtil.getNextEvent(xmlEventReader);
+ }
+ }
+ 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());
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLRequestAbstractParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLRequestAbstractParser.java
new file mode 100755
index 0000000..2c39451
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLRequestAbstractParser.java
@@ -0,0 +1,109 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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 org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.assertion.SubjectType;
+import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
+
+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));
+ }
+ }
+
+ protected SubjectType getSubject(XMLEventReader xmlEventReader) throws ParsingException {
+ SAMLSubjectParser subjectParser = new SAMLSubjectParser();
+ return (SubjectType) subjectParser.parse(xmlEventReader);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLResponseParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLResponseParser.java
new file mode 100755
index 0000000..7d3c474
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLResponseParser.java
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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.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.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.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;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSloRequestParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSloRequestParser.java
new file mode 100755
index 0000000..0f6ba86
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSloRequestParser.java
@@ -0,0 +1,119 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.saml.processing.core.parsers.saml;
+
+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 org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
+
+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
+ 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.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;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSloResponseParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSloResponseParser.java
new file mode 100755
index 0000000..60216f7
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSloResponseParser.java
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
+
+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)) {
+ startElement = StaxParserUtil.getNextStartElement(xmlEventReader);
+ StaxParserUtil.bypassElementBlock(xmlEventReader, JBossSAMLConstants.SIGNATURE.get());
+ } 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.equals(qname.getLocalPart());
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLStatusResponseTypeParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLStatusResponseTypeParser.java
new file mode 100755
index 0000000..ab4b88e
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLStatusResponseTypeParser.java
@@ -0,0 +1,187 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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.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.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;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSubjectParser.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSubjectParser.java
new file mode 100755
index 0000000..8d676c4
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/saml/SAMLSubjectParser.java
@@ -0,0 +1,206 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.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.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.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;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SecurityActions.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SecurityActions.java
new file mode 100755
index 0000000..6ff7025
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SecurityActions.java
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Oct 25, 2010
+ */
+public class SecurityActions {
+
+ /**
+ * <p>Returns a system property value using the specified <code>key</code>. If not found the
+ * <code>defaultValue</code> will be returned.</p>
+ *
+ * @param key
+ * @param defaultValue
+ *
+ * @return
+ */
+ static String getSystemProperty(final String key, final String defaultValue) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(key, defaultValue);
+ }
+ });
+ } else {
+ return System.getProperty(key, defaultValue);
+ }
+ }
+
+ /**
+ * Load a resource based on the passed {@link Class} classloader. Failing which try with the Thread Context CL
+ *
+ * @param clazz
+ * @param resourceName
+ *
+ * @return
+ */
+ static URL loadResource(final Class<?> clazz, final String resourceName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<URL>() {
+ public URL run() {
+ URL url = null;
+ ClassLoader clazzLoader = clazz.getClassLoader();
+ url = clazzLoader.getResource(resourceName);
+
+ if (url == null) {
+ clazzLoader = Thread.currentThread().getContextClassLoader();
+ url = clazzLoader.getResource(resourceName);
+ }
+
+ return url;
+ }
+ });
+ } else {
+ URL url = null;
+ ClassLoader clazzLoader = clazz.getClassLoader();
+ url = clazzLoader.getResource(resourceName);
+
+ if (url == null) {
+ clazzLoader = Thread.currentThread().getContextClassLoader();
+ url = clazzLoader.getResource(resourceName);
+ }
+
+ return url;
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/SAML11Constants.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/SAML11Constants.java
new file mode 100755
index 0000000..ba325c9
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/SAML11Constants.java
@@ -0,0 +1,131 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v1;
+
+/**
+ * Constants for the SAML v1.1 Specifications
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jun 22, 2011
+ */
+public interface SAML11Constants {
+
+ String ACTION = "Action";
+
+ String ASSERTIONID = "AssertionID";
+
+ String ASSERTION_11_NSURI = "urn:oasis:names:tc:SAML:1.0:assertion";
+
+ String ASSERTION_ARTIFACT = "AssertionArtifact";
+
+ String ASSERTION_ID_REF = "AssertionIDReference";
+
+ String ATTRIBUTE_QUERY = "AttributeQuery";
+
+ String ATTRIBUTE_NAME = "AttributeName";
+
+ String ATTRIBUTE_NAMESPACE = "AttributeNamespace";
+
+ String ATTRIBUTE_STATEMENT = "AttributeStatement";
+
+ String AUDIENCE_RESTRICTION_CONDITION = "AudienceRestrictionCondition";
+
+ String AUTHENTICATION_INSTANT = "AuthenticationInstant";
+
+ String AUTHENTICATION_METHOD = "AuthenticationMethod";
+
+ String AUTH_METHOD_PASSWORD = "urn:oasis:names:tc:SAML:1.0:am:password";
+
+ String AUTH_METHOD_KERBEROS = "urn:ietf:rfc:1510";
+
+ String AUTH_METHOD_SRP = "urn:ietf:rfc:2945";
+
+ String AUTH_METHOD_TLS = "urn:ietf:rfc:2246";
+
+ String AUTHENTICATION_QUERY = "AuthenticationQuery";
+
+ String AUTHENTICATION_STATEMENT = "AuthenticationStatement";
+
+ String AUTHORITY_BINDING = "AuthorityBinding";
+
+ String AUTHORITY_KIND = "AuthorityKind";
+
+ String AUTHORIZATION_DECISION_QUERY = "AuthorizationDecisionQuery";
+
+ String AUTHORIZATION_DECISION_STATEMENT = "AuthorizationDecisionStatement";
+
+ String BINDING = "Binding";
+
+ String CONFIRMATION_METHOD = "ConfirmationMethod";
+
+ String DECISION = "Decision";
+
+ String DNS_ADDRESS = "DNSAddress";
+
+ String EVIDENCE = "Evidence";
+
+ String FORMAT = "Format";
+
+ String FORMAT_EMAIL_ADDRESS = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";
+
+ String FORMAT_UNSPECIFIED = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified";
+
+ String IN_RESPONSE_TO = "InResponseTo";
+
+ String IP_ADDRESS = "IPAddress";
+
+ String ISSUER = "Issuer";
+
+ String ISSUE_INSTANT = "IssueInstant";
+
+ String LOCATION = "Location";
+
+ String MAJOR_VERSION = "MajorVersion";
+
+ String MINOR_VERSION = "MinorVersion";
+
+ String NAME_IDENTIFIER = "NameIdentifier";
+
+ String NAME_QUALIFIER = "NameQualifier";
+
+ String NAMESPACE = "Namespace";
+
+ String PROTOCOL_11_NSURI = "urn:oasis:names:tc:SAML:1.0:protocol";
+
+ String RECIPIENT = "Recipient";
+
+ String REQUEST = "Request";
+
+ String REQUEST_ID = "RequestID";
+
+ String RESOURCE = "Resource";
+
+ String RESPONSE = "Response";
+
+ String RESPONSE_ID = "ResponseID";
+
+ String STATUS = "Status";
+
+ String STATUS_CODE = "StatusCode";
+
+ String STATUS_DETAIL = "StatusDetail";
+
+ String STATUS_MSG = "StatusMessage";
+
+ String VALUE = "Value";
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/BaseSAML11Writer.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/BaseSAML11Writer.java
new file mode 100755
index 0000000..2adfac7
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/BaseSAML11Writer.java
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v1.writers;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+
+import javax.xml.stream.XMLStreamWriter;
+
+/**
+ * @author Anil.Saldhana@redhat.com
+ * @since Jun 27, 2011
+ */
+public abstract class BaseSAML11Writer {
+
+ protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ protected static String PROTOCOL_PREFIX = "samlp";
+
+ protected static String ASSERTION_PREFIX = "saml";
+
+ protected static String XACML_SAML_PREFIX = "xacml-saml";
+
+ protected static String XACML_SAML_PROTO_PREFIX = "xacml-samlp";
+
+ protected static String XSI_PREFIX = "xsi";
+
+ protected XMLStreamWriter writer;
+
+ public BaseSAML11Writer(XMLStreamWriter writer) {
+ this.writer = writer;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11RequestWriter.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11RequestWriter.java
new file mode 100755
index 0000000..60b4695
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11RequestWriter.java
@@ -0,0 +1,171 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v1.writers;
+
+import org.keycloak.saml.common.constants.JBossSAMLConstants;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.StaxUtil;
+import org.keycloak.saml.processing.core.saml.v1.SAML11Constants;
+import org.keycloak.dom.saml.v1.assertion.SAML11ActionType;
+import org.keycloak.dom.saml.v1.assertion.SAML11AttributeDesignatorType;
+import org.keycloak.dom.saml.v1.assertion.SAML11AttributeType;
+import org.keycloak.dom.saml.v1.assertion.SAML11EvidenceType;
+import org.keycloak.dom.saml.v1.assertion.SAML11SubjectType;
+import org.keycloak.dom.saml.v1.protocol.SAML11AttributeQueryType;
+import org.keycloak.dom.saml.v1.protocol.SAML11AuthenticationQueryType;
+import org.keycloak.dom.saml.v1.protocol.SAML11AuthorizationDecisionQueryType;
+import org.keycloak.dom.saml.v1.protocol.SAML11QueryAbstractType;
+import org.keycloak.dom.saml.v1.protocol.SAML11RequestType;
+
+import javax.xml.stream.XMLStreamWriter;
+import java.net.URI;
+import java.util.List;
+
+/**
+ * Write the {@link org.keycloak.dom.saml.v1.protocol.SAML11RequestType} to stream
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jun 27, 2011
+ */
+public class SAML11RequestWriter extends BaseSAML11Writer {
+
+ protected String namespace = SAML11Constants.PROTOCOL_11_NSURI;
+
+ protected SAML11AssertionWriter assertionWriter;
+
+ public SAML11RequestWriter(XMLStreamWriter writer) {
+ super(writer);
+ assertionWriter = new SAML11AssertionWriter(writer);
+ }
+
+ public void write(SAML11RequestType request) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, SAML11Constants.REQUEST, namespace);
+ StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, namespace);
+ StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, SAML11Constants.ASSERTION_11_NSURI);
+ StaxUtil.writeDefaultNameSpace(writer, namespace);
+
+ // Attributes
+ StaxUtil.writeAttribute(writer, SAML11Constants.REQUEST_ID, request.getID());
+ StaxUtil.writeAttribute(writer, SAML11Constants.MAJOR_VERSION, request.getMajorVersion() + "");
+ StaxUtil.writeAttribute(writer, SAML11Constants.MINOR_VERSION, request.getMinorVersion() + "");
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ISSUE_INSTANT.get(), request.getIssueInstant().toString());
+
+ List<String> assertionIDRefs = request.getAssertionIDRef();
+ for (String assertionIDRef : assertionIDRefs) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, SAML11Constants.ASSERTION_ID_REF,
+ SAML11Constants.ASSERTION_11_NSURI);
+ StaxUtil.writeCharacters(writer, assertionIDRef);
+ StaxUtil.writeEndElement(writer);
+ }
+
+ List<String> assertionArtifacts = request.getAssertionArtifact();
+ for (String assertionArtifact : assertionArtifacts) {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, SAML11Constants.ASSERTION_ARTIFACT, namespace);
+ StaxUtil.writeCharacters(writer, assertionArtifact);
+ StaxUtil.writeEndElement(writer);
+ }
+
+ SAML11QueryAbstractType query = request.getQuery();
+ if (query instanceof SAML11AuthenticationQueryType) {
+ SAML11AuthenticationQueryType authQuery = (SAML11AuthenticationQueryType) query;
+ write(authQuery);
+ } else if (query instanceof SAML11AttributeQueryType) {
+ SAML11AttributeQueryType attQuery = (SAML11AttributeQueryType) query;
+ write(attQuery);
+ } else if (query instanceof SAML11AuthenticationQueryType) {
+ SAML11AuthenticationQueryType attQuery = (SAML11AuthenticationQueryType) query;
+ write(attQuery);
+ } else if (query instanceof SAML11AuthorizationDecisionQueryType) {
+ SAML11AuthorizationDecisionQueryType attQuery = (SAML11AuthorizationDecisionQueryType) query;
+ write(attQuery);
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ public void write(SAML11AuthenticationQueryType auth) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, SAML11Constants.AUTHENTICATION_QUERY, namespace);
+
+ URI authMethod = auth.getAuthenticationMethod();
+ if (authMethod != null) {
+ StaxUtil.writeAttribute(writer, SAML11Constants.AUTHENTICATION_METHOD, authMethod.toString());
+ }
+
+ SAML11SubjectType subject = auth.getSubject();
+ if (subject != null) {
+ assertionWriter.write(subject);
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ public void write(SAML11AttributeQueryType attr) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, SAML11Constants.ATTRIBUTE_QUERY, namespace);
+
+ URI resource = attr.getResource();
+ if (resource != null) {
+ StaxUtil.writeAttribute(writer, SAML11Constants.RESOURCE, resource.toString());
+ }
+
+ SAML11SubjectType subject = attr.getSubject();
+ if (subject != null) {
+ assertionWriter.write(subject);
+ }
+
+ List<SAML11AttributeDesignatorType> attributes = attr.get();
+ for (SAML11AttributeDesignatorType attribute : attributes) {
+ if (attribute instanceof SAML11AttributeType) {
+ SAML11AttributeType sat = (SAML11AttributeType) attribute;
+ assertionWriter.write(sat);
+ } else
+ throw logger.writerUnknownTypeError(attribute.getClass().getName());
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ public void write(SAML11AuthorizationDecisionQueryType attr) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, SAML11Constants.AUTHORIZATION_DECISION_QUERY, namespace);
+
+ URI resource = attr.getResource();
+ if (resource != null) {
+ StaxUtil.writeAttribute(writer, SAML11Constants.RESOURCE, resource.toString());
+ }
+
+ SAML11SubjectType subject = attr.getSubject();
+ if (subject != null) {
+ assertionWriter.write(subject);
+ }
+
+ List<SAML11ActionType> actions = attr.get();
+ for (SAML11ActionType action : actions) {
+ assertionWriter.write(action);
+ }
+
+ SAML11EvidenceType evidence = attr.getEvidence();
+ if (evidence != null) {
+ assertionWriter.write(evidence);
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11ResponseWriter.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11ResponseWriter.java
new file mode 100755
index 0000000..7e6f6fd
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v1/writers/SAML11ResponseWriter.java
@@ -0,0 +1,137 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v1.writers;
+
+import org.keycloak.saml.common.constants.JBossSAMLConstants;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.StaxUtil;
+import org.keycloak.saml.common.util.StringUtil;
+import org.keycloak.saml.processing.core.saml.v1.SAML11Constants;
+import org.keycloak.dom.saml.common.CommonStatusDetailType;
+import org.keycloak.dom.saml.v1.assertion.SAML11AssertionType;
+import org.keycloak.dom.saml.v1.protocol.SAML11ResponseType;
+import org.keycloak.dom.saml.v1.protocol.SAML11StatusCodeType;
+import org.keycloak.dom.saml.v1.protocol.SAML11StatusType;
+import org.w3c.dom.Element;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamWriter;
+import java.net.URI;
+import java.util.List;
+
+/**
+ * Write the {@link SAML11ResponseType} to stream
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jun 29, 2011
+ */
+public class SAML11ResponseWriter extends BaseSAML11Writer {
+
+ protected String namespace = SAML11Constants.PROTOCOL_11_NSURI;
+
+ protected SAML11AssertionWriter assertionWriter;
+
+ public SAML11ResponseWriter(XMLStreamWriter writer) {
+ super(writer);
+ assertionWriter = new SAML11AssertionWriter(writer);
+ }
+
+ public void write(SAML11ResponseType response) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, SAML11Constants.RESPONSE, namespace);
+ StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, namespace);
+ StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, SAML11Constants.ASSERTION_11_NSURI);
+
+ // Attributes
+ StaxUtil.writeAttribute(writer, SAML11Constants.RESPONSE_ID, response.getID());
+ StaxUtil.writeAttribute(writer, SAML11Constants.MAJOR_VERSION, response.getMajorVersion() + "");
+ StaxUtil.writeAttribute(writer, SAML11Constants.MINOR_VERSION, response.getMinorVersion() + "");
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ISSUE_INSTANT.get(), response.getIssueInstant().toString());
+ String inResp = response.getInResponseTo();
+ if (StringUtil.isNotNull(inResp)) {
+ StaxUtil.writeAttribute(writer, SAML11Constants.IN_RESPONSE_TO, inResp);
+ }
+
+ URI recipient = response.getRecipient();
+ if (recipient != null) {
+ StaxUtil.writeAttribute(writer, SAML11Constants.RECIPIENT, recipient.toString());
+ }
+
+ Element sig = response.getSignature();
+ if (sig != null) {
+ StaxUtil.writeDOMElement(writer, sig);
+ }
+
+ SAML11StatusType status = response.getStatus();
+ if (status != null) {
+ write(status);
+ }
+
+ List<SAML11AssertionType> assertions = response.get();
+ for (SAML11AssertionType assertion : assertions) {
+ assertionWriter.write(assertion);
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ public void write(SAML11StatusType status) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, SAML11Constants.STATUS, namespace);
+
+ SAML11StatusCodeType statusCode = status.getStatusCode();
+ if (statusCode != null) {
+ write(statusCode);
+ }
+
+ String statusMsg = status.getStatusMessage();
+ if (StringUtil.isNotNull(statusMsg)) {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, SAML11Constants.STATUS_MSG, namespace);
+ StaxUtil.writeCharacters(writer, statusMsg);
+ StaxUtil.writeEndElement(writer);
+ }
+
+ CommonStatusDetailType details = status.getStatusDetail();
+ if (details != null) {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, SAML11Constants.STATUS_DETAIL, namespace);
+ List<Object> objs = details.getAny();
+ for (Object theObj : objs) {
+ StaxUtil.writeCharacters(writer, theObj.toString());
+ }
+ StaxUtil.writeEndElement(writer);
+ }
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ public void write(SAML11StatusCodeType statusCode) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, SAML11Constants.STATUS_CODE, namespace);
+
+ QName value = statusCode.getValue();
+ if (value == null)
+ throw logger.writerNullValueError("Attribute Value");
+ StaxUtil.writeAttribute(writer, SAML11Constants.VALUE, value);
+
+ SAML11StatusCodeType secondCode = statusCode.getStatusCode();
+ if (secondCode != null) {
+ write(secondCode);
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/common/IDGenerator.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/common/IDGenerator.java
new file mode 100755
index 0000000..bd0248a
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/common/IDGenerator.java
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.common;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+
+import java.util.UUID;
+
+/**
+ * Utility class that generates unique IDs
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jan 5, 2009
+ */
+public class IDGenerator {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /*
+ * Create a basic unique ID
+ */
+ public static String create() {
+ return UUID.randomUUID().toString();
+ }
+
+ /**
+ * Create an id that is prefixed by a string
+ *
+ * @param prefix
+ *
+ * @return an id
+ *
+ * @throws IllegalArgumentException when prefix is null
+ */
+ public static String create(String prefix) {
+ if (prefix == null)
+ throw logger.nullArgumentError("prefix");
+ StringBuilder sb = new StringBuilder(prefix);
+ sb.append(IDGenerator.create());
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/common/SAMLDocumentHolder.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/common/SAMLDocumentHolder.java
new file mode 100755
index 0000000..30bef07
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/common/SAMLDocumentHolder.java
@@ -0,0 +1,64 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.common;
+
+import org.keycloak.dom.saml.v2.SAML2Object;
+import org.w3c.dom.Document;
+
+/**
+ * A Holder class that can store the SAML object as well as the corresponding DOM object.
+ *
+ * Users of this class need to make it threadsafe by having one instance per thread (ThreadLocal)
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Aug 13, 2009
+ */
+public class SAMLDocumentHolder {
+
+ private SAML2Object samlObject;
+ private Document samlDocument;
+
+ public SAMLDocumentHolder(SAML2Object samlObject) {
+ this.samlObject = samlObject;
+ }
+
+ public SAMLDocumentHolder(Document samlDocument) {
+ this.samlDocument = samlDocument;
+ }
+
+ public SAMLDocumentHolder(SAML2Object samlObject, Document samlDocument) {
+ this.samlObject = samlObject;
+ this.samlDocument = samlDocument;
+ }
+
+ public SAML2Object getSamlObject() {
+ return samlObject;
+ }
+
+ public void setSamlObject(SAML2Object samlObject) {
+ this.samlObject = samlObject;
+ }
+
+ public Document getSamlDocument() {
+ return samlDocument;
+ }
+
+ public void setSamlDocument(Document samlDocument) {
+ this.samlDocument = samlDocument;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/constants/X500SAMLProfileConstants.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/constants/X500SAMLProfileConstants.java
new file mode 100755
index 0000000..3712f53
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/constants/X500SAMLProfileConstants.java
@@ -0,0 +1,154 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.constants;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * X500 SAML Profile Constants Adapted from
+ * http://code.google.com/p/simplesamlphp/source/browse/trunk/attributemap/name2oid.php?r=2654
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Sep 11, 2009
+ */
+public enum X500SAMLProfileConstants {
+ A_RECORD("aRecord", "urn:oid:0.9.2342.19200300.100.1.26"), ALIASED_ENTRY_NAME("aliasedEntryName", "urn:oid:2.5.4.1"), ALIASED_OBJECT_NAME(
+ "aliasedObjectName", "urn:oid:2.5.4.1"), ASSOCIATED_DOMAIN("associatedDomain", "urn:oid:0.9.2342.19200300.100.1.37"), ASSOCIATED_NAME(
+ "associatedName", "urn:oid:0.9.2342.19200300.100.1.38"), AUDIO("audio", "urn:oid:0.9.2342.19200300.100.1.55"), AUTHORITY_REVOCATION_LIST(
+ "authorityRevocationList", "urn:oid:2.5.4.38"), BINDING_NAME("buildingName", "urn:oid:0.9.2342.19200300.100.1.48"), BUSINESS_CATEGORY(
+ "businessCategory", "urn:oid:2.5.4.15"), C("c", "urn:oid:2.5.4.6"), CA_CERTIFICATE("cACertificate",
+ "urn:oid:2.5.4.37"), CNAME_RECORD("cNAMERecord", "urn:oid:0.9.2342.19200300.100.1.31"), CAR_LICENSE("carLicense",
+ "urn:oid:2.16.840.1.113730.3.1.1"), CRL("certificateRevocationList", "urn:oid:2.5.4.39"), CN("cn",
+ "urn:oid:2.5.4.3"), CO("co", "urn:oid:0.9.2342.19200300.100.1.43"), COMMON_NAME("commonName", "urn:oid:2.5.4.3"), COUNTRY_NAME(
+ "countryName", "urn:oid:2.5.4.6"), CROSS_CERTIFICATE_PAIR("crossCertificatePair", "urn:oid:2.5.4.40"), D_IT_REDIRECT(
+ "dITRedirect", "urn:oid:0.9.2342.19200300.100.1.54"), D_SA_QUALITY("dSAQuality",
+ "urn:oid:0.9.2342.19200300.100.1.49"), DC("dc", "urn:oid:0.9.2342.19200300.100.1.25"), DELTA_REVOCATION_LIST(
+ "deltaRevocationList", "urn:oid:2.5.4.53"), DEPARTMENT_NUMBER("departmentNumber", "urn:oid:2.16.840.1.113730.3.1.2"), DESCRIPTION(
+ "description", "urn:oid:2.5.4.13"), DESTINATION_INDICATOR("destinationIndicator", "urn:oid:2.5.4.27"), DISPLAY_NAME(
+ "displayName", "urn:oid:2.16.840.1.113730.3.1.241"), DISTINGUISHED_NAME("distinguishedName", "urn:oid:2.5.4.49"), DMD_NAME(
+ "dmdName", "urn:oid:2.5.4.54"), DN_QUALIFIER("dnQualifier", "urn:oid:2.5.4.46"), DOCUMENT_AUTHOR("documentAuthor",
+ "urn:oid:0.9.2342.19200300.100.1.14"), DOCUMENT_IDENTIFIER("documentIdentifier",
+ "urn:oid:0.9.2342.19200300.100.1.11"), DOCUMENT_LOCATION("documentLocation", "urn:oid:0.9.2342.19200300.100.1.15"), DOCUMENT_PUBLISHER(
+ "documentPublisher", "urn:oid:0.9.2342.19200300.100.1.56"), DOCUMENT_TITLE("documentTitle",
+ "urn:oid:0.9.2342.19200300.100.1.12"), DOCUMENT_VERSION("documentVersion", "urn:oid:0.9.2342.19200300.100.1.13"), DOMAIN_COMPONENT(
+ "domainComponent", "urn:oid:0.9.2342.19200300.100.1.25"), DRINK("drink", "urn:oid:0.9.2342.19200300.100.1.5"), EDU_ORG_HOMEPAGEURI(
+ "eduOrgHomePageURI", "urn:oid:1.3.6.1.4.1.5923.1.2.1.2"), EDU_ORG_IDENTITY_AUTHN_POLICYURI(
+ "eduOrgIdentityAuthNPolicyURI", "urn:oid:1.3.6.1.4.1.5923.1.2.1.3"), EDU_ORG_LEGALNAME("eduOrgLegalName",
+ "urn:oid:1.3.6.1.4.1.5923.1.2.1.4"), EDU_ORG_SUPERIORURI("eduOrgSuperiorURI", "urn:oid:1.3.6.1.4.1.5923.1.2.1.5"), EDU_ORG_WHITEPAGESURI(
+ "eduOrgWhitePagesURI", "urn:oid:1.3.6.1.4.1.5923.1.2.1.6"), EDU_PERSON_AFFLIATION("eduPersonAffiliation",
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.1"), EDU_PERSON_ENTITLEMENT("eduPersonEntitlement",
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.7"), EDU_PERSON_NICKNAME("eduPersonNickname", "urn:oid:1.3.6.1.4.1.5923.1.1.1.2"), EDU_PERSON_ORG_DN(
+ "eduPersonOrgDN", "urn:oid:1.3.6.1.4.1.5923.1.1.1.3"), EDU_PERSION_ORG_UNIT_DN("eduPersonOrgUnitDN",
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.4"), EDU_PERSON_PRIMARY_AFFLIATION("eduPersonPrimaryAffiliation",
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.5"), EDU_PERSON_PRIMARY_ORG_UNIT_DN("eduPersonPrimaryOrgUnitDN",
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.8"), EDU_PERSON_PRINCIPAL_NAME("eduPersonPrincipalName",
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.6"), EDU_PERSON_SCOPED_AFFLIATION("eduPersonScopedAffiliation",
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.9"), EDU_PERSON_TARGETED_ID("eduPersonTargetedID",
+ "urn:oid:1.3.6.1.4.1.5923.1.1.1.10"), EMAIL("email", "urn:oid:1.2.840.113549.1.9.1"), EMAIL_ADDRESS("emailAddress",
+ "urn:oid:1.2.840.113549.1.9.1"), EMPLOYEE_NUMBER("employeeNumber", "urn:oid:2.16.840.1.113730.3.1.3"), EMPLOYEE_TYPE(
+ "employeeType", "urn:oid:2.16.840.1.113730.3.1.4"), ENHANCED_SEARCH_GUIDE("enhancedSearchGuide", "urn:oid:2.5.4.47"), FAX_TELEPHONE_NUMBER(
+ "facsimileTelephoneNumber", "urn:oid:2.5.4.23"), FAVORITE_DRINK("favouriteDrink",
+ "urn:oid:0.9.2342.19200300.100.1.5"), FAX("fax", "urn:oid:2.5.4.23"), FEDERATION_FEIDE_SCHEMA_VERSION(
+ "federationFeideSchemaVersion", "urn:oid:1.3.6.1.4.1.2428.90.1.9"), FRIENDLY_COUNTRY_NAME("friendlyCountryName",
+ "urn:oid:0.9.2342.19200300.100.1.43"), GENERATION_QUALIFIER("generationQualifier", "urn:oid:2.5.4.44"), GIVEN_NAME(
+ "givenName", "urn:oid:2.5.4.42"), GN("gn", "urn:oid:2.5.4.42"), HOME_PHONE("homePhone",
+ "urn:oid:0.9.2342.19200300.100.1.20"), HOME_POSTAL_ADDRESS("homePostalAddress",
+ "urn:oid:0.9.2342.19200300.100.1.39"), HOME_TELEPHONE_NUMBER("homeTelephoneNumber",
+ "urn:oid:0.9.2342.19200300.100.1.20"), HOST("host", "urn:oid:0.9.2342.19200300.100.1.9"), HOUSE_IDENTIFIER(
+ "houseIdentifier", "urn:oid:2.5.4.51"), INFO("info", "urn:oid:0.9.2342.19200300.100.1.4"), INITIALS("initials",
+ "urn:oid:2.5.4.43"), INTERNATIONAL_ISDN_NUMBER("internationaliSDNNumber", "urn:oid:2.5.4.25"), IS_MEMBEROF(
+ "isMemberOf", "urn:oid:1.3.6.1.4.1.5923.1.5.1.1"), JANET_MAILBOX("janetMailbox",
+ "urn:oid:0.9.2342.19200300.100.1.46"), JPEG_PHOTO("jpegPhoto", "urn:oid:0.9.2342.19200300.100.1.60"), KNOWLEDGE_INFORMATION(
+ "knowledgeInformation", "urn:oid:2.5.4.2"), L("l", "urn:oid:2.5.4.7"), LABELED_URI("labeledURI",
+ "urn:oid:1.3.6.1.4.1.250.1.57"), LOCALITY_NAME("localityName", "urn:oid:2.5.4.7"), M_DRECORD("mDRecord",
+ "urn:oid:0.9.2342.19200300.100.1.27"), M_XRECORD("mXRecord", "urn:oid:0.9.2342.19200300.100.1.28"), MAIL("mail",
+ "urn:oid:0.9.2342.19200300.100.1.3"), MAIL_PREFERENCEOPTION("mailPreferenceOption",
+ "urn:oid:0.9.2342.19200300.100.1.47"), MANAGER("manager", "urn:oid:0.9.2342.19200300.100.1.10"), MEMBER("member",
+ "urn:oid:2.5.4.31"), MOBILE("mobile", "urn:oid:0.9.2342.19200300.100.1.41"), MOBILE_TELEPHONE_NUMBER(
+ "mobileTelephoneNumber", "urn:oid:0.9.2342.19200300.100.1.41"), N_SRECORD("nSRecord",
+ "urn:oid:0.9.2342.19200300.100.1.29"), NAME("name", "urn:oid:2.5.4.41"), NOR_EDU_ORG_ACRONYM("norEduOrgAcronym",
+ "urn:oid:1.3.6.1.4.1.2428.90.1.6"), NOR_EDU_ORG_NIN("norEduOrgNIN", "urn:oid:1.3.6.1.4.1.2428.90.1.12"), NOR_EDU_ORG_SCHEMA_VERSION(
+ "norEduOrgSchemaVersion", "urn:oid:1.3.6.1.4.1.2428.90.1.11"), NOR_EDU_ORG_UNIQUE_IDENTIFIER(
+ "norEduOrgUniqueIdentifier", "urn:oid:1.3.6.1.4.1.2428.90.1.7"), NOR_EDU_ORG_UNIQUE_NUMBER("norEduOrgUniqueNumber",
+ "urn:oid:1.3.6.1.4.1.2428.90.1.1"), NOR_EDU_ORG_UNIT_UNIQUE_IDENTIFIER("norEduOrgUnitUniqueIdentifier",
+ "urn:oid:1.3.6.1.4.1.2428.90.1.8"), NOR_EDU_ORG_UNIT_UNIQUE_NUMBER("norEduOrgUnitUniqueNumber",
+ "urn:oid:1.3.6.1.4.1.2428.90.1.2"), NOR_EDU_PERSON_BIRTH_DATE("norEduPersonBirthDate",
+ "urn:oid:1.3.6.1.4.1.2428.90.1.3"), NOR_EDU_PERSON_LIN("norEduPersonLIN", "urn:oid:1.3.6.1.4.1.2428.90.1.4"), NOR_EDU_PERSON_NIN(
+ "norEduPersonNIN", "urn:oid:1.3.6.1.4.1.2428.90.1.5"), O("o", "urn:oid:2.5.4.10"), OBJECT_CLASS("objectClass",
+ "urn:oid:2.5.4.0"), ORGANIZATION_NAME("organizationName", "urn:oid:2.5.4.10"), ORGANIZATIONAL_STATUS(
+ "organizationalStatus", "urn:oid:0.9.2342.19200300.100.1.45"), ORGANIZATIONAL_UNIT_NAME("organizationalUnitName",
+ "urn:oid:2.5.4.11"), OTHER_MAIL_BOX("otherMailbox", "urn:oid:0.9.2342.19200300.100.1.22"), OU("ou",
+ "urn:oid:2.5.4.11"), OWNER("owner", "urn:oid:2.5.4.32"), PAGER("pager", "urn:oid:0.9.2342.19200300.100.1.42"), PAGER_TELEPHONE_NUMBER(
+ "pagerTelephoneNumber", "urn:oid:0.9.2342.19200300.100.1.42"), PERSONAL_SIGNATURE("personalSignature",
+ "urn:oid:0.9.2342.19200300.100.1.53"), PERSONAL_TITLE("personalTitle", "urn:oid:0.9.2342.19200300.100.1.40"), PHOTO(
+ "photo", "urn:oid:0.9.2342.19200300.100.1.7"), PHYSICAL_DELIVERY_OFFICE_NAME("physicalDeliveryOfficeName",
+ "urn:oid:2.5.4.19"), PKCS_9_EMAIL("pkcs9email", "urn:oid:1.2.840.113549.1.9.1"), POST_OFFICE_BOX("postOfficeBox",
+ "urn:oid:2.5.4.18"), POSTAL_ADDRESS("postalAddress", "urn:oid:2.5.4.16"), POSTAL_CODE("postalCode",
+ "urn:oid:2.5.4.17"), PREFERRED_DELIVERY_METHOD("preferredDeliveryMethod", "urn:oid:2.5.4.28"), PREFERRED_LANGUAGE(
+ "preferredLanguage", "urn:oid:2.16.840.1.113730.3.1.39"), PRESENTATION_ADDRESS("presentationAddress",
+ "urn:oid:2.5.4.29"), PROTOCOL_INFORMATION("protocolInformation", "urn:oid:2.5.4.48"), PSEUDONYM("pseudonym",
+ "urn:oid:2.5.4.65"), REGISTERED_ADDRESS("registeredAddress", "urn:oid:2.5.4.26"), RFC_822_MAILBOX("rfc822Mailbox",
+ "urn:oid:0.9.2342.19200300.100.1.3"), ROLE_OCCUPANT("roleOccupant", "urn:oid:2.5.4.33"), ROOM_NUMBER("roomNumber",
+ "urn:oid:0.9.2342.19200300.100.1.6"), S_OAR_RECORD("sOARecord", "urn:oid:0.9.2342.19200300.100.1.30"), SEARCH_GUIDE(
+ "searchGuide", "urn:oid:2.5.4.14"), SECRETARY("secretary", "urn:oid:0.9.2342.19200300.100.1.21"), SEE_ALSO(
+ "seeAlso", "urn:oid:2.5.4.34"), SERIAL_NUMBER("serialNumber", "urn:oid:2.5.4.5"), SINGLE_LEVEL_QUALITY(
+ "singleLevelQuality", "urn:oid:0.9.2342.19200300.100.1.50"), SN("sn", "urn:oid:2.5.4.4"), ST("st",
+ "urn:oid:2.5.4.8"), STATE_OR_PROVINCE_NAME("stateOrProvinceName", "urn:oid:2.5.4.8"), STREET("street",
+ "urn:oid:2.5.4.9"), STREET_ADDRESS("streetAddress", "urn:oid:2.5.4.9"), SUBTREE_MAXIMUM_QUALITY(
+ "subtreeMaximumQuality", "urn:oid:0.9.2342.19200300.100.1.52"), SUBTREE_MINIMUM_QUALITY("subtreeMinimumQuality",
+ "urn:oid:0.9.2342.19200300.100.1.51"), SUPPORTED_ALGORITHMS("supportedAlgorithms", "urn:oid:2.5.4.52"), SUPPORTED_APPLICATION_CONTEXT(
+ "supportedApplicationContext", "urn:oid:2.5.4.30"), SURNAME("surname", "urn:oid:2.5.4.4"), TELEPHONE_NUMBER(
+ "telephoneNumber", "urn:oid:2.5.4.20"), TELETEX_TERMINAL_IDENTIFIER("teletexTerminalIdentifier", "urn:oid:2.5.4.22"), TELEX_NUMBER(
+ "telexNumber", "urn:oid:2.5.4.21"), TEXT_ENCODED_OR_ADDRESS("textEncodedORAddress",
+ "urn:oid:0.9.2342.19200300.100.1.2"), TITLE("title", "urn:oid:2.5.4.12"), UID("uid",
+ "urn:oid:0.9.2342.19200300.100.1.1"), UNIQUE_IDENTIFIER("uniqueIdentifier", "urn:oid:0.9.2342.19200300.100.1.44"), UNIQUE_MEMBER(
+ "uniqueMember", "urn:oid:2.5.4.50"), USER_CERTIFICATE("userCertificate", "urn:oid:2.5.4.36"), USER_CLASS(
+ "userClass", "urn:oid:0.9.2342.19200300.100.1.8"), USER_PKCS12("userPKCS12", "urn:oid:2.16.840.1.113730.3.1.216"), USER_PASSWORD(
+ "userPassword", "urn:oid:2.5.4.35"), USER_SMIME_CERTIFICATE("userSMIMECertificate",
+ "urn:oid:2.16.840.1.113730.3.1.40"), USERID("userid", "urn:oid:0.9.2342.19200300.100.1.1"), X121_ADDRESS(
+ "x121Address", "urn:oid:2.5.4.24"), X500_UNIQUE_IDENTIFIER("x500UniqueIdentifier", "urn:oid:2.5.4.45");
+
+ private String friendlyName = null;
+ private String uri = null;
+
+ private static final Map<String, String> lookup = new HashMap<String, String>();
+
+ static {
+ for (X500SAMLProfileConstants s : EnumSet.allOf(X500SAMLProfileConstants.class))
+ lookup.put(s.friendlyName, s.uri);
+ }
+
+ private X500SAMLProfileConstants(String friendlyName, String uristr) {
+ this.uri = uristr;
+ this.friendlyName = friendlyName;
+ }
+
+ public String get() {
+ return this.uri;
+ }
+
+ public String getFriendlyName() {
+ return friendlyName;
+ }
+
+ public static String getOID(final String key) {
+ return lookup.get(key);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java
new file mode 100755
index 0000000..ce40812
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/JBossSAMLAuthnResponseFactory.java
@@ -0,0 +1,217 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.factories;
+
+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.ConfigurationException;
+import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
+import org.keycloak.saml.processing.core.saml.v2.holders.IDPInfoHolder;
+import org.keycloak.saml.processing.core.saml.v2.holders.IssuerInfoHolder;
+import org.keycloak.saml.processing.core.saml.v2.holders.SPInfoHolder;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+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.StatementAbstractType;
+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.saml.v2.protocol.ResponseType;
+import org.keycloak.dom.saml.v2.protocol.ResponseType.RTChoiceType;
+import org.keycloak.dom.saml.v2.protocol.StatusCodeType;
+import org.keycloak.dom.saml.v2.protocol.StatusType;
+import org.w3c.dom.Element;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.net.URI;
+import java.util.List;
+
+/**
+ * Factory for the SAML v2 Authn Response
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 9, 2008
+ */
+public class JBossSAMLAuthnResponseFactory {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * Create a StatusType given the status code uri
+ *
+ * @param statusCodeURI
+ *
+ * @return
+ */
+ public static StatusType createStatusType(String statusCodeURI) {
+ StatusCodeType sct = new StatusCodeType();
+ sct.setValue(URI.create(statusCodeURI));
+
+ StatusType statusType = new StatusType();
+ statusType.setStatusCode(sct);
+ return statusType;
+ }
+
+ /**
+ * <p>Create a <code>StatusType</code> with a top-level <code>org.picketlink.common.constants.JBossSAMLURIConstants.STATUS_RESPONDER</code>
+ * and a second-level code reflecting the given <code>statusCodeURI</code>.</p>
+ *
+ * @param statusCodeURI The second-level code.
+ *
+ * @return
+ */
+ public static StatusType createStatusTypeForResponder(String statusCodeURI) {
+ StatusCodeType topLevelCode = new StatusCodeType();
+
+ topLevelCode.setValue(URI.create(JBossSAMLURIConstants.STATUS_RESPONDER.get()));
+
+ StatusCodeType secondLevelCode = new StatusCodeType();
+
+ secondLevelCode.setValue(URI.create(statusCodeURI));
+
+ topLevelCode.setStatusCode(secondLevelCode);
+
+ StatusType statusType = new StatusType();
+
+ statusType.setStatusCode(topLevelCode);
+
+ return statusType;
+ }
+
+ /**
+ * Create a ResponseType
+ *
+ * @param ID id of the response
+ * @param sp holder with the information about the Service Provider
+ * @param idp holder with the information on the Identity Provider
+ * @param issuerInfo holder with information on the issuer
+ *
+ * @return
+ *
+ * @throws ConfigurationException
+ */
+ public static ResponseType createResponseType(String ID, SPInfoHolder sp, IDPInfoHolder idp, IssuerInfoHolder issuerInfo)
+ throws ConfigurationException {
+ String responseDestinationURI = sp.getResponseDestinationURI();
+
+ XMLGregorianCalendar issueInstant = XMLTimeUtil.getIssueInstant();
+
+ // Create an assertion
+ String id = IDGenerator.create("ID_");
+
+ // Create assertion -> subject
+ SubjectType subjectType = new SubjectType();
+
+ // subject -> nameid
+ NameIDType nameIDType = new NameIDType();
+ nameIDType.setFormat(URI.create(idp.getNameIDFormat()));
+ nameIDType.setValue(idp.getNameIDFormatValue());
+
+ SubjectType.STSubType subType = new SubjectType.STSubType();
+ subType.addBaseID(nameIDType);
+ subjectType.setSubType(subType);
+
+ SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType();
+ subjectConfirmation.setMethod(idp.getSubjectConfirmationMethod());
+
+ SubjectConfirmationDataType subjectConfirmationData = new SubjectConfirmationDataType();
+ subjectConfirmationData.setInResponseTo(sp.getRequestID());
+ subjectConfirmationData.setRecipient(responseDestinationURI);
+ //subjectConfirmationData.setNotBefore(issueInstant);
+ subjectConfirmationData.setNotOnOrAfter(issueInstant);
+
+ subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData);
+
+ subjectType.addConfirmation(subjectConfirmation);
+
+ AssertionType assertionType = SAMLAssertionFactory.createAssertion(id, nameIDType, issueInstant, (ConditionsType) null,
+ subjectType, (List<StatementAbstractType>) null);
+
+ ResponseType responseType = createResponseType(ID, issuerInfo, assertionType);
+ // InResponseTo ID
+ responseType.setInResponseTo(sp.getRequestID());
+ // Destination
+ responseType.setDestination(responseDestinationURI);
+
+ return responseType;
+ }
+
+ /**
+ * Create a Response Type
+ *
+ * @param ID
+ * @param issuerInfo
+ * @param assertionType
+ *
+ * @return
+ *
+ * @throws ConfigurationException
+ */
+ public static ResponseType createResponseType(String ID, IssuerInfoHolder issuerInfo, AssertionType assertionType)
+ throws ConfigurationException {
+ XMLGregorianCalendar issueInstant = XMLTimeUtil.getIssueInstant();
+ ResponseType responseType = new ResponseType(ID, issueInstant);
+
+ // Issuer
+ NameIDType issuer = issuerInfo.getIssuer();
+ responseType.setIssuer(issuer);
+
+ // Status
+ String statusCode = issuerInfo.getStatusCode();
+ if (statusCode == null)
+ throw logger.issuerInfoMissingStatusCodeError();
+
+ responseType.setStatus(createStatusType(statusCode));
+
+ responseType.addAssertion(new RTChoiceType(assertionType));
+ return responseType;
+ }
+
+ /**
+ * Create a Response Type
+ *
+ * @param ID
+ * @param issuerInfo
+ * @param encryptedAssertion a DOM {@link Element} that represents an encrypted assertion
+ *
+ * @return
+ *
+ * @throws ConfigurationException
+ */
+ public static ResponseType createResponseType(String ID, IssuerInfoHolder issuerInfo, Element encryptedAssertion)
+ throws ConfigurationException {
+ ResponseType responseType = new ResponseType(ID, XMLTimeUtil.getIssueInstant());
+
+ // Issuer
+ NameIDType issuer = issuerInfo.getIssuer();
+ responseType.setIssuer(issuer);
+
+ // Status
+ String statusCode = issuerInfo.getStatusCode();
+ if (statusCode == null)
+ throw logger.issuerInfoMissingStatusCodeError();
+
+ responseType.setStatus(createStatusType(statusCode));
+
+ responseType.addAssertion(new RTChoiceType(new EncryptedAssertionType(encryptedAssertion)));
+ return responseType;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java
new file mode 100755
index 0000000..3201b8a
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SAMLAssertionFactory.java
@@ -0,0 +1,197 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.factories;
+
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType;
+import org.keycloak.dom.saml.v2.assertion.ConditionAbstractType;
+import org.keycloak.dom.saml.v2.assertion.ConditionsType;
+import org.keycloak.dom.saml.v2.assertion.KeyInfoConfirmationDataType;
+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.xmlsec.w3.xmldsig.KeyInfoType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.net.URI;
+import java.util.List;
+
+/**
+ * Deal with {@code AssertionType}
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jan 28, 2009
+ */
+public class SAMLAssertionFactory {
+
+ /**
+ * <p>
+ * Creates an {@code AudienceRestrictionType} with the specified values.
+ * </p>
+ *
+ * @param values a {@code String[]} containing the restriction values.
+ *
+ * @return the constructed {@code AudienceRestrictionType} instance.
+ */
+ public static AudienceRestrictionType createAudienceRestriction(String... values) {
+ AudienceRestrictionType audienceRestriction = new AudienceRestrictionType();
+ if (values != null) {
+ for (String val : values) {
+ audienceRestriction.addAudience(URI.create(val));
+ }
+ }
+ return audienceRestriction;
+ }
+
+ /**
+ * <p>
+ * Creates a {@code NameIDType} instance with the specified values.
+ * </p>
+ *
+ * @param format a {@code String} representing the name format.
+ * @param qualifier a {@code String} representing the name qualifier.
+ * @param value a {@code String} representing the name value.
+ *
+ * @return the constructed {@code NameIDType} instance.
+ */
+ public static NameIDType createNameID(String format, String qualifier, String value) {
+ NameIDType nameID = new NameIDType();
+ if (format != null)
+ nameID.setFormat(URI.create(format));
+ nameID.setNameQualifier(qualifier);
+ nameID.setValue(value);
+ return nameID;
+ }
+
+ /**
+ * <p>
+ * Creates a {@code Conditions} instance with the specified values.
+ * </p>
+ *
+ * @param notBefore a {@code XMLGregorianCalendar} representing the start of the token lifetime period.
+ * @param notOnOrAfter a {@code XMLGregorianCalendar} representing the end of the token lifetime period.
+ * @param restrictions an array containing the applicable restrictions.
+ *
+ * @return the constructed {@code Conditions} instance.
+ */
+ public static ConditionsType createConditions(XMLGregorianCalendar notBefore, XMLGregorianCalendar notOnOrAfter,
+ ConditionAbstractType... restrictions) {
+ ConditionsType conditions = new ConditionsType();
+ conditions.setNotBefore(notBefore);
+ conditions.setNotOnOrAfter(notOnOrAfter);
+ if (restrictions != null) {
+ for (ConditionAbstractType condition : restrictions) {
+ conditions.addCondition(condition);
+ }
+
+ }
+ return conditions;
+ }
+
+ /**
+ * <p>
+ * Creates a {@code KeyInfoConfirmationDataType} with the specified {@code KeyInfoType}.
+ * </p>
+ *
+ * @param keyInfo the {@code KeyInfoType} object that wraps the proof-of-possession token.
+ *
+ * @return the constructed {@code KeyInfoConfirmationDataType} instance.
+ */
+ public static KeyInfoConfirmationDataType createKeyInfoConfirmation(KeyInfoType keyInfo) {
+ KeyInfoConfirmationDataType type = new KeyInfoConfirmationDataType();
+ type.setAnyType(keyInfo);
+ return type;
+ }
+
+ /**
+ * <p>
+ * Creates a {@code SubjectConfirmationType} object with the specified values.
+ * </p>
+ *
+ * @param nameID the identifier of the confirmation.
+ * @param confirmationMethod a {@code String} representing the confirmation method.
+ * @param keyInfoData the {@code KeyInfoConfirmationDataType} instance that contains the proof of possession key.
+ *
+ * @return the constructed {@code SubjectConfirmationType} instance.
+ */
+ public static SubjectConfirmationType createSubjectConfirmation(NameIDType nameID, String confirmationMethod,
+ KeyInfoConfirmationDataType keyInfoData) {
+ SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType();
+ subjectConfirmation.setNameID(nameID);
+ subjectConfirmation.setMethod(confirmationMethod);
+ subjectConfirmation.setSubjectConfirmationData(keyInfoData);
+ return subjectConfirmation;
+ }
+
+ /**
+ * <p>
+ * Creates a {@code SubjectType} object with the specified values.
+ * </p>
+ *
+ * @param nameID the identifier of the subject.
+ * @param confirmation the {@code SubjectConfirmationType} that is used to establish the correspondence between the
+ * subject
+ * and claims of SAML statements.
+ *
+ * @return the constructed {@code SubjectType} instance.
+ */
+ public static SubjectType createSubject(NameIDType nameID, SubjectConfirmationType confirmation) {
+ SubjectType subject = new SubjectType();
+ if (nameID != null) {
+ SubjectType.STSubType subType = new SubjectType.STSubType();
+ subType.addConfirmation(confirmation);
+ subType.addBaseID(nameID);
+ subject.setSubType(subType);
+ }
+ return subject;
+ }
+
+ /**
+ * <p>
+ * Creates a SAMLV2 {@code AssertionType} with the specified values.
+ * </p>
+ *
+ * @param id a {@code String} representing the assertion ID.
+ * @param issuerID a {@code NameIDType} that identifies the assertion issuer.
+ * @param issueInstant the assertion time of creation.
+ * @param conditions the {@code ConditionsType} that specify the conditions under which the assertion is to be
+ * considered
+ * valid
+ * @param subject the {@code SubjectType} that identifies the authenticated principal.
+ * @param statements a list of statements associated with the authenticated principal.
+ *
+ * @return
+ */
+ public static AssertionType createAssertion(String id, NameIDType issuerID, XMLGregorianCalendar issueInstant,
+ ConditionsType conditions, SubjectType subject, List<StatementAbstractType> statements) {
+ AssertionType assertion = new AssertionType(id, issueInstant);
+ assertion.setIssuer(issuerID);
+ if (conditions != null)
+ assertion.setConditions(conditions);
+ if (subject != null)
+ assertion.setSubject(subject);
+
+ if (statements != null) {
+ for (StatementAbstractType statement : statements) {
+ assertion.addStatement(statement);
+ }
+ }
+ return assertion;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SecurityActions.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SecurityActions.java
new file mode 100755
index 0000000..5835c75
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/factories/SecurityActions.java
@@ -0,0 +1,126 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.factories;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 9, 2008
+ */
+class SecurityActions {
+
+ /**
+ * <p>
+ * Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
+ * the
+ * specified {@link Class}, if not found it will try to load from using TCL.
+ * </p>
+ *
+ * @param theClass
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ });
+ } else {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ }
+
+ /**
+ * <p>
+ * Loads a class from the specified {@link ClassLoader} using the <code>fullQualifiedName</code> supplied.
+ * </p>
+ *
+ * @param classLoader
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ });
+ } else {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ }
+
+ /**
+ * <p>Returns a system property value using the specified <code>key</code>. If not found the
+ * <code>defaultValue</code> will be returned.</p>
+ *
+ * @param key
+ * @param defaultValue
+ *
+ * @return
+ */
+ static String getSystemProperty(final String key, final String defaultValue) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(key, defaultValue);
+ }
+ });
+ } else {
+ return System.getProperty(key, defaultValue);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/DestinationInfoHolder.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/DestinationInfoHolder.java
new file mode 100755
index 0000000..9bc56de
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/DestinationInfoHolder.java
@@ -0,0 +1,56 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.holders;
+
+/**
+ * Holder containing the information about a destination
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jul 24, 2009
+ */
+public class DestinationInfoHolder {
+
+ private String destination;
+ private String samlMessage;
+ private String relayState;
+
+ /**
+ * Create an holder
+ *
+ * @param destination The destination where the post will be sent
+ * @param samlMessage SAML Message
+ * @param relayState
+ */
+ public DestinationInfoHolder(String destination, String samlMessage, String relayState) {
+ this.destination = destination;
+ this.samlMessage = samlMessage;
+ this.relayState = relayState;
+ }
+
+ public String getDestination() {
+ return destination;
+ }
+
+ public String getSamlMessage() {
+ return samlMessage;
+ }
+
+ public String getRelayState() {
+ return relayState;
+ }
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/IDPInfoHolder.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/IDPInfoHolder.java
new file mode 100755
index 0000000..89d3d1c
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/IDPInfoHolder.java
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.holders;
+
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+
+/**
+ * Holds essential information about an IDP for creating saml messages.
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 10, 2008
+ */
+public class IDPInfoHolder {
+
+ private String subjectConfirmationMethod = JBossSAMLURIConstants.SUBJECT_CONFIRMATION_BEARER.get();
+ private String nameIDFormat = JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get();
+ private String nameIDFormatValue;
+
+ private AssertionType assertion;
+
+ private int assertionValidityDuration = 5; // 5 Minutes
+
+ public int getAssertionValidityDuration() {
+ return assertionValidityDuration;
+ }
+
+ public void setAssertionValidityDuration(int assertionValidityDuration) {
+ this.assertionValidityDuration = assertionValidityDuration;
+ }
+
+ public String getSubjectConfirmationMethod() {
+ return subjectConfirmationMethod;
+ }
+
+ public void setSubjectConfirmationMethod(String subjectConfirmationMethod) {
+ this.subjectConfirmationMethod = subjectConfirmationMethod;
+ }
+
+ public String getNameIDFormat() {
+ return nameIDFormat;
+ }
+
+ public void setNameIDFormat(String nameIDFormat) {
+ this.nameIDFormat = nameIDFormat;
+ }
+
+ public String getNameIDFormatValue() {
+ return nameIDFormatValue;
+ }
+
+ public void setNameIDFormatValue(String nameIDFormatValue) {
+ this.nameIDFormatValue = nameIDFormatValue;
+ }
+
+ public AssertionType getAssertion() {
+ return assertion;
+ }
+
+ public void setAssertion(AssertionType assertion) {
+ this.assertion = assertion;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/IssuerInfoHolder.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/IssuerInfoHolder.java
new file mode 100755
index 0000000..ccb5794
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/IssuerInfoHolder.java
@@ -0,0 +1,80 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.holders;
+
+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.dom.saml.v2.assertion.NameIDType;
+
+/**
+ * Holds info about the issuer for saml messages creation
+ *
+ * @param <JBossSAMLConstants>
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 10, 2008
+ */
+public class IssuerInfoHolder {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ private NameIDType issuer;
+
+ private String statusCodeURI = JBossSAMLURIConstants.STATUS_SUCCESS.get();
+
+ private String samlVersion = JBossSAMLConstants.VERSION_2_0.get();
+
+ public IssuerInfoHolder(NameIDType issuer) {
+ if (issuer == null)
+ throw logger.nullArgumentError("issuer");
+ this.issuer = issuer;
+ }
+
+ public IssuerInfoHolder(String issuerAsString) {
+ if (issuerAsString == null)
+ throw logger.nullArgumentError("issuerAsString");
+ issuer = new NameIDType();
+ issuer.setValue(issuerAsString);
+ }
+
+ public NameIDType getIssuer() {
+ return issuer;
+ }
+
+ public void setIssuer(NameIDType issuer) {
+ this.issuer = issuer;
+ }
+
+ public String getStatusCode() {
+ return statusCodeURI;
+ }
+
+ public void setStatusCode(String statusCode) {
+ this.statusCodeURI = statusCode;
+ }
+
+ public String getSamlVersion() {
+ return samlVersion;
+ }
+
+ public void setSamlVersion(String samlVersion) {
+ this.samlVersion = samlVersion;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/SignatureInfoHolder.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/SignatureInfoHolder.java
new file mode 100755
index 0000000..545d2a5
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/SignatureInfoHolder.java
@@ -0,0 +1,45 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.holders;
+
+/**
+ * Holds information about signature
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jul 24, 2009
+ */
+public class SignatureInfoHolder {
+
+ private byte[] signatureValue;
+
+ private String sigAlg;
+
+ public SignatureInfoHolder(byte[] signatureValue, String sigAlg) {
+ super();
+ this.signatureValue = signatureValue;
+ this.sigAlg = sigAlg;
+ }
+
+ public byte[] getSignatureValue() {
+ return signatureValue;
+ }
+
+ public String getSigAlg() {
+ return sigAlg;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/SPInfoHolder.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/SPInfoHolder.java
new file mode 100755
index 0000000..c9ca5c3
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/holders/SPInfoHolder.java
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.holders;
+
+/**
+ * <p>
+ * Holds the information about a Service Provider
+ * </p>
+ * <p>
+ * This holder is useful in generating saml messages
+ * </p>
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 10, 2008
+ */
+public class SPInfoHolder {
+
+ private String requestID;
+ private String responseDestinationURI;
+ private String issuer;
+
+ public String getRequestID() {
+ return requestID;
+ }
+
+ public void setRequestID(String requestID) {
+ this.requestID = requestID;
+ }
+
+ public String getResponseDestinationURI() {
+ return responseDestinationURI;
+ }
+
+ public void setResponseDestinationURI(String responseDestinationURI) {
+ this.responseDestinationURI = responseDestinationURI;
+ }
+
+ public String getIssuer() {
+ return issuer;
+ }
+
+ public void setIssuer(String issuer) {
+ this.issuer = issuer;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/DocumentUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/DocumentUtil.java
new file mode 100755
index 0000000..fa1cadc
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/DocumentUtil.java
@@ -0,0 +1,28 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.util;
+
+/**
+ * PLINK-158: Maintain backward compatibility
+ *
+ * @author Anil Saldhana
+ * @since June 20, 2013
+ */
+public class DocumentUtil extends org.keycloak.saml.common.util.DocumentUtil {
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java
new file mode 100755
index 0000000..bca7eb0
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SAMLMetadataUtil.java
@@ -0,0 +1,101 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.util;
+
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
+import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.KeyTypes;
+import org.keycloak.dom.saml.v2.metadata.SSODescriptorType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * Deals with SAML2 Metadata
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jan 31, 2011
+ */
+public class SAMLMetadataUtil {
+
+ /**
+ * Get the {@link X509Certificate} from the KeyInfo
+ *
+ * @param keyDescriptor
+ *
+ * @return
+ *
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ * @throws org.keycloak.saml.common.exceptions.ConfigurationException
+ */
+ public static X509Certificate getCertificate(KeyDescriptorType keyDescriptor) throws ConfigurationException,
+ ProcessingException {
+ X509Certificate cert = null;
+ Element keyInfo = keyDescriptor.getKeyInfo();
+ if (keyInfo != null) {
+ NodeList x509DataNodes = keyInfo.getElementsByTagName("X509Data");
+ if (x509DataNodes == null || x509DataNodes.getLength() == 0) {
+ x509DataNodes = keyInfo.getElementsByTagNameNS(JBossSAMLURIConstants.XMLDSIG_NSURI.get(), "X509Data");
+ }
+
+ if (x509DataNodes == null || x509DataNodes.getLength() == 0) {
+ x509DataNodes = keyInfo.getElementsByTagName("ds:X509Data");
+ }
+
+ if (x509DataNodes != null && x509DataNodes.getLength() > 0) {
+ // Choose the first one
+ Node x509DataNode = x509DataNodes.item(0);
+ NodeList children = x509DataNode.getChildNodes();
+ int len = children != null ? children.getLength() : 0;
+ for (int i = 0; i < len; i++) {
+ Node nl = children.item(i);
+ if (nl.getNodeName().contains("X509Certificate")) {
+ Node certNode = nl.getFirstChild();
+ String certNodeValue = certNode.getNodeValue();
+ cert = XMLSignatureUtil.getX509CertificateFromKeyInfoString(certNodeValue.replaceAll("\\s", ""));
+ break;
+ }
+ }
+ }
+ }
+ return cert;
+ }
+
+ public static X509Certificate getCertificate(KeyTypes use, SSODescriptorType ssoDescriptorType) {
+ if (ssoDescriptorType != null) {
+ for (KeyDescriptorType keyDescriptorType : ssoDescriptorType.getKeyDescriptor()) {
+ KeyTypes keyUse = keyDescriptorType.getUse();
+
+ if (keyUse == null || (use != null && keyUse.value().equals(use.value()))) {
+ try {
+ return getCertificate(keyDescriptorType);
+ } catch (Exception e) {
+ throw new RuntimeException("Could not parse KeyDescriptor X509 certificate from metadata [" + ssoDescriptorType.getID() + "].");
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SecurityActions.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SecurityActions.java
new file mode 100755
index 0000000..1a9c090
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SecurityActions.java
@@ -0,0 +1,161 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.util;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 9, 2008
+ */
+class SecurityActions {
+
+ /**
+ * <p>
+ * Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
+ * the
+ * specified {@link Class}, if not found it will try to load from using TCL.
+ * </p>
+ *
+ * @param theClass
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ });
+ } else {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ }
+
+ /**
+ * <p>
+ * Loads a class from the specified {@link ClassLoader} using the <code>fullQualifiedName</code> supplied.
+ * </p>
+ *
+ * @param classLoader
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ });
+ } else {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ }
+
+ /**
+ * <p>Returns a system property value using the specified <code>key</code>. If not found the
+ * <code>defaultValue</code> will be returned.</p>
+ *
+ * @param key
+ * @param defaultValue
+ *
+ * @return
+ */
+ static String getSystemProperty(final String key, final String defaultValue) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(key, defaultValue);
+ }
+ });
+ } else {
+ return System.getProperty(key, defaultValue);
+ }
+ }
+
+ /**
+ * Get the Thread Context ClassLoader
+ *
+ * @return
+ */
+ static ClassLoader getTCCL() {
+ if (System.getSecurityManager() != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ } else {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ }
+
+ /**
+ * Set the Thread Context ClassLoader
+ *
+ * @param paramCl
+ */
+ static void setTCCL(final ClassLoader paramCl) {
+ if (System.getSecurityManager() != null) {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ Thread.currentThread().setContextClassLoader(paramCl);
+ return null;
+ }
+ });
+ } else {
+
+ Thread.currentThread().setContextClassLoader(paramCl);
+ }
+ }
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SignatureUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SignatureUtil.java
new file mode 100755
index 0000000..1c52241
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/SignatureUtil.java
@@ -0,0 +1,297 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.util;
+
+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.WSTrustConstants;
+import org.keycloak.saml.common.exceptions.ParsingException;
+import org.keycloak.saml.common.util.Base64;
+import org.keycloak.saml.processing.core.constants.PicketLinkFederationConstants;
+import org.keycloak.dom.xmlsec.w3.xmldsig.DSAKeyValueType;
+import org.keycloak.dom.xmlsec.w3.xmldsig.KeyValueType;
+import org.keycloak.dom.xmlsec.w3.xmldsig.RSAKeyValueType;
+import org.keycloak.dom.xmlsec.w3.xmldsig.SignatureType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.bind.JAXBException;
+import java.io.OutputStream;
+import java.security.GeneralSecurityException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.RSAPublicKey;
+
+/**
+ * Signature utility for signing content
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 16, 2008
+ */
+public class SignatureUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * Marshall a SignatureType to output stream
+ *
+ * @param signature
+ * @param os
+ *
+ * @throws SAXException
+ * @throws JAXBException
+ */
+ public static void marshall(SignatureType signature, OutputStream os) throws JAXBException, SAXException {
+ throw logger.notImplementedYet("NYI");
+ /*
+ * JAXBElement<SignatureType> jsig = objectFactory.createSignature(signature); Marshaller marshaller =
+ * JAXBUtil.getValidatingMarshaller(pkgName, schemaLocation); marshaller.marshal(jsig, os);
+ */
+ }
+
+ /**
+ * Get the XML Signature URI for the algo (RSA, DSA)
+ *
+ * @param algo
+ *
+ * @return
+ */
+ public static String getXMLSignatureAlgorithmURI(String algo) {
+ String xmlSignatureAlgo = null;
+
+ if ("DSA".equalsIgnoreCase(algo)) {
+ xmlSignatureAlgo = JBossSAMLConstants.SIGNATURE_SHA1_WITH_DSA.get();
+ } else if ("RSA".equalsIgnoreCase(algo)) {
+ xmlSignatureAlgo = JBossSAMLConstants.SIGNATURE_SHA1_WITH_RSA.get();
+ }
+ return xmlSignatureAlgo;
+ }
+
+ /**
+ * Sign a string using the private key
+ *
+ * @param stringToBeSigned
+ * @param signingKey
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ */
+ public static byte[] sign(String stringToBeSigned, PrivateKey signingKey) throws GeneralSecurityException {
+ if (stringToBeSigned == null)
+ throw logger.nullArgumentError("stringToBeSigned");
+ if (signingKey == null)
+ throw logger.nullArgumentError("signingKey");
+
+ String algo = signingKey.getAlgorithm();
+ Signature sig = getSignature(algo);
+ sig.initSign(signingKey);
+ sig.update(stringToBeSigned.getBytes());
+ return sig.sign();
+ }
+
+ /**
+ * Validate the signed content with the signature value
+ *
+ * @param signedContent
+ * @param signatureValue
+ * @param validatingKey
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ */
+ public static boolean validate(byte[] signedContent, byte[] signatureValue, PublicKey validatingKey)
+ throws GeneralSecurityException {
+ if (signedContent == null)
+ throw logger.nullArgumentError("signedContent");
+ if (signatureValue == null)
+ throw logger.nullArgumentError("signatureValue");
+ if (validatingKey == null)
+ throw logger.nullArgumentError("validatingKey");
+
+ // We assume that the sigatureValue has the same algorithm as the public key
+ // If not, there will be an exception anyway
+ String algo = validatingKey.getAlgorithm();
+ Signature sig = getSignature(algo);
+
+ sig.initVerify(validatingKey);
+ sig.update(signedContent);
+ return sig.verify(signatureValue);
+ }
+
+ /**
+ * Validate the signature using a x509 certificate
+ *
+ * @param signedContent
+ * @param signatureValue
+ * @param signatureAlgorithm
+ * @param validatingCert
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ */
+ public static boolean validate(byte[] signedContent, byte[] signatureValue, String signatureAlgorithm,
+ X509Certificate validatingCert) throws GeneralSecurityException {
+ if (signedContent == null)
+ throw logger.nullArgumentError("signedContent");
+ if (signatureValue == null)
+ throw logger.nullArgumentError("signatureValue");
+ if (signatureAlgorithm == null)
+ throw logger.nullArgumentError("signatureAlgorithm");
+ if (validatingCert == null)
+ throw logger.nullArgumentError("validatingCert");
+
+ Signature sig = getSignature(signatureAlgorithm);
+
+ sig.initVerify(validatingCert);
+ sig.update(signedContent);
+ 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();
+
+ 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();
+
+ if (WSTrustConstants.XMLDSig.MODULUS.equals(tag)) {
+ rsa.setModulus(text);
+ } else if (WSTrustConstants.XMLDSig.EXPONENT.equals(tag)) {
+ rsa.setExponent(text);
+ }
+ }
+ }
+
+ return rsa;
+ }
+
+ /**
+ * <p>
+ * Creates a {@code KeyValueType} that wraps the specified public key. This method supports DSA and RSA keys.
+ * </p>
+ *
+ * @param key the {@code PublicKey} that will be represented as a {@code KeyValueType}.
+ *
+ * @return the constructed {@code KeyValueType} or {@code null} if the specified key is neither a DSA nor a RSA
+ * key.
+ */
+ public static KeyValueType createKeyValue(PublicKey key) {
+ if (key instanceof RSAPublicKey) {
+ RSAPublicKey pubKey = (RSAPublicKey) key;
+ byte[] modulus = pubKey.getModulus().toByteArray();
+ byte[] exponent = pubKey.getPublicExponent().toByteArray();
+
+ RSAKeyValueType rsaKeyValue = new RSAKeyValueType();
+ rsaKeyValue.setModulus(Base64.encodeBytes(modulus).getBytes());
+ rsaKeyValue.setExponent(Base64.encodeBytes(exponent).getBytes());
+ return rsaKeyValue;
+ } else if (key instanceof DSAPublicKey) {
+ DSAPublicKey pubKey = (DSAPublicKey) key;
+ byte[] P = pubKey.getParams().getP().toByteArray();
+ byte[] Q = pubKey.getParams().getQ().toByteArray();
+ byte[] G = pubKey.getParams().getG().toByteArray();
+ byte[] Y = pubKey.getY().toByteArray();
+
+ DSAKeyValueType dsaKeyValue = new DSAKeyValueType();
+ dsaKeyValue.setP(Base64.encodeBytes(P).getBytes());
+ dsaKeyValue.setQ(Base64.encodeBytes(Q).getBytes());
+ dsaKeyValue.setG(Base64.encodeBytes(G).getBytes());
+ dsaKeyValue.setY(Base64.encodeBytes(Y).getBytes());
+ return dsaKeyValue;
+ }
+ throw logger.unsupportedType(key.toString());
+ }
+
+ private static Signature getSignature(String algo) throws GeneralSecurityException {
+ Signature sig = null;
+
+ if ("DSA".equalsIgnoreCase(algo)) {
+ sig = Signature.getInstance(PicketLinkFederationConstants.DSA_SIGNATURE_ALGORITHM);
+ } else if ("RSA".equalsIgnoreCase(algo)) {
+ sig = Signature.getInstance(PicketLinkFederationConstants.RSA_SIGNATURE_ALGORITHM);
+ } else
+ throw logger.signatureUnknownAlgo(algo);
+ return sig;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StatementUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StatementUtil.java
new file mode 100755
index 0000000..c184e58
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StatementUtil.java
@@ -0,0 +1,241 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.saml.processing.core.saml.v2.util;
+
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
+import org.keycloak.saml.common.util.StringUtil;
+import org.keycloak.saml.processing.core.constants.AttributeConstants;
+import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
+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.AuthnContextType;
+import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
+import org.keycloak.dom.saml.v2.assertion.StatementAbstractType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Deals with SAML2 Statements
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Aug 31, 2009
+ */
+public class StatementUtil {
+
+ public static final QName X500_QNAME = new QName(JBossSAMLURIConstants.X500_NSURI.get(), "Encoding",
+ JBossSAMLURIConstants.X500_PREFIX.get());
+
+ /**
+ * Create an AuthnStatementType given the issue instant and the type of authentication
+ *
+ * @param instant an instanceof {@link XMLGregorianCalendar}
+ * @param authnContextClassRefValue indicate the type of authentication performed
+ *
+ * @return {@link AuthnStatementType}
+ */
+ public static AuthnStatementType createAuthnStatement(XMLGregorianCalendar instant, String authnContextClassRefValue) {
+ AuthnStatementType authnStatement = new AuthnStatementType(instant);
+
+ AuthnContextType authnContext = new AuthnContextType();
+ AuthnContextClassRefType authnContextClassRef = new AuthnContextClassRefType(URI.create(authnContextClassRefValue));
+
+ AuthnContextType.AuthnContextTypeSequence sequence = (authnContext).new AuthnContextTypeSequence();
+ sequence.setClassRef(authnContextClassRef);
+ authnContext.setSequence(sequence);
+
+ authnStatement.setAuthnContext(authnContext);
+
+ return authnStatement;
+ }
+
+ /**
+ * Create an attribute statement with all the attributes
+ *
+ * @param attributes a map with keys from {@link AttributeConstants}
+ *
+ * @return
+ */
+ public static AttributeStatementType createAttributeStatement(Map<String, Object> attributes) {
+ AttributeStatementType attrStatement = null;
+
+ int i = 0;
+
+ Set<String> keys = attributes.keySet();
+ for (String key : keys) {
+ if (i == 0) {
+ // Deal with the X500 Profile of SAML2
+ attrStatement = new AttributeStatementType();
+ i++;
+ }
+
+ // if the attribute contains roles, add each role as an attribute.
+ if (AttributeConstants.ROLES.equalsIgnoreCase(key)) {
+ Object value = attributes.get(key);
+ if (value instanceof Collection<?>) {
+ Collection<?> roles = (Collection<?>) value;
+ attrStatement = createAttributeStatement(new ArrayList(roles));
+ }
+ } else {
+ AttributeType att;
+ Object value = attributes.get(key);
+
+ String uri = X500SAMLProfileConstants.getOID(key);
+ if (StringUtil.isNotNull(uri)) {
+ att = getX500Attribute(uri);
+ att.setFriendlyName(key);
+ } else {
+ att = new AttributeType(key);
+ att.setFriendlyName(key);
+ att.setNameFormat(JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get());
+ }
+
+ if (Collection.class.isInstance(value)) {
+ Collection collection = (Collection) value;
+ Iterator iterator = collection.iterator();
+
+ while (iterator.hasNext()) {
+ att.addAttributeValue(iterator.next());
+ }
+ } else if (String.class.isInstance(value)) {
+ att.addAttributeValue(value);
+ } else {
+ throw new RuntimeException("Unsupported attribute value [" + value + "]. Values must be a string, even if using a Collection.");
+ }
+
+ attrStatement.addAttribute(new ASTChoiceType(att));
+ }
+ }
+ return attrStatement;
+ }
+
+ /**
+ * Given a set of roles, create an attribute statement
+ *
+ * @param roles
+ *
+ * @return
+ */
+ public static AttributeStatementType createAttributeStatement(List<String> roles) {
+ AttributeStatementType attrStatement = null;
+ for (String role : roles) {
+ if (attrStatement == null) {
+ attrStatement = new AttributeStatementType();
+ }
+ AttributeType attr = new AttributeType(AttributeConstants.ROLE_IDENTIFIER_ASSERTION);
+ attr.addAttributeValue(role);
+ attrStatement.addAttribute(new ASTChoiceType(attr));
+ }
+ return attrStatement;
+ }
+
+ /**
+ * Given a set of roles, create an attribute statement
+ *
+ * @param roles
+ * @param multivalued if you want the attribute to be multi valued
+ *
+ * @return
+ */
+ public static AttributeStatementType createAttributeStatementForRoles(List<String> roles, boolean multivalued) {
+ if (multivalued == false) {
+ return createAttributeStatement(roles);
+ }
+ AttributeStatementType attrStatement = new AttributeStatementType();
+ AttributeType attr = new AttributeType(AttributeConstants.ROLE_IDENTIFIER_ASSERTION);
+ for (String role : roles) {
+ attr.addAttributeValue(role);
+ }
+ attrStatement.addAttribute(new ASTChoiceType(attr));
+ return attrStatement;
+ }
+
+ /**
+ * Given an attribute type and a value, create {@link AttributeStatementType}
+ *
+ * @param key attribute type
+ * @param value attribute value
+ *
+ * @return
+ */
+ public static AttributeStatementType createAttributeStatement(String key, String value) {
+ AttributeStatementType attrStatement = new AttributeStatementType();
+ AttributeType attr = new AttributeType(key);
+ attr.addAttributeValue(value);
+ attrStatement.addAttribute(new ASTChoiceType(attr));
+
+ return attrStatement;
+ }
+
+ public static Map<String, Object> asMap(Set<AttributeStatementType> attributeStatementTypes) {
+ Map<String, Object> attrMap = new HashMap<String, Object>();
+
+ if (attributeStatementTypes != null && !attributeStatementTypes.isEmpty()) {
+ attrMap = new HashMap<String, Object>();
+
+ for (StatementAbstractType statement : attributeStatementTypes) {
+ if (statement instanceof AttributeStatementType) {
+ AttributeStatementType attrStat = (AttributeStatementType) statement;
+ List<ASTChoiceType> attrs = attrStat.getAttributes();
+ for (ASTChoiceType attrChoice : attrs) {
+ AttributeType attr = attrChoice.getAttribute();
+ String attributeName = attr.getFriendlyName();
+
+ if (attributeName == null) {
+ attributeName = attr.getName();
+ }
+
+ List<Object> values = attr.getAttributeValue();
+
+ if (values != null) {
+ if (values.size() == 1) {
+ attrMap.put(attributeName, values.get(0));
+ } else {
+ attrMap.put(attributeName, values);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return attrMap;
+ }
+
+ private static AttributeType getX500Attribute(String name) {
+ AttributeType att = new AttributeType(name);
+ att.getOtherAttributes().put(X500_QNAME, "LDAP");
+
+ att.setNameFormat(JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get());
+ return att;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StaxWriterUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StaxWriterUtil.java
new file mode 100755
index 0000000..9da4caf
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StaxWriterUtil.java
@@ -0,0 +1,166 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.util;
+
+
+import org.keycloak.saml.common.ErrorCodes;
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.saml.common.constants.WSTrustConstants;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.StaxUtil;
+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.w3c.dom.Element;
+
+import javax.xml.stream.XMLStreamWriter;
+
+/**
+ * Utility methods for stax writing
+ *
+ * @author anil saldhana
+ * @since Jan 28, 2013
+ */
+public class StaxWriterUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * Write the {@link org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType}
+ *
+ * @param writer
+ * @param keyInfo
+ *
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ */
+ public static void writeKeyInfo(XMLStreamWriter writer, KeyInfoType keyInfo) throws ProcessingException {
+ if (keyInfo.getContent() == null || keyInfo.getContent().size() == 0)
+ throw logger.writerInvalidKeyInfoNullContentError();
+ StaxUtil.writeStartElement(writer, WSTrustConstants.XMLDSig.DSIG_PREFIX, WSTrustConstants.XMLDSig.KEYINFO,
+ WSTrustConstants.XMLDSig.DSIG_NS);
+ StaxUtil.writeNameSpace(writer, WSTrustConstants.XMLDSig.DSIG_PREFIX, WSTrustConstants.XMLDSig.DSIG_NS);
+ // write the keyInfo content.
+ Object content = keyInfo.getContent().get(0);
+ if (content instanceof Element) {
+ Element element = (Element) keyInfo.getContent().get(0);
+ StaxUtil.writeDOMNode(writer, element);
+ } else if (content instanceof X509DataType) {
+ X509DataType type = (X509DataType) content;
+ if (type.getDataObjects().size() == 0)
+ throw logger.writerNullValueError("X509Data");
+ StaxUtil.writeStartElement(writer, WSTrustConstants.XMLDSig.DSIG_PREFIX, WSTrustConstants.XMLDSig.X509DATA,
+ WSTrustConstants.XMLDSig.DSIG_NS);
+ Object obj = type.getDataObjects().get(0);
+ if (obj instanceof Element) {
+ Element element = (Element) obj;
+ StaxUtil.writeDOMElement(writer, element);
+ } else if (obj instanceof X509CertificateType) {
+ X509CertificateType cert = (X509CertificateType) obj;
+ StaxUtil.writeStartElement(writer, WSTrustConstants.XMLDSig.DSIG_PREFIX, WSTrustConstants.XMLDSig.X509CERT,
+ WSTrustConstants.XMLDSig.DSIG_NS);
+ StaxUtil.writeCharacters(writer, new String(cert.getEncodedCertificate()));
+ StaxUtil.writeEndElement(writer);
+ }
+ StaxUtil.writeEndElement(writer);
+ } else if (content instanceof KeyValueType) {
+ KeyValueType keyvalueType = (KeyValueType) content;
+ StaxUtil.writeStartElement(writer, WSTrustConstants.XMLDSig.DSIG_PREFIX, WSTrustConstants.XMLDSig.KEYVALUE,
+ WSTrustConstants.XMLDSig.DSIG_NS);
+ if (keyvalueType instanceof DSAKeyValueType) {
+ writeDSAKeyValueType(writer, (DSAKeyValueType) keyvalueType);
+ }
+ if (keyvalueType instanceof RSAKeyValueType) {
+ writeRSAKeyValueType(writer, (RSAKeyValueType) keyvalueType);
+ }
+ StaxUtil.writeEndElement(writer);
+ } else
+ throw new ProcessingException(ErrorCodes.UNSUPPORTED_TYPE + content);
+
+ StaxUtil.writeEndElement(writer);
+ }
+
+ public static void writeRSAKeyValueType(XMLStreamWriter writer, RSAKeyValueType type) throws ProcessingException {
+ String prefix = WSTrustConstants.XMLDSig.DSIG_PREFIX;
+
+ StaxUtil.writeStartElement(writer, prefix, WSTrustConstants.XMLDSig.RSA_KEYVALUE, WSTrustConstants.DSIG_NS);
+ // write the rsa key modulus.
+ byte[] modulus = type.getModulus();
+ StaxUtil.writeStartElement(writer, prefix, WSTrustConstants.XMLDSig.MODULUS, WSTrustConstants.DSIG_NS);
+ StaxUtil.writeCharacters(writer, new String(modulus));
+ StaxUtil.writeEndElement(writer);
+
+ // write the rsa key exponent.
+ byte[] exponent = type.getExponent();
+ StaxUtil.writeStartElement(writer, prefix, WSTrustConstants.XMLDSig.EXPONENT, WSTrustConstants.DSIG_NS);
+ StaxUtil.writeCharacters(writer, new String(exponent));
+ StaxUtil.writeEndElement(writer);
+
+ StaxUtil.writeEndElement(writer);
+ }
+
+ public static void writeDSAKeyValueType(XMLStreamWriter writer, DSAKeyValueType type) throws ProcessingException {
+
+ String prefix = WSTrustConstants.XMLDSig.DSIG_PREFIX;
+
+ StaxUtil.writeStartElement(writer, prefix, WSTrustConstants.XMLDSig.DSA_KEYVALUE, WSTrustConstants.DSIG_NS);
+
+ byte[] p = type.getP();
+ if (p != null) {
+ StaxUtil.writeStartElement(writer, prefix, WSTrustConstants.XMLDSig.P, WSTrustConstants.DSIG_NS);
+ StaxUtil.writeCharacters(writer, new String(p));
+ StaxUtil.writeEndElement(writer);
+ }
+ byte[] q = type.getQ();
+ if (q != null) {
+ StaxUtil.writeStartElement(writer, prefix, WSTrustConstants.XMLDSig.Q, WSTrustConstants.DSIG_NS);
+ StaxUtil.writeCharacters(writer, new String(q));
+ StaxUtil.writeEndElement(writer);
+ }
+ byte[] g = type.getG();
+ if (g != null) {
+ StaxUtil.writeStartElement(writer, prefix, WSTrustConstants.XMLDSig.G, WSTrustConstants.DSIG_NS);
+ StaxUtil.writeCharacters(writer, new String(g));
+ StaxUtil.writeEndElement(writer);
+ }
+ byte[] y = type.getY();
+ if (y != null) {
+ StaxUtil.writeStartElement(writer, prefix, WSTrustConstants.XMLDSig.Y, WSTrustConstants.DSIG_NS);
+ StaxUtil.writeCharacters(writer, new String(y));
+ StaxUtil.writeEndElement(writer);
+ }
+ byte[] seed = type.getSeed();
+ if (seed != null) {
+ StaxUtil.writeStartElement(writer, prefix, WSTrustConstants.XMLDSig.SEED, WSTrustConstants.DSIG_NS);
+ StaxUtil.writeCharacters(writer, new String(seed));
+ StaxUtil.writeEndElement(writer);
+ }
+ byte[] pgen = type.getPgenCounter();
+ if (pgen != null) {
+ StaxUtil.writeStartElement(writer, prefix, WSTrustConstants.XMLDSig.PGEN_COUNTER, WSTrustConstants.DSIG_NS);
+ StaxUtil.writeCharacters(writer, new String(pgen));
+ StaxUtil.writeEndElement(writer);
+ }
+
+ StaxUtil.writeEndElement(writer);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/XMLTimeUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/XMLTimeUtil.java
new file mode 100755
index 0000000..acb6ceb
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/XMLTimeUtil.java
@@ -0,0 +1,254 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ParsingException;
+import org.keycloak.saml.common.util.SystemPropertiesUtil;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+import javax.xml.datatype.XMLGregorianCalendar;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+/**
+ * Util class dealing with xml based time
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jan 6, 2009
+ */
+public class XMLTimeUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * Add additional time in miliseconds
+ *
+ * @param value calendar whose value needs to be updated
+ * @param milis
+ *
+ * @return calendar value with the addition
+ *
+ * @throws org.keycloak.saml.common.exceptions.ConfigurationException
+ */
+ public static XMLGregorianCalendar add(XMLGregorianCalendar value, long milis) throws ConfigurationException {
+ XMLGregorianCalendar newVal = (XMLGregorianCalendar) value.clone();
+
+ Duration duration;
+ try {
+ duration = newDatatypeFactory().newDuration(milis);
+ } catch (DatatypeConfigurationException e) {
+ throw logger.configurationError(e);
+ }
+ newVal.add(duration);
+ return newVal;
+ }
+
+ /**
+ * Subtract some miliseconds from the time value
+ *
+ * @param value
+ * @param milis miliseconds entered in a positive value
+ *
+ * @return
+ *
+ * @throws ConfigurationException
+ */
+ public static XMLGregorianCalendar subtract(XMLGregorianCalendar value, long milis) throws ConfigurationException {
+ if (milis < 0)
+ throw logger.invalidArgumentError("milis should be a positive value");
+ return add(value, -1 * milis);
+ }
+
+ /**
+ * Returns a XMLGregorianCalendar in the timezone specified. If the timezone is not valid, then the timezone falls
+ * back to
+ * "GMT"
+ *
+ * @param timezone
+ *
+ * @return
+ *
+ * @throws ConfigurationException
+ */
+ public static XMLGregorianCalendar getIssueInstant(String timezone) throws ConfigurationException {
+ TimeZone tz = TimeZone.getTimeZone(timezone);
+ DatatypeFactory dtf;
+ try {
+ dtf = newDatatypeFactory();
+ } catch (DatatypeConfigurationException e) {
+ throw logger.configurationError(e);
+ }
+
+ GregorianCalendar gc = new GregorianCalendar(tz);
+ XMLGregorianCalendar xgc = dtf.newXMLGregorianCalendar(gc);
+
+ return xgc;
+ }
+
+ /**
+ * Get the current instant of time
+ *
+ * @return
+ *
+ * @throws ConfigurationException
+ */
+ public static XMLGregorianCalendar getIssueInstant() throws ConfigurationException {
+ return getIssueInstant(getCurrentTimeZoneID());
+ }
+
+ public static String getCurrentTimeZoneID() {
+ String timezonePropertyValue = SecurityActions.getSystemProperty(GeneralConstants.TIMEZONE, "GMT");
+
+ TimeZone timezone;
+ if (GeneralConstants.TIMEZONE_DEFAULT.equals(timezonePropertyValue)) {
+ timezone = TimeZone.getDefault();
+ } else {
+ timezone = TimeZone.getTimeZone(timezonePropertyValue);
+ }
+
+ return timezone.getID();
+ }
+
+ /**
+ * Convert the minutes into miliseconds
+ *
+ * @param valueInMins
+ *
+ * @return
+ */
+ public static long inMilis(int valueInMins) {
+ return valueInMins * 60 * 1000;
+ }
+
+ /**
+ * Validate that the current time falls between the two boundaries
+ *
+ * @param now
+ * @param notbefore
+ * @param notOnOrAfter
+ *
+ * @return
+ */
+ public static boolean isValid(XMLGregorianCalendar now, XMLGregorianCalendar notbefore, XMLGregorianCalendar notOnOrAfter) {
+ int val = 0;
+
+ if (notbefore != null) {
+ val = notbefore.compare(now);
+
+ if (val == DatatypeConstants.INDETERMINATE || val == DatatypeConstants.GREATER)
+ return false;
+ }
+
+ if (notOnOrAfter != null) {
+ val = notOnOrAfter.compare(now);
+
+ if (val != DatatypeConstants.GREATER)
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Given a string, get the Duration object. The string can be an ISO 8601 period representation (Eg.: P10M) or a
+ * numeric
+ * value. If a ISO 8601 period, the duration will reflect the defined format. If a numeric (Eg.: 1000) the duration
+ * will
+ * be calculated in milliseconds.
+ *
+ * @param timeValue
+ *
+ * @return
+ *
+ * @throws org.keycloak.saml.common.exceptions.ParsingException
+ */
+ public static Duration parseAsDuration(String timeValue) throws ParsingException {
+ if (timeValue == null) {
+ PicketLinkLoggerFactory.getLogger().nullArgumentError("duration time");
+ }
+
+ DatatypeFactory factory = null;
+
+ try {
+ factory = newDatatypeFactory();
+ } catch (DatatypeConfigurationException e) {
+ throw logger.parserError(e);
+ }
+
+ try {
+ // checks if it is a ISO 8601 period. If not it must be a numeric value.
+ if (timeValue.startsWith("P")) {
+ return factory.newDuration(timeValue);
+ } else {
+ return factory.newDuration(Long.valueOf(timeValue));
+ }
+ } catch (Exception e) {
+ throw logger.samlMetaDataFailedToCreateCacheDuration(timeValue);
+ }
+ }
+
+ /**
+ * Given a string representing xml time, parse into {@code XMLGregorianCalendar}
+ *
+ * @param timeString
+ *
+ * @return
+ *
+ * @throws ParsingException
+ */
+ public static XMLGregorianCalendar parse(String timeString) throws ParsingException {
+ DatatypeFactory factory = null;
+ try {
+ factory = newDatatypeFactory();
+ } catch (DatatypeConfigurationException e) {
+ throw logger.parserError(e);
+ }
+ return factory.newXMLGregorianCalendar(timeString);
+ }
+
+
+ /**
+ * Create a new {@link DatatypeFactory}
+ *
+ * @return
+ *
+ * @throws DatatypeConfigurationException
+ */
+ public static DatatypeFactory newDatatypeFactory() throws DatatypeConfigurationException {
+ boolean tccl_jaxp = SystemPropertiesUtil.getSystemProperty(GeneralConstants.TCCL_JAXP, "false")
+ .equalsIgnoreCase("true");
+ ClassLoader prevTCCL = SecurityActions.getTCCL();
+ try {
+ if (tccl_jaxp) {
+ SecurityActions.setTCCL(XMLTimeUtil.class.getClassLoader());
+ }
+ return DatatypeFactory.newInstance();
+ } finally {
+ if (tccl_jaxp) {
+ SecurityActions.setTCCL(prevTCCL);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java
new file mode 100755
index 0000000..a484a19
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java
@@ -0,0 +1,322 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.writers;
+
+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.ProcessingException;
+import org.keycloak.saml.common.util.StaxUtil;
+import org.keycloak.saml.common.util.StringUtil;
+import org.keycloak.saml.processing.core.saml.v2.util.StaxWriterUtil;
+import org.keycloak.dom.saml.v2.assertion.AttributeType;
+import org.keycloak.dom.saml.v2.assertion.BaseIDAbstractType;
+import org.keycloak.dom.saml.v2.assertion.EncryptedElementType;
+import org.keycloak.dom.saml.v2.assertion.KeyInfoConfirmationDataType;
+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.saml.v2.metadata.LocalizedNameType;
+import org.keycloak.dom.xmlsec.w3.xmldsig.KeyInfoType;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamWriter;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ASSERTION_NSURI;
+
+/**
+ * Base Class for the Stax writers for SAML
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Nov 2, 2010
+ */
+public class BaseWriter {
+
+ protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ protected static String PROTOCOL_PREFIX = "samlp";
+
+ protected static String ASSERTION_PREFIX = "saml";
+
+ protected static String XACML_SAML_PREFIX = "xacml-saml";
+
+ protected static String XACML_SAML_PROTO_PREFIX = "xacml-samlp";
+
+ protected static String XSI_PREFIX = "xsi";
+
+ protected XMLStreamWriter writer = null;
+
+ public BaseWriter(XMLStreamWriter writer) {
+ this.writer = writer;
+ }
+
+ /**
+ * Write {@code NameIDType} to stream
+ *
+ * @param nameIDType
+ * @param tag
+ * @param out
+ *
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ */
+ public void write(NameIDType nameIDType, QName tag) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, tag.getPrefix(), tag.getLocalPart(), tag.getNamespaceURI());
+
+ StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, ASSERTION_NSURI.get());
+
+ URI format = nameIDType.getFormat();
+ if (format != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.FORMAT.get(), format.toASCIIString());
+ }
+
+ String spProvidedID = nameIDType.getSPProvidedID();
+ if (StringUtil.isNotNull(spProvidedID)) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.SP_PROVIDED_ID.get(), spProvidedID);
+ }
+
+ String spNameQualifier = nameIDType.getSPNameQualifier();
+ if (StringUtil.isNotNull(spNameQualifier)) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.SP_NAME_QUALIFIER.get(), spNameQualifier);
+ }
+
+ String nameQualifier = nameIDType.getNameQualifier();
+ if (StringUtil.isNotNull(nameQualifier)) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.NAME_QUALIFIER.get(), nameQualifier);
+ }
+
+ String value = nameIDType.getValue();
+ if (StringUtil.isNotNull(value)) {
+ StaxUtil.writeCharacters(writer, value);
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write an {@code AttributeType} to stream
+ *
+ * @param attributeType
+ * @param out
+ *
+ * @throws ProcessingException
+ */
+ public void write(AttributeType attributeType) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.ATTRIBUTE.get(), ASSERTION_NSURI.get());
+
+ writeAttributeTypeWithoutRootTag(attributeType);
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ public void writeAttributeTypeWithoutRootTag(AttributeType attributeType) throws ProcessingException {
+ String attributeName = attributeType.getName();
+ if (attributeName != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.NAME.get(), attributeName);
+ }
+
+ String friendlyName = attributeType.getFriendlyName();
+ if (StringUtil.isNotNull(friendlyName)) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.FRIENDLY_NAME.get(), friendlyName);
+ }
+
+ String nameFormat = attributeType.getNameFormat();
+ if (StringUtil.isNotNull(nameFormat)) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.NAME_FORMAT.get(), nameFormat);
+ }
+
+ // Take care of other attributes such as x500:encoding
+ Map<QName, String> otherAttribs = attributeType.getOtherAttributes();
+ if (otherAttribs != null) {
+ List<String> nameSpacesDealt = new ArrayList<String>();
+
+ Iterator<QName> keySet = otherAttribs.keySet().iterator();
+ while (keySet != null && keySet.hasNext()) {
+ QName qname = keySet.next();
+ String ns = qname.getNamespaceURI();
+ if (!nameSpacesDealt.contains(ns)) {
+ StaxUtil.writeNameSpace(writer, qname.getPrefix(), ns);
+ nameSpacesDealt.add(ns);
+ }
+ String attribValue = otherAttribs.get(qname);
+ StaxUtil.writeAttribute(writer, qname, attribValue);
+ }
+ }
+
+ List<Object> attributeValues = attributeType.getAttributeValue();
+ if (attributeValues != null) {
+ for (Object attributeValue : attributeValues) {
+ if (attributeValue != null) {
+ if (attributeValue instanceof String) {
+ writeStringAttributeValue((String) attributeValue);
+ } else
+ throw logger.writerUnsupportedAttributeValueError(attributeValue.getClass().getName());
+ }
+ }
+ }
+ }
+
+ public void writeStringAttributeValue(String attributeValue) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.ATTRIBUTE_VALUE.get(), ASSERTION_NSURI.get());
+
+ StaxUtil.writeNameSpace(writer, JBossSAMLURIConstants.XSI_PREFIX.get(), JBossSAMLURIConstants.XSI_NSURI.get());
+ StaxUtil.writeNameSpace(writer, "xs", JBossSAMLURIConstants.XMLSCHEMA_NSURI.get());
+ StaxUtil.writeAttribute(writer, "xsi", JBossSAMLURIConstants.XSI_NSURI.get(), "type", "xs:string");
+ StaxUtil.writeCharacters(writer, attributeValue);
+ StaxUtil.writeEndElement(writer);
+ }
+
+ public void writeLocalizedNameType(LocalizedNameType localizedNameType, QName startElement) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, startElement.getPrefix(), startElement.getLocalPart(),
+ startElement.getNamespaceURI());
+ StaxUtil.writeAttribute(writer, new QName(JBossSAMLURIConstants.XML.get(), "lang", "xml"), localizedNameType.getLang());
+ StaxUtil.writeCharacters(writer, localizedNameType.getValue());
+ StaxUtil.writeEndElement(writer);
+ }
+
+ /**
+ * write an {@code SubjectType} to stream
+ *
+ * @param subject
+ * @param out
+ *
+ * @throws ProcessingException
+ */
+ public void write(SubjectType subject) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.SUBJECT.get(), ASSERTION_NSURI.get());
+
+ SubjectType.STSubType subType = subject.getSubType();
+ if (subType != null) {
+ BaseIDAbstractType baseID = subType.getBaseID();
+ if (baseID instanceof NameIDType) {
+ NameIDType nameIDType = (NameIDType) baseID;
+ write(nameIDType, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.NAMEID.get(), ASSERTION_PREFIX));
+ }
+ EncryptedElementType enc = subType.getEncryptedID();
+ if (enc != null)
+ throw new RuntimeException("NYI");
+ List<SubjectConfirmationType> confirmations = subType.getConfirmation();
+ if (confirmations != null) {
+ for (SubjectConfirmationType confirmation : confirmations) {
+ write(confirmation);
+ }
+ }
+ }
+ List<SubjectConfirmationType> subjectConfirmations = subject.getConfirmation();
+ if (subjectConfirmations != null) {
+ for (SubjectConfirmationType subjectConfirmationType : subjectConfirmations) {
+ write(subjectConfirmationType);
+ }
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ private void write(SubjectConfirmationType subjectConfirmationType) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.SUBJECT_CONFIRMATION.get(),
+ ASSERTION_NSURI.get());
+
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.METHOD.get(), subjectConfirmationType.getMethod());
+
+ BaseIDAbstractType baseID = subjectConfirmationType.getBaseID();
+ if (baseID != null) {
+ write(baseID);
+ }
+ NameIDType nameIDType = subjectConfirmationType.getNameID();
+ if (nameIDType != null) {
+ write(nameIDType, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.NAMEID.get(), ASSERTION_PREFIX));
+ }
+ SubjectConfirmationDataType subjectConfirmationData = subjectConfirmationType.getSubjectConfirmationData();
+ if (subjectConfirmationData != null) {
+ write(subjectConfirmationData);
+ }
+ StaxUtil.writeEndElement(writer);
+ }
+
+ private void write(SubjectConfirmationDataType subjectConfirmationData) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.SUBJECT_CONFIRMATION_DATA.get(),
+ ASSERTION_NSURI.get());
+
+ // Let us look at attributes
+ String inResponseTo = subjectConfirmationData.getInResponseTo();
+ if (StringUtil.isNotNull(inResponseTo)) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.IN_RESPONSE_TO.get(), inResponseTo);
+ }
+
+ XMLGregorianCalendar notBefore = subjectConfirmationData.getNotBefore();
+ if (notBefore != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.NOT_BEFORE.get(), notBefore.toString());
+ }
+
+ XMLGregorianCalendar notOnOrAfter = subjectConfirmationData.getNotOnOrAfter();
+ if (notOnOrAfter != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.NOT_ON_OR_AFTER.get(), notOnOrAfter.toString());
+ }
+
+ String recipient = subjectConfirmationData.getRecipient();
+ if (StringUtil.isNotNull(recipient)) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.RECIPIENT.get(), recipient);
+ }
+
+ String address = subjectConfirmationData.getAddress();
+ if (StringUtil.isNotNull(address)) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ADDRESS.get(), address);
+ }
+
+ if (subjectConfirmationData instanceof KeyInfoConfirmationDataType) {
+ KeyInfoConfirmationDataType kicd = (KeyInfoConfirmationDataType) subjectConfirmationData;
+ KeyInfoType keyInfo = (KeyInfoType) kicd.getAnyType();
+ StaxWriterUtil.writeKeyInfo(writer, keyInfo);
+ /*
+ * if (keyInfo.getContent() == null || keyInfo.getContent().size() == 0) throw new
+ * ProcessingException(ErrorCodes.WRITER_INVALID_KEYINFO_NULL_CONTENT); StaxUtil.writeStartElement(this.writer,
+ * WSTrustConstants.XMLDSig.DSIG_PREFIX, WSTrustConstants.XMLDSig.KEYINFO, WSTrustConstants.XMLDSig.DSIG_NS);
+ * StaxUtil.writeNameSpace(this.writer, WSTrustConstants.XMLDSig.DSIG_PREFIX, WSTrustConstants.XMLDSig.DSIG_NS); //
+ * write the keyInfo content. Object content = keyInfo.getContent().get(0); if (content instanceof Element) {
+ * Element element = (Element) keyInfo.getContent().get(0); StaxUtil.writeDOMNode(this.writer, element); } else if
+ * (content instanceof X509DataType) { X509DataType type = (X509DataType) content; if (type.getDataObjects().size()
+ * == 0) throw new ProcessingException(ErrorCodes.WRITER_NULL_VALUE + "X509Data");
+ * StaxUtil.writeStartElement(this.writer, WSTrustConstants.XMLDSig.DSIG_PREFIX, WSTrustConstants.XMLDSig.X509DATA,
+ * WSTrustConstants.XMLDSig.DSIG_NS); Object obj = type.getDataObjects().get(0); if (obj instanceof Element) {
+ * Element element = (Element) obj; StaxUtil.writeDOMElement(this.writer, element); } else if (obj instanceof
+ * X509CertificateType) { X509CertificateType cert = (X509CertificateType) obj;
+ * StaxUtil.writeStartElement(this.writer, WSTrustConstants.XMLDSig.DSIG_PREFIX, WSTrustConstants.XMLDSig.X509CERT,
+ * WSTrustConstants.XMLDSig.DSIG_NS); StaxUtil.writeCharacters(this.writer, new
+ * String(cert.getEncodedCertificate())); StaxUtil.writeEndElement(this.writer); }
+ * StaxUtil.writeEndElement(this.writer); } StaxUtil.writeEndElement(this.writer);
+ */
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ private void write(BaseIDAbstractType baseId) throws ProcessingException {
+ throw logger.notImplementedYet("Method not implemented.");
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java
new file mode 100755
index 0000000..23a90d3
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLAssertionWriter.java
@@ -0,0 +1,289 @@
+/*
+ * JBoss, Home of Professional Open Source. Copyright 2008, Red Hat Middleware LLC, and individual contributors as
+ * indicated by the @author tags. See the copyright.txt file in the distribution for a full listing of individual
+ * contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any
+ * later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with this software; if not, write to
+ * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site:
+ * http://www.fsf.org.
+ */
+package org.keycloak.saml.processing.core.saml.v2.writers;
+
+import org.keycloak.saml.common.constants.JBossSAMLConstants;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.StaxUtil;
+import org.keycloak.dom.saml.v2.assertion.AdviceType;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+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.AudienceRestrictionType;
+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.ConditionAbstractType;
+import org.keycloak.dom.saml.v2.assertion.ConditionsType;
+import org.keycloak.dom.saml.v2.assertion.EncryptedElementType;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.assertion.StatementAbstractType;
+import org.keycloak.dom.saml.v2.assertion.SubjectType;
+import org.keycloak.dom.saml.v2.assertion.URIType;
+import org.w3c.dom.Element;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamWriter;
+import java.net.URI;
+import java.util.List;
+import java.util.Set;
+
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ASSERTION_NSURI;
+
+/**
+ * Write the SAML Assertion to stream
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Nov 2, 2010
+ */
+public class SAMLAssertionWriter extends BaseWriter {
+
+ public SAMLAssertionWriter(XMLStreamWriter writer) {
+ super(writer);
+ }
+
+ /**
+ * Write an {@code AssertionType} to stream
+ *
+ * @param assertion
+ *
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ */
+ public void write(AssertionType assertion) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.ASSERTION.get(), ASSERTION_NSURI.get());
+ StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, ASSERTION_NSURI.get());
+ StaxUtil.writeDefaultNameSpace(writer, ASSERTION_NSURI.get());
+
+ // Attributes
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ID.get(), assertion.getID());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.VERSION.get(), assertion.getVersion());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ISSUE_INSTANT.get(), assertion.getIssueInstant().toString());
+
+ NameIDType issuer = assertion.getIssuer();
+ if (issuer != null)
+ write(issuer, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX));
+
+ Element sig = assertion.getSignature();
+ if (sig != null)
+ StaxUtil.writeDOMElement(writer, sig);
+
+ SubjectType subject = assertion.getSubject();
+ if (subject != null) {
+ write(subject);
+ }
+
+ ConditionsType conditions = assertion.getConditions();
+ if (conditions != null) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.CONDITIONS.get(), ASSERTION_NSURI.get());
+
+ if (conditions.getNotBefore() != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.NOT_BEFORE.get(), conditions.getNotBefore().toString());
+ }
+
+ if (conditions.getNotOnOrAfter() != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.NOT_ON_OR_AFTER.get(), conditions.getNotOnOrAfter().toString());
+ }
+
+ List<ConditionAbstractType> typeOfConditions = conditions.getConditions();
+ if (typeOfConditions != null) {
+ for (ConditionAbstractType typeCondition : typeOfConditions) {
+ if (typeCondition instanceof AudienceRestrictionType) {
+ AudienceRestrictionType art = (AudienceRestrictionType) typeCondition;
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUDIENCE_RESTRICTION.get(),
+ ASSERTION_NSURI.get());
+ List<URI> audiences = art.getAudience();
+ if (audiences != null) {
+ for (URI audience : audiences) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUDIENCE.get(),
+ ASSERTION_NSURI.get());
+ StaxUtil.writeCharacters(writer, audience.toString());
+ StaxUtil.writeEndElement(writer);
+ }
+ }
+
+ StaxUtil.writeEndElement(writer);
+ }
+ }
+ }
+
+ StaxUtil.writeEndElement(writer);
+ }
+
+ AdviceType advice = assertion.getAdvice();
+ if (advice != null)
+ throw logger.notImplementedYet("Advice");
+
+ Set<StatementAbstractType> statements = assertion.getStatements();
+ if (statements != null) {
+ for (StatementAbstractType statement : statements) {
+ if (statement instanceof AuthnStatementType) {
+ write((AuthnStatementType) statement, false);
+ } else if (statement instanceof AttributeStatementType) {
+ write((AttributeStatementType) statement);
+ } else
+ throw logger.writerUnknownTypeError(statement.getClass().getName());
+ }
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write an {@code StatementAbstractType} to stream
+ *
+ * @param statement
+ *
+ * @throws ProcessingException
+ */
+ public void write(StatementAbstractType statement) throws ProcessingException {
+ // TODO: handle this section
+ throw logger.notImplementedYet("NYI");
+ }
+
+ public void write(AttributeStatementType statement) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.ATTRIBUTE_STATEMENT.get(),
+ ASSERTION_NSURI.get());
+
+ List<ASTChoiceType> attributes = statement.getAttributes();
+ if (attributes != null) {
+ for (ASTChoiceType attr : attributes) {
+ AttributeType attributeType = attr.getAttribute();
+ if (attributeType != null) {
+ write(attributeType);
+ }
+ EncryptedElementType encType = attr.getEncryptedAssertion();
+ if (encType != null)
+ throw logger.notImplementedYet("EncryptedElementType");
+ }
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write an {@code AuthnStatementType} to stream
+ *
+ * @param authnStatement
+ *
+ * @throws ProcessingException
+ */
+ public void write(AuthnStatementType authnStatement, boolean includeNamespace) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_STATEMENT.get(), ASSERTION_NSURI.get());
+ if (includeNamespace) {
+ StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, ASSERTION_NSURI.get());
+ StaxUtil.writeDefaultNameSpace(writer, ASSERTION_NSURI.get());
+ }
+
+ XMLGregorianCalendar authnInstant = authnStatement.getAuthnInstant();
+ if (authnInstant != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.AUTHN_INSTANT.get(), authnInstant.toString());
+ }
+
+ String sessionIndex = authnStatement.getSessionIndex();
+
+ if (sessionIndex != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.SESSION_INDEX.get(), sessionIndex);
+ }
+
+ AuthnContextType authnContext = authnStatement.getAuthnContext();
+ if (authnContext != null)
+ write(authnContext);
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write an {@code AuthnContextType} to stream
+ *
+ * @param authContext
+ *
+ * @throws ProcessingException
+ */
+ public void write(AuthnContextType authContext) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT.get(), ASSERTION_NSURI.get());
+
+ AuthnContextType.AuthnContextTypeSequence sequence = authContext.getSequence();
+ if (sequence != null) {
+ AuthnContextClassRefType authnContextClassRefType = sequence.getClassRef();
+ if (authnContextClassRefType != null) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_CLASS_REF.get(),
+ ASSERTION_NSURI.get());
+ StaxUtil.writeCharacters(writer, authnContextClassRefType.getValue().toASCIIString());
+ StaxUtil.writeEndElement(writer);
+ }
+
+ Set<URIType> uriTypes = sequence.getURIType();
+ if (uriTypes != null) {
+ for (URIType uriType : uriTypes) {
+ if (uriType instanceof AuthnContextDeclType) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX,
+ JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION.get(), ASSERTION_NSURI.get());
+ StaxUtil.writeCharacters(writer, uriType.getValue().toASCIIString());
+ StaxUtil.writeEndElement(writer);
+ }
+ if (uriType instanceof AuthnContextDeclRefType) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX,
+ JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION_REF.get(), ASSERTION_NSURI.get());
+ StaxUtil.writeCharacters(writer, uriType.getValue().toASCIIString());
+ StaxUtil.writeEndElement(writer);
+ }
+ }
+ }
+ }
+
+ Set<URI> authAuthorities = authContext.getAuthenticatingAuthority();
+ if (authAuthorities != null) {
+ for (URI aa : authAuthorities) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHENTICATING_AUTHORITY.get(),
+ ASSERTION_NSURI.get());
+ StaxUtil.writeCharacters(writer, aa.toASCIIString());
+ StaxUtil.writeEndElement(writer);
+ }
+ }
+
+ Set<URIType> uriTypes = authContext.getURIType();
+ for (URIType uriType : uriTypes) {
+ if (uriType instanceof AuthnContextClassRefType) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_CLASS_REF.get(),
+ ASSERTION_NSURI.get());
+ StaxUtil.writeCharacters(writer, uriType.getValue().toString());
+ StaxUtil.writeEndElement(writer);
+ } else if (uriType instanceof AuthnContextDeclRefType) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION_REF.get(),
+ ASSERTION_NSURI.get());
+ StaxUtil.writeCharacters(writer, uriType.getValue().toString());
+ StaxUtil.writeEndElement(writer);
+ } else if (uriType instanceof AuthnContextDeclType) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_DECLARATION.get(),
+ ASSERTION_NSURI.get());
+ StaxUtil.writeCharacters(writer, uriType.getValue().toString());
+ StaxUtil.writeEndElement(writer);
+ }
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java
new file mode 100755
index 0000000..a6bfbe7
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLRequestWriter.java
@@ -0,0 +1,335 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.saml.processing.core.saml.v2.writers;
+
+import org.keycloak.saml.common.constants.JBossSAMLConstants;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.StaxUtil;
+import org.keycloak.saml.common.util.StringUtil;
+import org.keycloak.dom.saml.v2.assertion.AttributeType;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.assertion.SubjectType;
+import org.keycloak.dom.saml.v2.protocol.ArtifactResolveType;
+import org.keycloak.dom.saml.v2.protocol.AttributeQueryType;
+import org.keycloak.dom.saml.v2.protocol.AuthnContextComparisonType;
+import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
+import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
+import org.keycloak.dom.saml.v2.protocol.NameIDPolicyType;
+import org.keycloak.dom.saml.v2.protocol.RequestedAuthnContextType;
+import org.w3c.dom.Element;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamWriter;
+import java.net.URI;
+import java.util.List;
+
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.ASSERTION_NSURI;
+import static org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_NSURI;
+
+/**
+ * Writes a SAML2 Request Type to Stream
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Nov 2, 2010
+ */
+public class SAMLRequestWriter extends BaseWriter {
+
+ public SAMLRequestWriter(XMLStreamWriter writer) {
+ super(writer);
+ }
+
+ /**
+ * Write a {@code AuthnRequestType } to stream
+ *
+ * @param request
+ *
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ */
+ public void write(AuthnRequestType request) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.AUTHN_REQUEST.get(), PROTOCOL_NSURI.get());
+ StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, PROTOCOL_NSURI.get());
+ StaxUtil.writeDefaultNameSpace(writer, ASSERTION_NSURI.get());
+
+ // Attributes
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ID.get(), request.getID());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.VERSION.get(), request.getVersion());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ISSUE_INSTANT.get(), request.getIssueInstant().toString());
+
+ URI destination = request.getDestination();
+ if (destination != null)
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.DESTINATION.get(), destination.toASCIIString());
+
+ String consent = request.getConsent();
+ if (StringUtil.isNotNull(consent))
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.CONSENT.get(), consent);
+
+ URI assertionURL = request.getAssertionConsumerServiceURL();
+ if (assertionURL != null)
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ASSERTION_CONSUMER_SERVICE_URL.get(),
+ assertionURL.toASCIIString());
+
+ Boolean forceAuthn = request.isForceAuthn();
+ if (forceAuthn != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.FORCE_AUTHN.get(), forceAuthn.toString());
+ }
+
+ Boolean isPassive = request.isIsPassive();
+ if (isPassive != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.IS_PASSIVE.get(), isPassive.toString());
+ }
+
+ URI protocolBinding = request.getProtocolBinding();
+ if (protocolBinding != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.PROTOCOL_BINDING.get(), protocolBinding.toString());
+ }
+
+ Integer assertionIndex = request.getAssertionConsumerServiceIndex();
+ if (assertionIndex != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ASSERTION_CONSUMER_SERVICE_INDEX.get(),
+ assertionIndex.toString());
+ }
+
+ Integer attrIndex = request.getAttributeConsumingServiceIndex();
+ if (attrIndex != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ATTRIBUTE_CONSUMING_SERVICE_INDEX.get(), attrIndex.toString());
+ }
+ String providerName = request.getProviderName();
+ if (StringUtil.isNotNull(providerName)) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.PROVIDER_NAME.get(), providerName);
+ }
+
+ NameIDType issuer = request.getIssuer();
+ if (issuer != null) {
+ write(issuer, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX));
+ }
+
+ Element sig = request.getSignature();
+ if (sig != null) {
+ StaxUtil.writeDOMElement(writer, sig);
+ }
+
+ NameIDPolicyType nameIDPolicy = request.getNameIDPolicy();
+ if (nameIDPolicy != null) {
+ write(nameIDPolicy);
+ }
+
+ RequestedAuthnContextType requestedAuthnContext = request.getRequestedAuthnContext();
+ if (requestedAuthnContext != null) {
+ write(requestedAuthnContext);
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write a {@code LogoutRequestType} to stream
+ *
+ * @param logOutRequest
+ *
+ * @throws ProcessingException
+ */
+ public void write(LogoutRequestType logOutRequest) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.LOGOUT_REQUEST.get(), PROTOCOL_NSURI.get());
+
+ StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, PROTOCOL_NSURI.get());
+ StaxUtil.writeDefaultNameSpace(writer, ASSERTION_NSURI.get());
+
+ // Attributes
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ID.get(), logOutRequest.getID());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.VERSION.get(), logOutRequest.getVersion());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ISSUE_INSTANT.get(), logOutRequest.getIssueInstant().toString());
+
+ URI destination = logOutRequest.getDestination();
+ if (destination != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.DESTINATION.get(), destination.toASCIIString());
+ }
+
+ String consent = logOutRequest.getConsent();
+ if (StringUtil.isNotNull(consent))
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.CONSENT.get(), consent);
+
+ NameIDType issuer = logOutRequest.getIssuer();
+ write(issuer, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX));
+
+ Element signature = logOutRequest.getSignature();
+ if (signature != null) {
+ StaxUtil.writeDOMElement(writer, signature);
+ }
+
+ NameIDType nameID = logOutRequest.getNameID();
+ if (nameID != null) {
+ write(nameID, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.NAMEID.get(), ASSERTION_PREFIX));
+ }
+
+ List<String> sessionIndexes = logOutRequest.getSessionIndex();
+
+ for (String sessionIndex : sessionIndexes) {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.SESSION_INDEX.get(), PROTOCOL_NSURI.get());
+
+ StaxUtil.writeCharacters(writer, sessionIndex);
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write a {@code NameIDPolicyType} to stream
+ *
+ * @param nameIDPolicy
+ *
+ * @throws ProcessingException
+ */
+ public void write(NameIDPolicyType nameIDPolicy) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.NAMEID_POLICY.get(), PROTOCOL_NSURI.get());
+
+ URI format = nameIDPolicy.getFormat();
+ if (format != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.FORMAT.get(), format.toASCIIString());
+ }
+
+ String spNameQualifier = nameIDPolicy.getSPNameQualifier();
+ if (StringUtil.isNotNull(spNameQualifier)) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.SP_NAME_QUALIFIER.get(), spNameQualifier);
+ }
+
+ Boolean allowCreate = nameIDPolicy.isAllowCreate();
+ if (allowCreate != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ALLOW_CREATE.get(), allowCreate.toString());
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write a {@code RequestedAuthnContextType} to stream
+ *
+ * @param requestedAuthnContextType
+ *
+ * @throws ProcessingException
+ */
+ public void write(RequestedAuthnContextType requestedAuthnContextType) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.REQUESTED_AUTHN_CONTEXT.get(), PROTOCOL_NSURI.get());
+
+ AuthnContextComparisonType comparison = requestedAuthnContextType.getComparison();
+
+ if (comparison != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.COMPARISON.get(), comparison.value());
+ }
+
+ List<String> authnContextClassRef = requestedAuthnContextType.getAuthnContextClassRef();
+
+ if (authnContextClassRef != null && !authnContextClassRef.isEmpty()) {
+ for (String classRef : authnContextClassRef) {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.AUTHN_CONTEXT_CLASS_REF.get(), ASSERTION_NSURI.get());
+ StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, ASSERTION_NSURI.get());
+ StaxUtil.writeCharacters(writer, classRef);
+ StaxUtil.writeEndElement(writer);
+ }
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ public void write(ArtifactResolveType request) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.ARTIFACT_RESOLVE.get(), PROTOCOL_NSURI.get());
+ StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, PROTOCOL_NSURI.get());
+ StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, ASSERTION_NSURI.get());
+ StaxUtil.writeDefaultNameSpace(writer, ASSERTION_NSURI.get());
+
+ // Attributes
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ID.get(), request.getID());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.VERSION.get(), request.getVersion());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ISSUE_INSTANT.get(), request.getIssueInstant().toString());
+
+ URI destination = request.getDestination();
+ if (destination != null)
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.DESTINATION.get(), destination.toASCIIString());
+
+ String consent = request.getConsent();
+ if (StringUtil.isNotNull(consent))
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.CONSENT.get(), consent);
+
+ NameIDType issuer = request.getIssuer();
+ if (issuer != null) {
+ write(issuer, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX));
+ }
+ Element sig = request.getSignature();
+ if (sig != null) {
+ StaxUtil.writeDOMElement(writer, sig);
+ }
+ String artifact = request.getArtifact();
+ if (StringUtil.isNotNull(artifact)) {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.ARTIFACT.get(), PROTOCOL_NSURI.get());
+ StaxUtil.writeCharacters(writer, artifact);
+ StaxUtil.writeEndElement(writer);
+ }
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ public void write(AttributeQueryType request) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.ATTRIBUTE_QUERY.get(), PROTOCOL_NSURI.get());
+ StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, PROTOCOL_NSURI.get());
+ StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, ASSERTION_NSURI.get());
+ StaxUtil.writeDefaultNameSpace(writer, ASSERTION_NSURI.get());
+
+ // Attributes
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ID.get(), request.getID());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.VERSION.get(), request.getVersion());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ISSUE_INSTANT.get(), request.getIssueInstant().toString());
+
+ URI destination = request.getDestination();
+ if (destination != null)
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.DESTINATION.get(), destination.toASCIIString());
+
+ String consent = request.getConsent();
+ if (StringUtil.isNotNull(consent))
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.CONSENT.get(), consent);
+
+ NameIDType issuer = request.getIssuer();
+ if (issuer != null) {
+ write(issuer, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX));
+ }
+ Element sig = request.getSignature();
+ if (sig != null) {
+ StaxUtil.writeDOMElement(writer, sig);
+ }
+ SubjectType subject = request.getSubject();
+ if (subject != null) {
+ write(subject);
+ }
+ List<AttributeType> attributes = request.getAttribute();
+ for (AttributeType attr : attributes) {
+ write(attr);
+ }
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java
new file mode 100755
index 0000000..1c4d3a6
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/SAMLResponseWriter.java
@@ -0,0 +1,264 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.saml.v2.writers;
+
+import org.keycloak.saml.common.constants.JBossSAMLConstants;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.StaxUtil;
+import org.keycloak.saml.common.util.StringUtil;
+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.ArtifactResponseType;
+import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+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.constants.JBossSAMLURIConstants;
+import org.w3c.dom.Element;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamWriter;
+import java.net.URI;
+import java.util.List;
+
+/**
+ * Write a SAML Response to stream
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Nov 2, 2010
+ */
+public class SAMLResponseWriter extends BaseWriter {
+
+ private final SAMLAssertionWriter assertionWriter;
+
+ public SAMLResponseWriter(XMLStreamWriter writer) {
+ super(writer);
+ this.assertionWriter = new SAMLAssertionWriter(writer);
+ }
+
+ /**
+ * Write a {@code ResponseType} to stream
+ *
+ * @param response
+ * @param out
+ *
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ */
+ public void write(ResponseType response) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.RESPONSE.get(), JBossSAMLURIConstants.PROTOCOL_NSURI.get());
+
+ StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, JBossSAMLURIConstants.PROTOCOL_NSURI.get());
+ StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, JBossSAMLURIConstants.ASSERTION_NSURI.get());
+
+ writeBaseAttributes(response);
+
+ NameIDType issuer = response.getIssuer();
+ if (issuer != null) {
+ write(issuer, new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX));
+ }
+
+ Element sig = response.getSignature();
+ if (sig != null) {
+ StaxUtil.writeDOMElement(writer, sig);
+ }
+
+ StatusType status = response.getStatus();
+ write(status);
+
+ List<ResponseType.RTChoiceType> choiceTypes = response.getAssertions();
+ if (choiceTypes != null) {
+ for (ResponseType.RTChoiceType choiceType : choiceTypes) {
+ AssertionType assertion = choiceType.getAssertion();
+ if (assertion != null) {
+ assertionWriter.write(assertion);
+ }
+
+ EncryptedAssertionType encryptedAssertion = choiceType.getEncryptedAssertion();
+ if (encryptedAssertion != null) {
+ Element encElement = encryptedAssertion.getEncryptedElement();
+ StaxUtil.writeDOMElement(writer, encElement);
+ }
+ }
+ }
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ public void write(ArtifactResponseType response) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.ARTIFACT_RESPONSE.get(), JBossSAMLURIConstants.PROTOCOL_NSURI.get());
+
+ StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, JBossSAMLURIConstants.PROTOCOL_NSURI.get());
+ StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, JBossSAMLURIConstants.ASSERTION_NSURI.get());
+ StaxUtil.writeDefaultNameSpace(writer, JBossSAMLURIConstants.ASSERTION_NSURI.get());
+
+ writeBaseAttributes(response);
+
+ NameIDType issuer = response.getIssuer();
+ if (issuer != null) {
+ write(issuer, new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX));
+ }
+
+ Element sig = response.getSignature();
+ if (sig != null) {
+ StaxUtil.writeDOMElement(writer, sig);
+ }
+
+ StatusType status = response.getStatus();
+ if (status != null) {
+ write(status);
+ }
+ Object anyObj = response.getAny();
+ if (anyObj instanceof AuthnRequestType) {
+ AuthnRequestType authn = (AuthnRequestType) anyObj;
+ SAMLRequestWriter requestWriter = new SAMLRequestWriter(writer);
+ requestWriter.write(authn);
+ } else if (anyObj instanceof ResponseType) {
+ ResponseType rt = (ResponseType) anyObj;
+ write(rt);
+ }
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write a {@code StatusResponseType}
+ *
+ * @param response
+ * @param qname QName of the starting element
+ * @param out
+ *
+ * @throws ProcessingException
+ */
+ public void write(StatusResponseType response, QName qname) throws ProcessingException {
+ if (qname == null) {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.STATUS_RESPONSE_TYPE.get(),
+ JBossSAMLURIConstants.PROTOCOL_NSURI.get());
+ } else {
+ StaxUtil.writeStartElement(writer, qname.getPrefix(), qname.getLocalPart(), qname.getNamespaceURI());
+ }
+
+ StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, JBossSAMLURIConstants.PROTOCOL_NSURI.get());
+ StaxUtil.writeDefaultNameSpace(writer, JBossSAMLURIConstants.ASSERTION_NSURI.get());
+
+ writeBaseAttributes(response);
+
+ NameIDType issuer = response.getIssuer();
+ write(issuer, new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX));
+
+ StatusType status = response.getStatus();
+ write(status);
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write a {@code StatusType} to stream
+ *
+ * @param status
+ * @param out
+ *
+ * @throws ProcessingException
+ */
+ public void write(StatusType status) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.STATUS.get(), JBossSAMLURIConstants.PROTOCOL_NSURI.get());
+
+ StatusCodeType statusCodeType = status.getStatusCode();
+ write(statusCodeType);
+
+ String statusMessage = status.getStatusMessage();
+ if (StringUtil.isNotNull(statusMessage)) {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.STATUS_MESSAGE.get(), JBossSAMLURIConstants.PROTOCOL_NSURI.get());
+ StaxUtil.writeEndElement(writer);
+ }
+
+ StatusDetailType statusDetail = status.getStatusDetail();
+ if (statusDetail != null)
+ write(statusDetail);
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write a {@code StatusCodeType} to stream
+ *
+ * @param statusCodeType
+ * @param out
+ *
+ * @throws ProcessingException
+ */
+ public void write(StatusCodeType statusCodeType) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.STATUS_CODE.get(), JBossSAMLURIConstants.PROTOCOL_NSURI.get());
+
+ URI value = statusCodeType.getValue();
+ if (value != null) {
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.VALUE.get(), value.toASCIIString());
+ }
+ StatusCodeType subStatusCode = statusCodeType.getStatusCode();
+ if (subStatusCode != null)
+ write(subStatusCode);
+
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write a {@code StatusDetailType} to stream
+ *
+ * @param statusDetailType
+ * @param out
+ *
+ * @throws ProcessingException
+ */
+ public void write(StatusDetailType statusDetailType) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.STATUS_CODE.get(), JBossSAMLURIConstants.PROTOCOL_NSURI.get());
+ StaxUtil.writeEndElement(writer);
+ StaxUtil.flush(writer);
+ }
+
+ /**
+ * Write the common attributes for all response types
+ *
+ * @param statusResponse
+ *
+ * @throws ProcessingException
+ */
+ private void writeBaseAttributes(StatusResponseType statusResponse) throws ProcessingException {
+ // Attributes
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ID.get(), statusResponse.getID());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.VERSION.get(), statusResponse.getVersion());
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.ISSUE_INSTANT.get(), statusResponse.getIssueInstant().toString());
+
+ String destination = statusResponse.getDestination();
+ if (StringUtil.isNotNull(destination))
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.DESTINATION.get(), destination);
+
+ String consent = statusResponse.getConsent();
+ if (StringUtil.isNotNull(consent))
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.CONSENT.get(), consent);
+
+ String inResponseTo = statusResponse.getInResponseTo();
+ if (StringUtil.isNotNull(inResponseTo))
+ StaxUtil.writeAttribute(writer, JBossSAMLConstants.IN_RESPONSE_TO.get(), inResponseTo);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/CoreConfigUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/CoreConfigUtil.java
new file mode 100755
index 0000000..4aa2819
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/CoreConfigUtil.java
@@ -0,0 +1,208 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.dom.saml.v2.metadata.EndpointType;
+import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
+import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType.EDTChoiceType;
+import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType.EDTDescriptorChoiceType;
+import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType;
+import org.keycloak.dom.saml.v2.metadata.IndexedEndpointType;
+import org.keycloak.dom.saml.v2.metadata.SPSSODescriptorType;
+import java.util.List;
+
+/**
+ * Utility for configuration
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Nov 13, 2009
+ */
+public class CoreConfigUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * Get the first metadata descriptor for an IDP
+ *
+ * @param entitiesDescriptor
+ *
+ * @return
+ */
+ public static IDPSSODescriptorType getIDPDescriptor(EntitiesDescriptorType entitiesDescriptor) {
+ IDPSSODescriptorType idp = null;
+ List<Object> entitiesList = entitiesDescriptor.getEntityDescriptor();
+ for (Object theObject : entitiesList) {
+ if (theObject instanceof EntitiesDescriptorType) {
+ idp = getIDPDescriptor((EntitiesDescriptorType) theObject);
+ } else if (theObject instanceof EntityDescriptorType) {
+ idp = getIDPDescriptor((EntityDescriptorType) theObject);
+ }
+ if (idp != null) {
+ break;
+ }
+ }
+ return idp;
+ }
+
+ /**
+ * Get the IDP metadata descriptor from an entity descriptor
+ *
+ * @param entityDescriptor
+ *
+ * @return
+ */
+ public static IDPSSODescriptorType getIDPDescriptor(EntityDescriptorType entityDescriptor) {
+ List<EDTChoiceType> edtChoices = entityDescriptor.getChoiceType();
+ for (EDTChoiceType edt : edtChoices) {
+ List<EDTDescriptorChoiceType> edtDescriptors = edt.getDescriptors();
+ for (EDTDescriptorChoiceType edtDesc : edtDescriptors) {
+ IDPSSODescriptorType idpSSO = edtDesc.getIdpDescriptor();
+ if (idpSSO != null) {
+ return idpSSO;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get the SP Descriptor from an entity descriptor
+ *
+ * @param entityDescriptor
+ *
+ * @return
+ */
+ public static SPSSODescriptorType getSPDescriptor(EntityDescriptorType entityDescriptor) {
+ List<EDTChoiceType> edtChoices = entityDescriptor.getChoiceType();
+ for (EDTChoiceType edt : edtChoices) {
+ List<EDTDescriptorChoiceType> edtDescriptors = edt.getDescriptors();
+ for (EDTDescriptorChoiceType edtDesc : edtDescriptors) {
+ SPSSODescriptorType spSSO = edtDesc.getSpDescriptor();
+ if (spSSO != null) {
+ return spSSO;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Given a binding uri, get the IDP identity url
+ *
+ * @param idp
+ * @param bindingURI
+ *
+ * @return
+ */
+ public static String getIdentityURL(IDPSSODescriptorType idp, String bindingURI) {
+ String identityURL = null;
+
+ List<EndpointType> endpoints = idp.getSingleSignOnService();
+ for (EndpointType endpoint : endpoints) {
+ if (endpoint.getBinding().toString().equals(bindingURI)) {
+ identityURL = endpoint.getLocation().toString();
+ break;
+ }
+
+ }
+ return identityURL;
+ }
+
+ /**
+ * Given a binding uri, get the IDP identity url
+ *
+ * @param idp
+ * @param bindingURI
+ *
+ * @return
+ */
+ public static String getLogoutURL(IDPSSODescriptorType idp, String bindingURI) {
+ String logoutURL = null;
+
+ List<EndpointType> endpoints = idp.getSingleLogoutService();
+ for (EndpointType endpoint : endpoints) {
+ if (endpoint.getBinding().toString().equals(bindingURI)) {
+ logoutURL = endpoint.getLocation().toString();
+ break;
+ }
+
+ }
+ return logoutURL;
+ }
+
+ /**
+ * Given a binding uri, get the IDP logout response url (used for global logouts)
+ */
+ public static String getLogoutResponseLocation(IDPSSODescriptorType idp, String bindingURI) {
+ String logoutResponseLocation = null;
+
+ List<EndpointType> endpoints = idp.getSingleLogoutService();
+ for (EndpointType endpoint : endpoints) {
+ if (endpoint.getBinding().toString().equals(bindingURI)) {
+ if (endpoint.getResponseLocation() != null) {
+ logoutResponseLocation = endpoint.getResponseLocation().toString();
+ } else {
+ logoutResponseLocation = null;
+ }
+
+ break;
+ }
+
+ }
+ return logoutResponseLocation;
+ }
+
+ /**
+ * Get the service url for the SP
+ *
+ * @param sp
+ * @param bindingURI
+ *
+ * @return
+ */
+ public static String getServiceURL(SPSSODescriptorType sp, String bindingURI) {
+ String serviceURL = null;
+
+ List<IndexedEndpointType> endpoints = sp.getAssertionConsumerService();
+ for (IndexedEndpointType endpoint : endpoints) {
+ if (endpoint.getBinding().toString().equals(bindingURI)) {
+ serviceURL = endpoint.getLocation().toString();
+ break;
+ }
+
+ }
+ return serviceURL;
+ }
+
+ private static void addAllEntityDescriptorsRecursively(List<EntityDescriptorType> resultList,
+ EntitiesDescriptorType entitiesDescriptorType) {
+ List<Object> entities = entitiesDescriptorType.getEntityDescriptor();
+ for (Object o : entities) {
+ if (o instanceof EntitiesDescriptorType) {
+ addAllEntityDescriptorsRecursively(resultList, (EntitiesDescriptorType) o);
+ } else if (o instanceof EntityDescriptorType) {
+ resultList.add((EntityDescriptorType) o);
+ } else {
+ throw new IllegalArgumentException("Wrong type: " + o.getClass());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/EncryptionKeyUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/EncryptionKeyUtil.java
new file mode 100755
index 0000000..850997d
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/EncryptionKeyUtil.java
@@ -0,0 +1,50 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import java.security.GeneralSecurityException;
+
+/**
+ * Utility to generate symmetric key
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Feb 4, 2009
+ */
+public class EncryptionKeyUtil {
+
+ /**
+ * Generate a secret key useful for encryption/decryption
+ *
+ * @param encAlgo
+ * @param keySize Length of the key (if 0, defaults to 128 bits)
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ */
+ public static SecretKey getSecretKey(String encAlgo, int keySize) throws GeneralSecurityException {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(encAlgo);
+ if (keySize == 0)
+ keySize = 128;
+ keyGenerator.init(keySize);
+ return keyGenerator.generateKey();
+ }
+
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolver.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolver.java
new file mode 100755
index 0000000..99b5a3c
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/IDFedLSInputResolver.java
@@ -0,0 +1,224 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.saml.common.util.StringUtil;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * An LSResource Resolver for schema validation
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jun 9, 2009
+ */
+public class IDFedLSInputResolver implements LSResourceResolver {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ private static Map<String, LSInput> lsmap = new HashMap<String, LSInput>();
+
+ private static Map<String, String> schemaLocationMap = new LinkedHashMap<String, String>();
+
+ static {
+ // XML Schema/DTD
+ schemaLocationMap.put("datatypes.dtd", "schema/w3c/xmlschema/datatypes.dtd");
+ schemaLocationMap.put("XMLSchema.dtd", "schema/w3c/xmlschema/XMLSchema.dtd");
+ schemaLocationMap.put("http://www.w3.org/2001/xml.xsd", "schema/w3c/xmlschema/xml.xsd");
+
+ // XML DSIG
+ schemaLocationMap.put("http://www.w3.org/2000/09/xmldsig#", "schema/w3c/xmldsig/xmldsig-core-schema.xsd");
+ schemaLocationMap.put("http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd",
+ "schema/w3c/xmldsig/xmldsig-core-schema.xsd");
+
+ // XML Enc
+ schemaLocationMap.put("http://www.w3.org/2001/04/xmlenc#", "schema/w3c/xmlenc/xenc-schema.xsd");
+ schemaLocationMap.put("http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/xenc-schema.xsd",
+ "schema/w3c/xmlenc/xenc-schema.xsd");
+
+ // XACML
+ schemaLocationMap.put("access_control-xacml-2.0-context-schema-os.xsd",
+ "schema/access_control-xacml-2.0-context-schema-os.xsd");
+ schemaLocationMap.put("access_control-xacml-2.0-policy-schema-os.xsd",
+ "schema/access_control-xacml-2.0-policy-schema-os.xsd");
+
+ // SAML
+
+ schemaLocationMap.put("saml-schema-assertion-2.0.xsd", "schema/saml/v2/saml-schema-assertion-2.0.xsd");
+ schemaLocationMap.put("saml-schema-protocol-2.0.xsd", "schema/saml/v2/saml-schema-protocol-2.0.xsd");
+ schemaLocationMap.put("saml-schema-metadata-2.0.xsd", "schema/saml/v2/saml-schema-metadata-2.0.xsd");
+ schemaLocationMap.put("saml-schema-x500-2.0.xsd", "schema/saml/v2/saml-schema-x500-2.0.xsd");
+ schemaLocationMap.put("saml-schema-xacml-2.0.xsd", "schema/saml/v2/saml-schema-xacml-2.0.xsd");
+ schemaLocationMap.put("saml-schema-xacml-2.0.xsd", "schema/saml/v2/saml-schema-xacml-2.0.xsd");
+ schemaLocationMap.put("saml-schema-authn-context-2.0.xsd", "schema/saml/v2/saml-schema-authn-context-2.0.xsd");
+ schemaLocationMap.put("saml-schema-authn-context-types-2.0.xsd",
+ "schema/saml/v2/saml-schema-authn-context-types-2.0.xsd");
+
+ schemaLocationMap.put("saml-schema-assertion-1.0.xsd", "schema/saml/v1/saml-schema-assertion-1.0.xsd");
+ schemaLocationMap.put("oasis-sstc-saml-schema-assertion-1.1.xsd",
+ "schema/saml/v1/oasis-sstc-saml-schema-assertion-1.1.xsd");
+ schemaLocationMap.put("saml-schema-protocol-1.1.xsd", "schema/saml/v1/saml-schema-protocol-1.1.xsd");
+
+ schemaLocationMap.put("access_control-xacml-2.0-saml-assertion-schema-os.xsd",
+ "schema/saml/v2/access_control-xacml-2.0-saml-assertion-schema-os.xsd");
+
+ schemaLocationMap.put("access_control-xacml-2.0-saml-protocol-schema-os.xsd",
+ "schema/saml/v2/access_control-xacml-2.0-saml-protocol-schema-os.xsd");
+
+ // WS-T
+ schemaLocationMap.put("http://docs.oasis-open.org/ws-sx/ws-trust/200512", "schema/wstrust/v1_3/ws-trust-1.3.xsd");
+ schemaLocationMap.put("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
+ "schema/wstrust/v1_3/oasis-200401-wss-wssecurity-secext-1.0.xsd");
+ schemaLocationMap.put("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd",
+ "schema/wstrust/v1_3/oasis-200401-wss-wssecurity-utility-1.0.xsd");
+ schemaLocationMap.put("http://schemas.xmlsoap.org/ws/2004/09/policy", "schema/wstrust/v1_3/ws-policy.xsd");
+ schemaLocationMap.put("http://www.w3.org/2005/08/addressing", "schema/wstrust/v1_3/ws-addr.xsd");
+ }
+
+ public static Collection<String> schemas() {
+ Collection<String> schemaValues = schemaLocationMap.values();
+ schemaValues.remove("schema/w3c/xmlschema/datatypes.dtd");
+ schemaValues.remove("schema/w3c/xmlschema/XMLSchema.dtd");
+ logger.info("Considered the schemas:" + schemaValues);
+ return schemaValues;
+ }
+
+ public LSInput resolveResource(String type, String namespaceURI, final String publicId, final String systemId,
+ final String baseURI) {
+ LSInput lsi = null;
+ if (systemId == null)
+ throw logger.nullValueError("systemid");
+ if (StringUtil.isNotNull(systemId) && systemId.endsWith("dtd") && StringUtil.isNotNull(baseURI)) {
+ lsi = lsmap.get(baseURI);
+ }
+ if (lsi == null)
+ lsi = lsmap.get(systemId);
+ if (lsi == null) {
+ final String loc = schemaLocationMap.get(systemId);
+ if (loc == null)
+ return null;
+
+ lsi = new PicketLinkLSInput(baseURI, loc, publicId, systemId);
+
+ logger.trace("Loaded:" + lsi);
+
+ lsmap.put(systemId, lsi);
+ }
+ return lsi;
+ }
+
+ public static class PicketLinkLSInput implements LSInput {
+
+ private final String baseURI;
+
+ private final String loc;
+
+ private final String publicId;
+
+ private final String systemId;
+
+ public PicketLinkLSInput(String baseURI, String loc, String publicID, String systemID) {
+ this.baseURI = baseURI;
+ this.loc = loc;
+ this.publicId = publicID;
+ this.systemId = systemID;
+ }
+
+ public String getBaseURI() {
+ return baseURI;
+ }
+
+ public InputStream getByteStream() {
+ URL url = SecurityActions.loadResource(getClass(), loc);
+ InputStream is;
+ try {
+ is = url.openStream();
+ } catch (IOException e) {
+ throw new RuntimeException(logger.classNotLoadedError(loc));
+ }
+ if (is == null)
+ throw logger.nullValueError("inputstream is null for " + loc);
+ return is;
+ }
+
+ public boolean getCertifiedText() {
+ return false;
+ }
+
+ public Reader getCharacterStream() {
+ return null;
+ }
+
+ public String getEncoding() {
+ return null;
+ }
+
+ public String getPublicId() {
+ return publicId;
+ }
+
+ public String getStringData() {
+ return null;
+ }
+
+ public String getSystemId() {
+ return systemId;
+ }
+
+ public void setBaseURI(String baseURI) {
+ }
+
+ public void setByteStream(InputStream byteStream) {
+ }
+
+ public void setCertifiedText(boolean certifiedText) {
+ }
+
+ public void setCharacterStream(Reader characterStream) {
+ }
+
+ public void setEncoding(String encoding) {
+ }
+
+ public void setPublicId(String publicId) {
+ }
+
+ public void setStringData(String stringData) {
+ }
+
+ public void setSystemId(String systemId) {
+ }
+
+ @Override
+ public String toString() {
+ return "PicketLinkLSInput [baseURI=" + baseURI + ", loc=" + loc + ", publicId=" + publicId + ", systemId="
+ + systemId + "]";
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXBUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXBUtil.java
new file mode 100755
index 0000000..2c3ad47
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXBUtil.java
@@ -0,0 +1,280 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+
+/**
+ * Utility to obtain JAXB2 marshaller/unmarshaller etc
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since May 26, 2009
+ */
+public class JAXBUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ public static final String W3C_XML_SCHEMA_NS_URI = "http://www.w3.org/2001/XMLSchema";
+
+ private static HashMap<String, JAXBContext> jaxbContextHash = new HashMap<String, JAXBContext>();
+
+ static {
+ // Useful on Sun VMs. Harmless on other VMs.
+ SecurityActions.setSystemProperty("com.sun.xml.bind.v2.runtime.JAXBContextImpl.fastBoot", "true");
+ }
+
+ /**
+ * Get the JAXB Marshaller
+ *
+ * @param pkgName The package name for the jaxb context
+ * @param schemaLocation location of the schema to validate against
+ *
+ * @return Marshaller
+ *
+ * @throws JAXBException
+ * @throws SAXException
+ */
+ public static Marshaller getValidatingMarshaller(String pkgName, String schemaLocation) throws JAXBException, SAXException {
+ Marshaller marshaller = getMarshaller(pkgName);
+
+ // Validate against schema
+ Schema schema = getJAXPSchemaInstance(schemaLocation);
+ marshaller.setSchema(schema);
+
+ return marshaller;
+ }
+
+ /**
+ * Get the JAXB Marshaller
+ *
+ * @param pkgName The package name for the jaxb context
+ *
+ * @return Marshaller
+ *
+ * @throws JAXBException
+ */
+ public static Marshaller getMarshaller(String pkgName) throws JAXBException {
+ if (pkgName == null)
+ throw logger.nullArgumentError("pkgName");
+
+ JAXBContext jc = getJAXBContext(pkgName);
+ Marshaller marshaller = jc.createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE); // Breaks signatures
+ return marshaller;
+ }
+
+ /**
+ * Get the JAXB Unmarshaller
+ *
+ * @param pkgName The package name for the jaxb context
+ *
+ * @return unmarshaller
+ *
+ * @throws JAXBException
+ */
+ public static Unmarshaller getUnmarshaller(String pkgName) throws JAXBException {
+ if (pkgName == null)
+ throw logger.nullArgumentError("pkgName");
+ JAXBContext jc = getJAXBContext(pkgName);
+ return jc.createUnmarshaller();
+ }
+
+ /**
+ * Get the JAXB Unmarshaller for a selected set of package names
+ *
+ * @param pkgNames
+ *
+ * @return
+ *
+ * @throws JAXBException
+ */
+ public static Unmarshaller getUnmarshaller(String... pkgNames) throws JAXBException {
+ if (pkgNames == null)
+ throw logger.nullArgumentError("pkgName");
+ int len = pkgNames.length;
+ if (len == 0)
+ return getUnmarshaller(pkgNames[0]);
+
+ JAXBContext jc = getJAXBContext(pkgNames);
+ return jc.createUnmarshaller();
+ }
+
+ /**
+ * Get the JAXB Unmarshaller
+ *
+ * @param pkgName The package name for the jaxb context
+ * @param schemaLocation location of the schema to validate against
+ *
+ * @return unmarshaller
+ *
+ * @throws JAXBException
+ * @throws SAXException
+ */
+ public static Unmarshaller getValidatingUnmarshaller(String pkgName, String schemaLocation) throws JAXBException,
+ SAXException {
+ Unmarshaller unmarshaller = getUnmarshaller(pkgName);
+ Schema schema = getJAXPSchemaInstance(schemaLocation);
+ unmarshaller.setSchema(schema);
+
+ return unmarshaller;
+ }
+
+ public static Unmarshaller getValidatingUnmarshaller(String[] pkgNames, String[] schemaLocations) throws JAXBException,
+ SAXException, IOException {
+ StringBuilder builder = new StringBuilder();
+ int len = pkgNames.length;
+ if (len == 0)
+ throw logger.nullValueError("Packages are empty");
+
+ for (String pkg : pkgNames) {
+ builder.append(pkg);
+ builder.append(":");
+ }
+
+ Unmarshaller unmarshaller = getUnmarshaller(builder.toString());
+
+ SchemaFactory schemaFactory = getSchemaFactory();
+
+ // Get the sources
+ Source[] schemaSources = new Source[schemaLocations.length];
+
+ int i = 0;
+ for (String schemaLocation : schemaLocations) {
+ URL schemaURL = SecurityActions.loadResource(JAXBUtil.class, schemaLocation);
+ if (schemaURL == null)
+ throw logger.nullValueError("Schema URL :" + schemaLocation);
+
+ schemaSources[i++] = new StreamSource(schemaURL.openStream());
+ }
+
+ Schema schema = schemaFactory.newSchema(schemaSources);
+ unmarshaller.setSchema(schema);
+
+ return unmarshaller;
+ }
+
+ private static Schema getJAXPSchemaInstance(String schemaLocation) throws SAXException {
+ URL schemaURL = SecurityActions.loadResource(JAXBUtil.class, schemaLocation);
+ if (schemaURL == null)
+ throw logger.nullValueError("Schema URL :" + schemaLocation);
+ SchemaFactory scFact = getSchemaFactory();
+ Schema schema = scFact.newSchema(schemaURL);
+ return schema;
+ }
+
+ private static SchemaFactory getSchemaFactory() {
+ SchemaFactory scFact = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
+
+ // Always install the resolver unless the system property is set
+ if (SecurityActions.getSystemProperty("org.picketlink.identity.federation.jaxb.ls", null) == null)
+ scFact.setResourceResolver(new IDFedLSInputResolver());
+
+ scFact.setErrorHandler(new ErrorHandler() {
+ public void error(SAXParseException exception) throws SAXException {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Line Number=").append(exception.getLineNumber());
+ builder.append(" Col Number=").append(exception.getColumnNumber());
+ builder.append(" Public ID=").append(exception.getPublicId());
+ builder.append(" System ID=").append(exception.getSystemId());
+ builder.append(" exc=").append(exception.getLocalizedMessage());
+
+ logger.trace("SAX Error:" + builder.toString());
+ }
+
+ public void fatalError(SAXParseException exception) throws SAXException {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Line Number=").append(exception.getLineNumber());
+ builder.append(" Col Number=").append(exception.getColumnNumber());
+ builder.append(" Public ID=").append(exception.getPublicId());
+ builder.append(" System ID=").append(exception.getSystemId());
+ builder.append(" exc=").append(exception.getLocalizedMessage());
+
+ logger.error("SAX Fatal Error:" + builder.toString());
+ }
+
+ public void warning(SAXParseException exception) throws SAXException {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Line Number=").append(exception.getLineNumber());
+ builder.append(" Col Number=").append(exception.getColumnNumber());
+ builder.append(" Public ID=").append(exception.getPublicId());
+ builder.append(" System ID=").append(exception.getSystemId());
+ builder.append(" exc=").append(exception.getLocalizedMessage());
+
+ logger.trace("SAX Warn:" + builder.toString());
+ }
+ });
+ return scFact;
+ }
+
+ public static JAXBContext getJAXBContext(String path) throws JAXBException {
+ JAXBContext jx = jaxbContextHash.get(path);
+ if (jx == null) {
+ jx = JAXBContext.newInstance(path);
+ jaxbContextHash.put(path, jx);
+ }
+ return jx;
+ }
+
+ public static JAXBContext getJAXBContext(String... paths) throws JAXBException {
+ int len = paths.length;
+ if (len == 0)
+ return getJAXBContext(paths[0]);
+
+ StringBuilder builder = new StringBuilder();
+ for (String path : paths) {
+ builder.append(path).append(":");
+ }
+
+ String finalPath = builder.toString();
+
+ JAXBContext jx = jaxbContextHash.get(finalPath);
+ if (jx == null) {
+ jx = JAXBContext.newInstance(finalPath);
+ jaxbContextHash.put(finalPath, jx);
+ }
+ return jx;
+ }
+
+ public static JAXBContext getJAXBContext(Class<?> clazz) throws JAXBException {
+ String clazzName = clazz.getName();
+
+ JAXBContext jx = jaxbContextHash.get(clazzName);
+ if (jx == null) {
+ jx = JAXBContext.newInstance(clazz);
+ jaxbContextHash.put(clazzName, jx);
+ }
+ return jx;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXPValidationUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXPValidationUtil.java
new file mode 100755
index 0000000..836b3fc
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/JAXPValidationUtil.java
@@ -0,0 +1,168 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.saml.common.constants.GeneralConstants;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.DocumentUtil;
+import org.keycloak.saml.common.util.SystemPropertiesUtil;
+import org.w3c.dom.Node;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+
+/**
+ * Utility class associated with JAXP Validation
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jun 30, 2011
+ */
+public class JAXPValidationUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ protected static Validator validator;
+
+ protected static SchemaFactory schemaFactory;
+
+ public static void validate(String str) throws SAXException, IOException {
+ validator().validate(new StreamSource(str));
+ }
+
+ public static void validate(InputStream stream) throws SAXException, IOException {
+ validator().validate(new StreamSource(stream));
+ }
+
+ /**
+ * Based on system property "picketlink.schema.validate" set to "true", do schema validation
+ *
+ * @param samlDocument
+ *
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ */
+ public static void checkSchemaValidation(Node samlDocument) throws ProcessingException {
+ if (SecurityActions.getSystemProperty("picketlink.schema.validate", "false").equalsIgnoreCase("true")) {
+ try {
+ JAXPValidationUtil.validate(DocumentUtil.getNodeAsStream(samlDocument));
+ } catch (Exception e) {
+ throw logger.processingError(e);
+ }
+ }
+ }
+
+ public static Validator validator() throws SAXException, IOException {
+ SystemPropertiesUtil.ensure();
+
+ if (validator == null) {
+ Schema schema = getSchema();
+ if (schema == null)
+ throw logger.nullValueError("schema");
+
+ validator = schema.newValidator();
+ validator.setErrorHandler(new CustomErrorHandler());
+ }
+ return validator;
+ }
+
+ private static Schema getSchema() throws IOException {
+ boolean tccl_jaxp = SystemPropertiesUtil.getSystemProperty(GeneralConstants.TCCL_JAXP, "false").equalsIgnoreCase("true");
+
+ ClassLoader prevTCCL = SecurityActions.getTCCL();
+ try {
+ if (tccl_jaxp) {
+ SecurityActions.setTCCL(JAXPValidationUtil.class.getClassLoader());
+ }
+ schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
+
+ schemaFactory.setResourceResolver(new IDFedLSInputResolver());
+ schemaFactory.setErrorHandler(new CustomErrorHandler());
+ } finally {
+ if (tccl_jaxp) {
+ SecurityActions.setTCCL(prevTCCL);
+ }
+ }
+ Schema schemaGrammar = null;
+ try {
+ schemaGrammar = schemaFactory.newSchema(sources());
+ } catch (SAXException e) {
+ logger.xmlCouldNotGetSchema(e);
+ }
+ return schemaGrammar;
+ }
+
+ private static Source[] sources() throws IOException {
+ List<String> schemas = SchemaManagerUtil.getSchemas();
+
+ Source[] sourceArr = new Source[schemas.size()];
+
+ int i = 0;
+ for (String schema : schemas) {
+ URL url = SecurityActions.loadResource(JAXPValidationUtil.class, schema);
+ if (url == null)
+ throw logger.nullValueError("schema url:" + schema);
+ sourceArr[i++] = new StreamSource(url.openStream());
+ }
+ return sourceArr;
+ }
+
+ private static class CustomErrorHandler implements ErrorHandler {
+
+ public void error(SAXParseException ex) throws SAXException {
+ logException(ex);
+ if (ex.getMessage().contains("null") == false) {
+ throw ex;
+ }
+ }
+
+ public void fatalError(SAXParseException ex) throws SAXException {
+ logException(ex);
+ throw ex;
+ }
+
+ public void warning(SAXParseException ex) throws SAXException {
+ logException(ex);
+ }
+
+ private void logException(SAXParseException sax) {
+ StringBuilder builder = new StringBuilder();
+
+ if (logger.isTraceEnabled()) {
+ builder.append("[line:").append(sax.getLineNumber()).append(",").append("::col=").append(sax.getColumnNumber())
+ .append("]");
+ builder.append("[publicID:").append(sax.getPublicId()).append(",systemId=").append(sax.getSystemId())
+ .append("]");
+ builder.append(":").append(sax.getLocalizedMessage());
+ logger.trace(builder.toString());
+ }
+ }
+ }
+
+ ;
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/KeyStoreUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/KeyStoreUtil.java
new file mode 100755
index 0000000..793f608
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/KeyStoreUtil.java
@@ -0,0 +1,187 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+
+/**
+ * Utility to handle Java Keystore
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jan 12, 2009
+ */
+public class KeyStoreUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * Get the KeyStore
+ *
+ * @param keyStoreFile
+ * @param storePass
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ public static KeyStore getKeyStore(File keyStoreFile, char[] storePass) throws GeneralSecurityException, IOException {
+ FileInputStream fis = new FileInputStream(keyStoreFile);
+ return getKeyStore(fis, storePass);
+ }
+
+ /**
+ * Get the Keystore given the url to the keystore file as a string
+ *
+ * @param fileURL
+ * @param storePass
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ public static KeyStore getKeyStore(String fileURL, char[] storePass) throws GeneralSecurityException, IOException {
+ if (fileURL == null)
+ throw logger.nullArgumentError("fileURL");
+
+ File file = new File(fileURL);
+ FileInputStream fis = new FileInputStream(file);
+ return getKeyStore(fis, storePass);
+ }
+
+ /**
+ * Get the Keystore given the URL to the keystore
+ *
+ * @param url
+ * @param storePass
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ public static KeyStore getKeyStore(URL url, char[] storePass) throws GeneralSecurityException, IOException {
+ if (url == null)
+ throw logger.nullArgumentError("url");
+
+ return getKeyStore(url.openStream(), storePass);
+ }
+
+ /**
+ * Get the Key Store <b>Note:</b> This method wants the InputStream to be not null.
+ *
+ * @param ksStream
+ * @param storePass
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ * @throws IOException
+ * @throws IllegalArgumentException if ksStream is null
+ */
+ public static KeyStore getKeyStore(InputStream ksStream, char[] storePass) throws GeneralSecurityException, IOException {
+ if (ksStream == null)
+ throw logger.nullArgumentError("InputStream for the KeyStore");
+ KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+ ks.load(ksStream, storePass);
+ return ks;
+ }
+
+ /**
+ * Get the Public Key from the keystore
+ *
+ * @param ks
+ * @param alias
+ * @param password
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ */
+ public static PublicKey getPublicKey(KeyStore ks, String alias, char[] password) throws GeneralSecurityException {
+ PublicKey publicKey = null;
+
+ // Get private key
+ Key key = ks.getKey(alias, password);
+ if (key instanceof PrivateKey) {
+ // Get certificate of public key
+ Certificate cert = ks.getCertificate(alias);
+
+ // Get public key
+ publicKey = cert.getPublicKey();
+ }
+ // if alias is a certificate alias, get the public key from the certificate.
+ if (publicKey == null) {
+ Certificate cert = ks.getCertificate(alias);
+ if (cert != null)
+ publicKey = cert.getPublicKey();
+ }
+ return publicKey;
+ }
+
+ /**
+ * Add a certificate to the KeyStore
+ *
+ * @param keystoreFile
+ * @param storePass
+ * @param alias
+ * @param cert
+ *
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ public static void addCertificate(File keystoreFile, char[] storePass, String alias, Certificate cert)
+ throws GeneralSecurityException, IOException {
+ KeyStore keystore = getKeyStore(keystoreFile, storePass);
+
+ // Add the certificate
+ keystore.setCertificateEntry(alias, cert);
+
+ // Save the new keystore contents
+ FileOutputStream out = null;
+ try {
+ out = new FileOutputStream(keystoreFile);
+ keystore.store(out, storePass);
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException ioe) {
+ // Ignore
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/NamespaceContext.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/NamespaceContext.java
new file mode 100755
index 0000000..4928e64
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/NamespaceContext.java
@@ -0,0 +1,96 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Helper class in process of parsing signature out of SAML token.
+ * usage example:
+ * <code>
+ * xpath.setNamespaceContext(
+ * NamespaceContext.create()
+ * .addNsUriPair(xmlSignatureNSPrefix, JBossSAMLURIConstants.XMLDSIG_NSURI.get())
+ * );
+ * </code>
+ *
+ * @author Peter Skopek: pskopek at redhat dot com
+ */
+
+public class NamespaceContext implements javax.xml.namespace.NamespaceContext {
+
+ private Map<String, String> nsMap = new HashMap<String, String>();
+
+ public NamespaceContext() {
+ }
+
+ public NamespaceContext(String prefix, String uri) {
+ nsMap.put(prefix, uri);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * javax.xml.namespace.NamespaceContext#getNamespaceURI(java.lang.String)
+ */
+ public String getNamespaceURI(String prefix) {
+ return nsMap.get(prefix);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.xml.namespace.NamespaceContext#getPrefix(java.lang.String)
+ */
+ public String getPrefix(String namespaceURI) {
+ for (String key : nsMap.keySet()) {
+ String value = nsMap.get(key);
+ if (value.equals(namespaceURI)) {
+ return key;
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.xml.namespace.NamespaceContext#getPrefixes(java.lang.String)
+ */
+ public Iterator<String> getPrefixes(String namespaceURI) {
+ return nsMap.keySet().iterator();
+ }
+
+ public NamespaceContext addNsUriPair(String ns, String uri) {
+ nsMap.put(ns, uri);
+ return this;
+ }
+
+ /**
+ * Create new NamespaceContext for use.
+ *
+ * @return
+ */
+ public static NamespaceContext create() {
+ return new NamespaceContext();
+ }
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/ProvidersUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/ProvidersUtil.java
new file mode 100755
index 0000000..cf6ec6f
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/ProvidersUtil.java
@@ -0,0 +1,127 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.security.Security;
+
+/**
+ * Utility dealing with the Santuario (XMLSec) providers registration for PicketLink
+ *
+ * @author alessio.soldano@jboss.com
+ * @since 07-May-2012
+ */
+public class ProvidersUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * No-op call such that the default system properties are set
+ */
+ public static synchronized void ensure() {
+ AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ public Boolean run() {
+ // register Apache Santuario 1.5.x XMLDSig version
+ addXMLDSigRI();
+ // register BC provider if available (to have additional encryption algorithms, etc.)
+ addJceProvider("BC", "org.bouncycastle.jce.provider.BouncyCastleProvider");
+ return true;
+ }
+ });
+ }
+
+ private static void addXMLDSigRI() {
+ try {
+ Class<?> clazz = SecurityActions
+ .loadClass(XMLSignatureUtil.class, "org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI");
+ if (clazz == null)
+ throw logger.classNotLoadedError("org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI");
+ addJceProvider("ApacheXMLDSig", (Provider) clazz.newInstance());
+ } catch (Throwable t) {
+ // ignore - may be a NoClassDefFound if XMLDSigRI isn't avail
+ return;
+ }
+ }
+
+ /**
+ * Add a new JCE security provider to use for PicketLink.
+ *
+ * @param name The name string of the provider (this may not be the real name of the provider)
+ * @param provider A subclass of <code>java.security.Provider</code>
+ *
+ * @return Returns the actual name of the provider that was loaded
+ */
+ private static String addJceProvider(String name, Provider provider) {
+ Provider currentProvider = Security.getProvider(name);
+ if (currentProvider == null) {
+ try {
+ //
+ // Install the provider after the SUN provider (see WSS-99)
+ // Otherwise fall back to the old behaviour of inserting
+ // the provider in position 2. For AIX, install it after
+ // the IBMJCE provider.
+ //
+ int ret = 0;
+ Provider[] provs = Security.getProviders();
+ for (int i = 0; i < provs.length; i++) {
+ if ("SUN".equals(provs[i].getName()) || "IBMJCE".equals(provs[i].getName())) {
+ ret = Security.insertProviderAt(provider, i + 2);
+ break;
+ }
+ }
+ if (ret == 0) {
+ ret = Security.insertProviderAt(provider, 2);
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("The provider " + provider.getName() + " - " + provider.getVersion() + " was added at position: "
+ + ret);
+ }
+ return provider.getName();
+ } catch (Throwable t) {
+ if (logger.isDebugEnabled()) {
+ logger.jceProviderCouldNotBeLoaded(name, t);
+ }
+ return null;
+ }
+ }
+ return currentProvider.getName();
+ }
+
+ private static String addJceProvider(String name, String className) {
+ Provider currentProvider = Security.getProvider(name);
+ if (currentProvider == null) {
+ try {
+ // Class<? extends Provider> clazz = Loader.loadClass(className, false, Provider.class);
+ Class<? extends Provider> clazz = Class.forName(className).asSubclass(Provider.class);
+ Provider provider = clazz.newInstance();
+ return addJceProvider(name, provider);
+ } catch (Throwable t) {
+ if (logger.isDebugEnabled()) {
+ logger.jceProviderCouldNotBeLoaded(name, t);
+ }
+ return null;
+ }
+ }
+ return currentProvider.getName();
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SchemaManagerUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SchemaManagerUtil.java
new file mode 100755
index 0000000..758133d
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SchemaManagerUtil.java
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages the schemas for PicketLink
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jun 30, 2011
+ */
+public class SchemaManagerUtil {
+
+ public static List<String> getXMLSchemas() {
+ List<String> list = new ArrayList<String>();
+
+ list.add("schema/w3c/xmlschema/xml.xsd");
+ return list;
+ }
+
+ public static List<String> getXMLDSig() {
+ List<String> list = new ArrayList<String>();
+
+ list.add("schema/w3c/xmldsig/xmldsig-core-schema.xsd");
+ return list;
+ }
+
+ public static List<String> getXMLEnc() {
+ List<String> list = new ArrayList<String>();
+
+ list.add("schema/w3c/xmlenc/xenc-schema.xsd");
+ return list;
+ }
+
+ public static List<String> getXACMLSchemas() {
+ List<String> list = new ArrayList<String>();
+
+ list.add("schema/access_control-xacml-2.0-policy-schema-os.xsd");
+ list.add("schema/access_control-xacml-2.0-context-schema-os.xsd");
+ return list;
+ }
+
+ public static List<String> getSAML2Schemas() {
+ List<String> list = new ArrayList<String>();
+
+ list.add("schema/saml/v2/saml-schema-assertion-2.0.xsd");
+ list.add("schema/saml/v2/saml-schema-protocol-2.0.xsd");
+ list.add("schema/saml/v2/saml-schema-metadata-2.0.xsd");
+ list.add("schema/saml/v2/saml-schema-x500-2.0.xsd");
+ list.add("schema/saml/v2/saml-schema-authn-context-2.0.xsd");
+ list.add("schema/saml/v2/saml-schema-authn-context-types-2.0.xsd");
+ list.add("schema/saml/v2/saml-schema-xacml-2.0.xsd");
+ list.add("schema/saml/v2/access_control-xacml-2.0-saml-assertion-schema-os.xsd");
+ list.add("schema/saml/v2/access_control-xacml-2.0-saml-protocol-schema-os.xsd");
+ return list;
+ }
+
+ public static List<String> getSAML11Schemas() {
+ List<String> list = new ArrayList<String>();
+
+ list.add("schema/saml/v1/saml-schema-assertion-1.0.xsd");
+ list.add("schema/saml/v1/oasis-sstc-saml-schema-assertion-1.1.xsd");
+ list.add("schema/saml/v1/saml-schema-protocol-1.1.xsd");
+ return list;
+ }
+
+ public static List<String> getWSTrustSchemas() {
+ List<String> list = new ArrayList<String>();
+
+ list.add("schema/wstrust/v1_3/ws-trust-1.3.xsd");
+ list.add("schema/wstrust/v1_3/oasis-200401-wss-wssecurity-secext-1.0.xsd");
+ list.add("schema/wstrust/v1_3/oasis-200401-wss-wssecurity-utility-1.0.xsd");
+ list.add("schema/wstrust/v1_3/ws-policy.xsd");
+ list.add("schema/wstrust/v1_3/ws-addr.xsd");
+ return list;
+ }
+
+ public static List<String> getSchemas() {
+ List<String> list = new ArrayList<String>();
+ list.addAll(getXMLSchemas());
+ list.addAll(getXMLDSig());
+ list.addAll(getXMLEnc());
+ list.addAll(getSAML2Schemas());
+ list.addAll(getSAML11Schemas());
+ list.addAll(getXACMLSchemas());
+ list.addAll(getWSTrustSchemas());
+ return list;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SecurityActions.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SecurityActions.java
new file mode 100755
index 0000000..d7c5382
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SecurityActions.java
@@ -0,0 +1,225 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 9, 2008
+ */
+class SecurityActions {
+
+ /**
+ * <p>
+ * Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
+ * the
+ * specified {@link Class}, if not found it will try to load from using TCL.
+ * </p>
+ *
+ * @param theClass
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ });
+ } else {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ }
+
+ /**
+ * <p>
+ * Loads a class from the specified {@link ClassLoader} using the <code>fullQualifiedName</code> supplied.
+ * </p>
+ *
+ * @param classLoader
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ });
+ } else {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Load a resource based on the passed {@link Class} classloader. Failing which try with the Thread Context CL
+ *
+ * @param clazz
+ * @param resourceName
+ *
+ * @return
+ */
+ static URL loadResource(final Class<?> clazz, final String resourceName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<URL>() {
+ public URL run() {
+ URL url = null;
+ ClassLoader clazzLoader = clazz.getClassLoader();
+ url = clazzLoader.getResource(resourceName);
+
+ if (url == null) {
+ clazzLoader = Thread.currentThread().getContextClassLoader();
+ url = clazzLoader.getResource(resourceName);
+ }
+
+ return url;
+ }
+ });
+ } else {
+ URL url = null;
+ ClassLoader clazzLoader = clazz.getClassLoader();
+ url = clazzLoader.getResource(resourceName);
+
+ if (url == null) {
+ clazzLoader = Thread.currentThread().getContextClassLoader();
+ url = clazzLoader.getResource(resourceName);
+ }
+
+ return url;
+ }
+ }
+
+ /**
+ * Set the system property
+ *
+ * @param key
+ * @param defaultValue
+ *
+ * @return
+ */
+ static void setSystemProperty(final String key, final String value) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ System.setProperty(key, value);
+ return null;
+ }
+ });
+ } else {
+ System.setProperty(key, value);
+ }
+ }
+
+ /**
+ * <p>Returns a system property value using the specified <code>key</code>. If not found the
+ * <code>defaultValue</code> will be returned.</p>
+ *
+ * @param key
+ * @param defaultValue
+ *
+ * @return
+ */
+ static String getSystemProperty(final String key, final String defaultValue) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(key, defaultValue);
+ }
+ });
+ } else {
+ return System.getProperty(key, defaultValue);
+ }
+ }
+
+ /**
+ * Get the Thread Context ClassLoader
+ *
+ * @return
+ */
+ static ClassLoader getTCCL() {
+ if (System.getSecurityManager() != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ } else {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ }
+
+ /**
+ * Set the Thread Context ClassLoader
+ *
+ * @param paramCl
+ */
+ static void setTCCL(final ClassLoader paramCl) {
+ if (System.getSecurityManager() != null) {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ Thread.currentThread().setContextClassLoader(paramCl);
+ return null;
+ }
+ });
+ } else {
+
+ Thread.currentThread().setContextClassLoader(paramCl);
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SignatureUtilTransferObject.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SignatureUtilTransferObject.java
new file mode 100755
index 0000000..96e3f69
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/SignatureUtilTransferObject.java
@@ -0,0 +1,115 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.util;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.security.KeyPair;
+import java.security.cert.X509Certificate;
+
+/**
+ * A Transfer Object used by {@link XMLSignatureUtil}
+ *
+ * @author anil saldhana
+ */
+public class SignatureUtilTransferObject {
+
+ private X509Certificate x509Certificate;
+
+ private Document documentToBeSigned;
+ private KeyPair keyPair;
+
+ private Node nextSibling;
+
+ private String digestMethod;
+
+ private String referenceURI;
+
+ private String signatureMethod;
+
+ public Document getDocumentToBeSigned() {
+ return documentToBeSigned;
+ }
+
+ public void setDocumentToBeSigned(Document documentToBeSigned) {
+ this.documentToBeSigned = documentToBeSigned;
+ }
+
+ public KeyPair getKeyPair() {
+ return keyPair;
+ }
+
+ public void setKeyPair(KeyPair keyPair) {
+ this.keyPair = keyPair;
+ }
+
+ public Node getNextSibling() {
+ return nextSibling;
+ }
+
+ public void setNextSibling(Node nextSibling) {
+ this.nextSibling = nextSibling;
+ }
+
+ public String getDigestMethod() {
+ return digestMethod;
+ }
+
+ public void setDigestMethod(String digestMethod) {
+ this.digestMethod = digestMethod;
+ }
+
+ public String getReferenceURI() {
+ return referenceURI;
+ }
+
+ public void setReferenceURI(String referenceURI) {
+ this.referenceURI = referenceURI;
+ }
+
+ public String getSignatureMethod() {
+ return signatureMethod;
+ }
+
+ public void setSignatureMethod(String signatureMethod) {
+ this.signatureMethod = signatureMethod;
+ }
+
+ /**
+ * Get the {@link X509Certificate} used for signing
+ *
+ * @return
+ *
+ * @since 2.5.0
+ */
+ public X509Certificate getX509Certificate() {
+ return x509Certificate;
+ }
+
+ /**
+ * Set the {@link X509Certificate} used for signing
+ *
+ * @param x509Certificate
+ *
+ * @since 2.5.0
+ */
+ public void setX509Certificate(X509Certificate x509Certificate) {
+ this.x509Certificate = x509Certificate;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/web/util/PostBindingUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/web/util/PostBindingUtil.java
new file mode 100755
index 0000000..3cf658a
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/web/util/PostBindingUtil.java
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.saml.processing.web.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.saml.common.util.Base64;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Utility for the HTTP/Post binding
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since May 22, 2009
+ */
+public class PostBindingUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * Apply base64 encoding on the message
+ *
+ * @param stringToEncode
+ *
+ * @return
+ */
+ public static String base64Encode(String stringToEncode) throws IOException {
+ return Base64.encodeBytes(stringToEncode.getBytes("UTF-8"), Base64.DONT_BREAK_LINES);
+ }
+
+ /**
+ * Apply base64 decoding on the message and return the byte array
+ *
+ * @param encodedString
+ *
+ * @return
+ */
+ public static byte[] base64Decode(String encodedString) {
+ if (encodedString == null)
+ throw logger.nullArgumentError("encodedString");
+
+ return Base64.decode(encodedString);
+ }
+
+ /**
+ * Apply base64 decoding on the message and return the stream
+ *
+ * @param encodedString
+ *
+ * @return
+ */
+ public static InputStream base64DecodeAsStream(String encodedString) {
+ if (encodedString == null)
+ throw logger.nullArgumentError("encodedString");
+
+ return new ByteArrayInputStream(base64Decode(encodedString));
+ }
+
+ public static String escapeHTML(String toEscape) {
+ StringBuilder escaped = new StringBuilder();
+
+ for (int i = 0; i < toEscape.length(); i++) {
+ char chr = toEscape.charAt(i);
+
+ if (chr != '"' && chr != '<' && chr != '>') {
+ escaped.append(chr);
+ }
+ }
+
+ return escaped.toString();
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/web/util/RedirectBindingSignatureUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/web/util/RedirectBindingSignatureUtil.java
new file mode 100755
index 0000000..a9c3765
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/web/util/RedirectBindingSignatureUtil.java
@@ -0,0 +1,345 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.web.util;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.saml.common.constants.GeneralConstants;
+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.util.DocumentUtil;
+import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
+import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.saml.v2.util.SignatureUtil;
+import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.security.GeneralSecurityException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import static org.keycloak.saml.common.util.StringUtil.isNotNull;
+
+/**
+ * Signature Support for the HTTP/Redirect binding
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 16, 2008
+ */
+public class RedirectBindingSignatureUtil {
+
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ /**
+ * Get the URL for the SAML request that contains the signature and signature algorithm
+ *
+ * @param authRequest
+ * @param relayState
+ * @param signingKey
+ *
+ * @return
+ *
+ * @throws SAXException
+ * @throws IOException
+ * @throws GeneralSecurityException
+ */
+ public static String getSAMLRequestURLWithSignature(AuthnRequestType authRequest, String relayState, PrivateKey signingKey)
+ throws SAXException, IOException, GeneralSecurityException {
+ SAML2Request saml2Request = new SAML2Request();
+
+ // Deal with the original request
+ StringWriter sw = new StringWriter();
+
+ saml2Request.marshall(authRequest, sw);
+
+ // URL Encode the Request
+ String urlEncodedRequest = RedirectBindingUtil.deflateBase64URLEncode(sw.toString());
+
+ String urlEncodedRelayState = null;
+
+ if (isNotNull(relayState))
+ urlEncodedRelayState = URLEncoder.encode(relayState, "UTF-8");
+
+ byte[] sigValue = computeSignature(GeneralConstants.SAML_REQUEST_KEY, urlEncodedRequest, urlEncodedRelayState,
+ signingKey);
+
+ // Now construct the URL
+ return getRequestRedirectURLWithSignature(urlEncodedRequest, urlEncodedRelayState, sigValue, signingKey.getAlgorithm());
+ }
+
+ /**
+ * Get the URL for the SAML request that contains the signature and signature algorithm
+ *
+ * @param responseType
+ * @param relayState
+ * @param signingKey
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws GeneralSecurityException
+ */
+ public static String getSAMLResponseURLWithSignature(ResponseType responseType, String relayState, PrivateKey signingKey)
+ throws IOException, GeneralSecurityException {
+ SAML2Response saml2Response = new SAML2Response();
+
+ Document responseDoc = saml2Response.convert(responseType);
+
+ // URL Encode the Request
+ String responseString = DocumentUtil.getDocumentAsString(responseDoc);
+
+ String urlEncodedResponse = RedirectBindingUtil.deflateBase64URLEncode(responseString);
+
+ String urlEncodedRelayState = null;
+ if (isNotNull(relayState))
+ urlEncodedRelayState = URLEncoder.encode(relayState, "UTF-8");
+
+ byte[] sigValue = computeSignature(GeneralConstants.SAML_RESPONSE_KEY, urlEncodedResponse, urlEncodedRelayState,
+ signingKey);
+
+ // Now construct the URL
+ return getResponseRedirectURLWithSignature(urlEncodedResponse, urlEncodedRelayState, sigValue,
+ signingKey.getAlgorithm());
+ }
+
+ /**
+ * Given an url-encoded saml request and relay state and a private key, compute the url
+ *
+ * @param urlEncodedRequest
+ * @param urlEncodedRelayState
+ * @param signingKey
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ public static String getSAMLRequestURLWithSignature(String urlEncodedRequest, String urlEncodedRelayState,
+ PrivateKey signingKey) throws IOException, GeneralSecurityException {
+ byte[] sigValue = computeSignature(GeneralConstants.SAML_REQUEST_KEY, urlEncodedRequest, urlEncodedRelayState,
+ signingKey);
+ return getRequestRedirectURLWithSignature(urlEncodedRequest, urlEncodedRelayState, sigValue, signingKey.getAlgorithm());
+ }
+
+ /**
+ * Given an url-encoded saml response and relay state and a private key, compute the url
+ *
+ * @param urlEncodedResponse
+ * @param urlEncodedRelayState
+ * @param signingKey
+ *
+ * @return
+ *
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ public static String getSAMLResponseURLWithSignature(String urlEncodedResponse, String urlEncodedRelayState,
+ PrivateKey signingKey) throws IOException, GeneralSecurityException {
+ byte[] sigValue = computeSignature(GeneralConstants.SAML_RESPONSE_KEY, urlEncodedResponse, urlEncodedRelayState,
+ signingKey);
+ return getResponseRedirectURLWithSignature(urlEncodedResponse, urlEncodedRelayState, sigValue,
+ signingKey.getAlgorithm());
+ }
+
+ /**
+ * From the SAML Request URL, get the Request object
+ *
+ * @param signedURL
+ *
+ * @return
+ *
+ * @throws IOException
+ * @throws ParsingException
+ * @throws org.keycloak.saml.common.exceptions.ProcessingException
+ * @throws ConfigurationException
+ */
+ public static AuthnRequestType getRequestFromSignedURL(String signedURL) throws ConfigurationException,
+ ProcessingException, ParsingException, IOException {
+ String samlRequestTokenValue = getTokenValue(signedURL, GeneralConstants.SAML_REQUEST_KEY);
+
+ SAML2Request saml2Request = new SAML2Request();
+ return saml2Request.getAuthnRequestType(RedirectBindingUtil.urlBase64DeflateDecode(samlRequestTokenValue));
+ }
+
+ /**
+ * Get the signature value from the url
+ *
+ * @param signedURL
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static byte[] getSignatureValueFromSignedURL(String signedURL) throws IOException {
+ String sigValueTokenValue = getTokenValue(signedURL, GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
+ if (sigValueTokenValue == null)
+ throw new IllegalStateException(logger.samlHandlerSignatureNotPresentError());
+ return RedirectBindingUtil.urlBase64Decode(sigValueTokenValue);
+ }
+
+ /**
+ * From the query string that contains key/value pairs, get the value of a key <b>Note:</b> if the token is null, a
+ * null
+ * value is returned
+ *
+ * @param queryString
+ * @param token
+ *
+ * @return
+ */
+ public static String getTokenValue(String queryString, String token) {
+ return getTokenValue(getToken(queryString, token));
+ }
+
+ public static boolean validateSignature(String queryString, PublicKey validatingKey, byte[] sigValue)
+ throws UnsupportedEncodingException, GeneralSecurityException {
+ // Construct the url again
+ StringBuilder sb = new StringBuilder();
+
+ if (isRequestQueryString(queryString)) {
+ addParameter(sb, GeneralConstants.SAML_REQUEST_KEY,
+ RedirectBindingSignatureUtil.getTokenValue(queryString, GeneralConstants.SAML_REQUEST_KEY));
+ } else {
+ addParameter(sb, GeneralConstants.SAML_RESPONSE_KEY,
+ RedirectBindingSignatureUtil.getTokenValue(queryString, GeneralConstants.SAML_RESPONSE_KEY));
+ }
+
+ String relayStateFromURL = RedirectBindingSignatureUtil.getTokenValue(queryString, GeneralConstants.RELAY_STATE);
+
+ if (isNotNull(relayStateFromURL)) {
+ addParameter(sb, GeneralConstants.RELAY_STATE, relayStateFromURL);
+ }
+
+ addParameter(sb, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY,
+ RedirectBindingSignatureUtil.getTokenValue(queryString, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY));
+
+ return SignatureUtil.validate(sb.toString().getBytes("UTF-8"), sigValue, validatingKey);
+ }
+
+ private static boolean isRequestQueryString(String queryString) {
+ return RedirectBindingSignatureUtil.getTokenValue(queryString, GeneralConstants.SAML_REQUEST_KEY) != null;
+ }
+
+ // ***************** Private Methods **************
+
+ private static byte[] computeSignature(String samlParameter, String urlEncoded, String urlEncodedRelayState,
+ PrivateKey signingKey) throws IOException, GeneralSecurityException {
+ StringBuilder sb = new StringBuilder();
+
+ addParameter(sb, samlParameter, urlEncoded);
+
+ if (isNotNull(urlEncodedRelayState)) {
+ addParameter(sb, GeneralConstants.RELAY_STATE, urlEncodedRelayState);
+ }
+
+ // SigAlg
+ String algo = signingKey.getAlgorithm();
+ String sigAlg = SignatureUtil.getXMLSignatureAlgorithmURI(algo);
+
+ sigAlg = URLEncoder.encode(sigAlg, "UTF-8");
+
+ addParameter(sb, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, sigAlg);
+
+ byte[] sigValue = SignatureUtil.sign(sb.toString(), signingKey);
+
+ return sigValue;
+ }
+
+ private static String getRequestRedirectURLWithSignature(String urlEncodedRequest, String urlEncodedRelayState,
+ byte[] signature, String sigAlgo) throws IOException {
+ return getRedirectURLWithSignature(GeneralConstants.SAML_REQUEST_KEY, urlEncodedRequest, urlEncodedRelayState,
+ signature, sigAlgo);
+ }
+
+ private static String getResponseRedirectURLWithSignature(String urlEncodedResponse, String urlEncodedRelayState,
+ byte[] signature, String sigAlgo) throws IOException {
+ return getRedirectURLWithSignature(GeneralConstants.SAML_RESPONSE_KEY, urlEncodedResponse, urlEncodedRelayState,
+ signature, sigAlgo);
+ }
+
+ private static String getRedirectURLWithSignature(String samlParameter, String urlEncoded, String urlEncodedRelayState,
+ byte[] signature, String sigAlgo) throws IOException {
+ StringBuilder sb = new StringBuilder();
+
+ addParameter(sb, samlParameter, urlEncoded);
+
+ if (isNotNull(urlEncodedRelayState)) {
+ addParameter(sb, GeneralConstants.RELAY_STATE, urlEncodedRelayState);
+ }
+
+ // SigAlg
+ String sigAlg = SignatureUtil.getXMLSignatureAlgorithmURI(sigAlgo);
+
+ sigAlg = URLEncoder.encode(sigAlg, "UTF-8");
+
+ addParameter(sb, GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, sigAlg);
+
+ // Encode the signature value
+ String encodedSig = RedirectBindingUtil.base64URLEncode(signature);
+
+ addParameter(sb, GeneralConstants.SAML_SIGNATURE_REQUEST_KEY, encodedSig);
+
+ return sb.toString();
+ }
+
+ private static void addParameter(StringBuilder queryString, String paramName, String paramValue) {
+ String parameterSeparator = "&";
+
+ if (queryString.length() == 0) {
+ parameterSeparator = "";
+ }
+
+ queryString.append(parameterSeparator).append(paramName).append("=").append(paramValue);
+ }
+
+ private static String getToken(String queryString, String token) {
+ if (queryString == null)
+ throw logger.nullArgumentError("queryString");
+
+ token += "=";
+
+ int start = queryString.indexOf(token);
+ if (start < 0)
+ return null;
+
+ int end = queryString.indexOf("&", start);
+
+ if (end == -1)
+ return queryString.substring(start);
+
+ return queryString.substring(start, end);
+ }
+
+ private static String getTokenValue(String token) {
+ if (token == null)
+ return token;
+
+ int eq = token.indexOf('=');
+ if (eq == -1)
+ return token;
+ else
+ return token.substring(eq + 1);
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/web/util/RedirectBindingUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/web/util/RedirectBindingUtil.java
new file mode 100755
index 0000000..0e1c7f7
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/web/util/RedirectBindingUtil.java
@@ -0,0 +1,219 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.web.util;
+
+import org.keycloak.saml.common.util.Base64;
+import org.keycloak.saml.processing.api.util.DeflateUtil;
+import org.keycloak.saml.common.util.StringUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+/**
+ * Utility class for SAML HTTP/Redirect binding
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Jan 14, 2009
+ */
+public class RedirectBindingUtil {
+
+ /**
+ * URL encode the string
+ *
+ * @param str
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static String urlEncode(String str) throws IOException {
+ return URLEncoder.encode(str, "UTF-8");
+ }
+
+ /**
+ * URL decode the string
+ *
+ * @param str
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static String urlDecode(String str) throws IOException {
+ return URLDecoder.decode(str, "UTF-8");
+ }
+
+ /**
+ * On the byte array, apply base64 encoding following by URL encoding
+ *
+ * @param stringToEncode
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static String base64URLEncode(byte[] stringToEncode) throws IOException {
+ String base64Request = Base64.encodeBytes(stringToEncode, Base64.DONT_BREAK_LINES);
+ return urlEncode(base64Request);
+ }
+
+ /**
+ * On the byte array, apply URL decoding followed by base64 decoding
+ *
+ * @param encodedString
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static byte[] urlBase64Decode(String encodedString) throws IOException {
+ String decodedString = urlDecode(encodedString);
+ return Base64.decode(decodedString);
+ }
+
+ /**
+ * Apply deflate compression followed by base64 encoding and URL encoding
+ *
+ * @param stringToEncode
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static String deflateBase64URLEncode(String stringToEncode) throws IOException {
+ return deflateBase64URLEncode(stringToEncode.getBytes("UTF-8"));
+ }
+
+ /**
+ * Apply deflate compression followed by base64 encoding and URL encoding
+ *
+ * @param stringToEncode
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static String deflateBase64URLEncode(byte[] stringToEncode) throws IOException {
+ byte[] deflatedMsg = DeflateUtil.encode(stringToEncode);
+ return base64URLEncode(deflatedMsg);
+ }
+
+ /**
+ * Apply deflate compression followed by base64 encoding
+ *
+ * @param stringToEncode
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static String deflateBase64Encode(byte[] stringToEncode) throws IOException {
+ byte[] deflatedMsg = DeflateUtil.encode(stringToEncode);
+ return Base64.encodeBytes(deflatedMsg);
+ }
+
+ /**
+ * Apply URL decoding, followed by base64 decoding followed by deflate decompression
+ *
+ * @param encodedString
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static InputStream urlBase64DeflateDecode(String encodedString) throws IOException {
+ byte[] deflatedString = urlBase64Decode(encodedString);
+ return DeflateUtil.decode(deflatedString);
+ }
+
+ /**
+ * Base64 decode followed by Deflate decoding
+ *
+ * @param encodedString
+ *
+ * @return
+ */
+ public static InputStream base64DeflateDecode(String encodedString) {
+ byte[] base64decodedMsg = Base64.decode(encodedString);
+ return DeflateUtil.decode(base64decodedMsg);
+ }
+
+ /**
+ * Get the Query String for the destination url
+ *
+ * @param urlEncodedRequest
+ * @param urlEncodedRelayState
+ * @param sendRequest either going to be saml request or response
+ *
+ * @return
+ */
+ public static String getDestinationQueryString(String urlEncodedRequest, String urlEncodedRelayState, boolean sendRequest) {
+ StringBuilder sb = new StringBuilder();
+ if (sendRequest)
+ sb.append("SAMLRequest=").append(urlEncodedRequest);
+ else
+ sb.append("SAMLResponse=").append(urlEncodedRequest);
+ if (StringUtil.isNotNull(urlEncodedRelayState))
+ sb.append("&RelayState=").append(urlEncodedRelayState);
+ return sb.toString();
+ }
+
+ /**
+ * Get the destination url
+ *
+ * @param holder
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ public static String getDestinationURL(RedirectBindingUtilDestHolder holder) throws IOException {
+ String destination = holder.destination;
+ StringBuilder destinationURL = new StringBuilder(destination);
+
+ if (destination.contains("?"))
+ destinationURL.append("&");
+ else
+ destinationURL.append("?");
+
+ destinationURL.append(holder.destinationQueryString);
+
+ return destinationURL.toString();
+ }
+
+ /**
+ * A Destination holder that holds the destination host url and the destination query string
+ */
+ public static class RedirectBindingUtilDestHolder {
+
+ private String destination;
+ private String destinationQueryString;
+
+ public RedirectBindingUtilDestHolder setDestinationQueryString(String dest) {
+ destinationQueryString = dest;
+ return this;
+ }
+
+ public RedirectBindingUtilDestHolder setDestination(String dest) {
+ destination = dest;
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/web/util/SecurityActions.java b/saml-core/src/main/java/org/keycloak/saml/processing/web/util/SecurityActions.java
new file mode 100755
index 0000000..a5411c9
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/web/util/SecurityActions.java
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.web.util;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author Anil.Saldhana@redhat.com
+ * @since Dec 9, 2008
+ */
+class SecurityActions {
+
+ /**
+ * <p>
+ * Loads a {@link Class} using the <code>fullQualifiedName</code> supplied. This method tries first to load from
+ * the
+ * specified {@link Class}, if not found it will try to load from using TCL.
+ * </p>
+ *
+ * @param theClass
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final Class<?> theClass, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ });
+ } else {
+ ClassLoader classLoader = theClass.getClassLoader();
+
+ Class<?> clazz = loadClass(classLoader, fullQualifiedName);
+ if (clazz == null) {
+ classLoader = Thread.currentThread().getContextClassLoader();
+ clazz = loadClass(classLoader, fullQualifiedName);
+ }
+ return clazz;
+ }
+ }
+
+ /**
+ * <p>
+ * Loads a class from the specified {@link ClassLoader} using the <code>fullQualifiedName</code> supplied.
+ * </p>
+ *
+ * @param classLoader
+ * @param fullQualifiedName
+ *
+ * @return
+ */
+ static Class<?> loadClass(final ClassLoader classLoader, final String fullQualifiedName) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+ public Class<?> run() {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ });
+ } else {
+ try {
+ return classLoader.loadClass(fullQualifiedName);
+ } catch (ClassNotFoundException e) {
+ }
+ return null;
+ }
+ }
+
+ /**
+ * <p>Returns a system property value using the specified <code>key</code>. If not found the
+ * <code>defaultValue</code> will be returned.</p>
+ *
+ * @param key
+ * @param defaultValue
+ *
+ * @return
+ */
+ static String getSystemProperty(final String key, final String defaultValue) {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null) {
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty(key, defaultValue);
+ }
+ });
+ } else {
+ return System.getProperty(key, defaultValue);
+ }
+ }
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/RandomSecret.java b/saml-core/src/main/java/org/keycloak/saml/RandomSecret.java
new file mode 100755
index 0000000..67f4ba7
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/RandomSecret.java
@@ -0,0 +1,25 @@
+package org.keycloak.saml;
+
+import java.security.SecureRandom;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RandomSecret {
+ /**
+ * <p>
+ * Creates a random {@code byte[]} secret of the specified size.
+ * </p>
+ *
+ * @param size the size of the secret to be created, in bytes.
+ *
+ * @return a {@code byte[]} containing the generated secret.
+ */
+ public static byte[] createRandomSecret(final int size) {
+ SecureRandom random = new SecureRandom();
+ byte[] secret = new byte[size];
+ random.nextBytes(secret);
+ return secret;
+ }
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2AuthnRequestBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2AuthnRequestBuilder.java
new file mode 100755
index 0000000..b043a12
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/SAML2AuthnRequestBuilder.java
@@ -0,0 +1,99 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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;
+
+import java.net.URI;
+
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
+import org.keycloak.saml.common.exceptions.ConfigurationException;
+import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
+import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.w3c.dom.Document;
+
+/**
+ * @author pedroigor
+ */
+public class SAML2AuthnRequestBuilder {
+
+ private final AuthnRequestType authnRequestType;
+ protected String destination;
+ protected String issuer;
+
+ public SAML2AuthnRequestBuilder destination(String destination) {
+ this.destination = destination;
+ return this;
+ }
+
+ public SAML2AuthnRequestBuilder issuer(String issuer) {
+ this.issuer = issuer;
+ return this;
+ }
+
+ public SAML2AuthnRequestBuilder() {
+ try {
+ this.authnRequestType = new AuthnRequestType(IDGenerator.create("ID_"), XMLTimeUtil.getIssueInstant());
+ } catch (ConfigurationException e) {
+ throw new RuntimeException("Could not create SAML AuthnRequest builder.", e);
+ }
+ }
+
+ public SAML2AuthnRequestBuilder assertionConsumerUrl(String assertionConsumerUrl) {
+ this.authnRequestType.setAssertionConsumerServiceURL(URI.create(assertionConsumerUrl));
+ return this;
+ }
+
+ public SAML2AuthnRequestBuilder forceAuthn(boolean forceAuthn) {
+ this.authnRequestType.setForceAuthn(forceAuthn);
+ return this;
+ }
+
+ public SAML2AuthnRequestBuilder isPassive(boolean isPassive) {
+ this.authnRequestType.setIsPassive(isPassive);
+ return this;
+ }
+
+ public SAML2AuthnRequestBuilder nameIdPolicy(SAML2NameIDPolicyBuilder nameIDPolicy) {
+ this.authnRequestType.setNameIDPolicy(nameIDPolicy.build());
+ return this;
+ }
+
+ public SAML2AuthnRequestBuilder protocolBinding(String protocolBinding) {
+ this.authnRequestType.setProtocolBinding(URI.create(protocolBinding));
+ return this;
+ }
+
+ public Document toDocument() {
+ try {
+ AuthnRequestType authnRequestType = this.authnRequestType;
+
+ NameIDType nameIDType = new NameIDType();
+
+ nameIDType.setValue(this.issuer);
+
+ authnRequestType.setIssuer(nameIDType);
+
+ authnRequestType.setDestination(URI.create(this.destination));
+
+ return new SAML2Request().convert(authnRequestType);
+ } catch (Exception e) {
+ throw new RuntimeException("Could not convert " + authnRequestType + " to a document.", e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2ErrorResponseBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2ErrorResponseBuilder.java
new file mode 100755
index 0000000..2373656
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/SAML2ErrorResponseBuilder.java
@@ -0,0 +1,72 @@
+package org.keycloak.saml;
+
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.protocol.StatusCodeType;
+import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
+import org.keycloak.dom.saml.v2.protocol.StatusType;
+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.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
+import org.keycloak.saml.processing.core.saml.v2.factories.JBossSAMLAuthnResponseFactory;
+import org.keycloak.saml.processing.core.saml.v2.holders.IDPInfoHolder;
+import org.keycloak.saml.processing.core.saml.v2.holders.IssuerInfoHolder;
+import org.keycloak.saml.processing.core.saml.v2.holders.SPInfoHolder;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.w3c.dom.Document;
+
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2ErrorResponseBuilder {
+
+ protected String status;
+ protected String destination;
+ protected String issuer;
+
+ public SAML2ErrorResponseBuilder status(String status) {
+ this.status = status;
+ return this;
+ }
+
+ public SAML2ErrorResponseBuilder destination(String destination) {
+ this.destination = destination;
+ return this;
+ }
+
+ public SAML2ErrorResponseBuilder issuer(String issuer) {
+ this.issuer = issuer;
+ return this;
+ }
+
+
+ public Document buildDocument() throws ProcessingException {
+
+ try {
+ StatusResponseType statusResponse = new StatusResponseType(IDGenerator.create("ID_"), XMLTimeUtil.getIssueInstant());
+
+ statusResponse.setStatus(JBossSAMLAuthnResponseFactory.createStatusTypeForResponder(status));
+ NameIDType issuer = new NameIDType();
+ issuer.setValue(this.issuer);
+
+ statusResponse.setIssuer(issuer);
+ statusResponse.setDestination(destination);
+
+ SAML2Response saml2Response = new SAML2Response();
+ return saml2Response.convert(statusResponse);
+ } catch (ConfigurationException e) {
+ throw new ProcessingException(e);
+ } catch (ParsingException e) {
+ throw new ProcessingException(e);
+ }
+
+ }
+
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2LoginResponseBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2LoginResponseBuilder.java
new file mode 100755
index 0000000..9ca5f67
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/SAML2LoginResponseBuilder.java
@@ -0,0 +1,195 @@
+package org.keycloak.saml;
+
+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.ConfigurationException;
+import org.keycloak.saml.common.exceptions.ProcessingException;
+import org.keycloak.saml.common.util.DocumentUtil;
+import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
+import org.keycloak.saml.processing.core.saml.v2.holders.IDPInfoHolder;
+import org.keycloak.saml.processing.core.saml.v2.holders.IssuerInfoHolder;
+import org.keycloak.saml.processing.core.saml.v2.holders.SPInfoHolder;
+import org.keycloak.saml.processing.core.saml.v2.util.StatementUtil;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
+import org.keycloak.dom.saml.v2.assertion.ConditionsType;
+import org.keycloak.dom.saml.v2.assertion.SubjectConfirmationDataType;
+import org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType;
+import org.keycloak.dom.saml.v2.protocol.ResponseType;
+import org.w3c.dom.Document;
+import java.net.URI;
+
+import static org.keycloak.saml.common.util.StringUtil.isNotNull;
+
+/**
+ * <p> Handles for dealing with SAML2 Authentication </p>
+ * <p/>
+ * Configuration Options:
+ *
+ * @author bburke@redhat.com
+*/
+public class SAML2LoginResponseBuilder {
+ protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ protected String destination;
+ protected String issuer;
+ protected int subjectExpiration;
+ protected int assertionExpiration;
+ protected String nameId;
+ protected String nameIdFormat;
+ protected boolean multiValuedRoles;
+ protected boolean disableAuthnStatement;
+ protected String requestID;
+ protected String authMethod;
+ protected String requestIssuer;
+ protected String sessionIndex;
+
+
+ public SAML2LoginResponseBuilder sessionIndex(String sessionIndex) {
+ this.sessionIndex = sessionIndex;
+ return this;
+ }
+
+ public SAML2LoginResponseBuilder destination(String destination) {
+ this.destination = destination;
+ return this;
+ }
+
+ public SAML2LoginResponseBuilder issuer(String issuer) {
+ this.issuer = issuer;
+ return this;
+ }
+
+ /**
+ * Length of time in seconds the subject can be confirmed
+ * See SAML core specification 2.4.1.2 NotOnOrAfter
+ *
+ * @param subjectExpiration Number of seconds the subject should be valid
+ * @return
+ */
+ public SAML2LoginResponseBuilder subjectExpiration(int subjectExpiration) {
+ this.subjectExpiration = subjectExpiration;
+ return this;
+ }
+
+ /**
+ * Length of time in seconds the assertion is valid for
+ * See SAML core specification 2.5.1.2 NotOnOrAfter
+ *
+ * @param assertionExpiration Number of seconds the assertion should be valid
+ * @return
+ */
+ public SAML2LoginResponseBuilder assertionExpiration(int assertionExpiration) {
+ this.assertionExpiration = assertionExpiration;
+ return this;
+ }
+
+ public SAML2LoginResponseBuilder requestID(String requestID) {
+ this.requestID =requestID;
+ return this;
+ }
+
+ public SAML2LoginResponseBuilder requestIssuer(String requestIssuer) {
+ this.requestIssuer =requestIssuer;
+ return this;
+ }
+
+ public SAML2LoginResponseBuilder authMethod(String authMethod) {
+ this.authMethod = authMethod;
+ return this;
+ }
+
+ public SAML2LoginResponseBuilder nameIdentifier(String nameIdFormat, String nameId) {
+ this.nameIdFormat = nameIdFormat;
+ this.nameId = nameId;
+ return this;
+ }
+
+ public SAML2LoginResponseBuilder multiValuedRoles(boolean multiValuedRoles) {
+ this.multiValuedRoles = multiValuedRoles;
+ return this;
+ }
+
+ public SAML2LoginResponseBuilder disableAuthnStatement(boolean disableAuthnStatement) {
+ this.disableAuthnStatement = disableAuthnStatement;
+ return this;
+ }
+
+ public Document buildDocument(ResponseType responseType) throws ConfigurationException, ProcessingException {
+ Document samlResponseDocument = null;
+
+ try {
+ SAML2Response docGen = new SAML2Response();
+ samlResponseDocument = docGen.convert(responseType);
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("SAML Response Document: " + DocumentUtil.asString(samlResponseDocument));
+ }
+ } catch (Exception e) {
+ throw logger.samlAssertionMarshallError(e);
+ }
+
+ return samlResponseDocument;
+ }
+
+ public ResponseType buildModel() throws ConfigurationException, ProcessingException {
+ ResponseType responseType = null;
+
+ SAML2Response saml2Response = new SAML2Response();
+
+ // Create a response type
+ String id = IDGenerator.create("ID_");
+
+ IssuerInfoHolder issuerHolder = new IssuerInfoHolder(issuer);
+ issuerHolder.setStatusCode(JBossSAMLURIConstants.STATUS_SUCCESS.get());
+
+ IDPInfoHolder idp = new IDPInfoHolder();
+ idp.setNameIDFormatValue(nameId);
+ idp.setNameIDFormat(nameIdFormat);
+
+ SPInfoHolder sp = new SPInfoHolder();
+ sp.setResponseDestinationURI(destination);
+ sp.setRequestID(requestID);
+ sp.setIssuer(requestIssuer);
+ responseType = saml2Response.createResponseType(id, sp, idp, issuerHolder);
+
+ AssertionType assertion = responseType.getAssertions().get(0).getAssertion();
+
+ //Add request issuer as the audience restriction
+ AudienceRestrictionType audience = new AudienceRestrictionType();
+ audience.addAudience(URI.create(requestIssuer));
+ assertion.getConditions().addCondition(audience);
+
+ //Update Conditions NotOnOrAfter
+ if(assertionExpiration > 0) {
+ ConditionsType conditions = assertion.getConditions();
+ conditions.setNotOnOrAfter(XMLTimeUtil.add(conditions.getNotBefore(), assertionExpiration * 1000));
+ }
+
+ //Update SubjectConfirmationData NotOnOrAfter
+ if(subjectExpiration > 0) {
+ SubjectConfirmationDataType subjectConfirmationData = assertion.getSubject().getConfirmation().get(0).getSubjectConfirmationData();
+ subjectConfirmationData.setNotOnOrAfter(XMLTimeUtil.add(assertion.getConditions().getNotBefore(), subjectExpiration * 1000));
+ }
+
+ // Create an AuthnStatementType
+ if (!disableAuthnStatement) {
+ String authContextRef = JBossSAMLURIConstants.AC_UNSPECIFIED.get();
+ if (isNotNull(authMethod))
+ authContextRef = authMethod;
+
+ AuthnStatementType authnStatement = StatementUtil.createAuthnStatement(XMLTimeUtil.getIssueInstant(),
+ authContextRef);
+ if (sessionIndex != null) authnStatement.setSessionIndex(sessionIndex);
+ else authnStatement.setSessionIndex(assertion.getID());
+
+ assertion.addStatement(authnStatement);
+ }
+
+ return responseType;
+ }
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutRequestBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutRequestBuilder.java
new file mode 100755
index 0000000..a1c7c7e
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutRequestBuilder.java
@@ -0,0 +1,87 @@
+package org.keycloak.saml;
+
+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.processing.api.saml.v2.request.SAML2Request;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
+import org.w3c.dom.Document;
+
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2LogoutRequestBuilder {
+ protected String userPrincipal;
+ protected String userPrincipalFormat;
+ protected String sessionIndex;
+ protected long assertionExpiration;
+ protected String destination;
+ protected String issuer;
+
+ public SAML2LogoutRequestBuilder destination(String destination) {
+ this.destination = destination;
+ return this;
+ }
+
+ public SAML2LogoutRequestBuilder issuer(String issuer) {
+ this.issuer = issuer;
+ return this;
+ }
+
+ /**
+ * Length of time in seconds the assertion is valid for
+ * See SAML core specification 2.5.1.2 NotOnOrAfter
+ *
+ * @param assertionExpiration Number of seconds the assertion should be valid
+ * @return
+ */
+ public SAML2LogoutRequestBuilder assertionExpiration(int assertionExpiration) {
+ this.assertionExpiration = assertionExpiration;
+ return this;
+ }
+
+
+ public SAML2LogoutRequestBuilder userPrincipal(String nameID, String nameIDformat) {
+ this.userPrincipal = nameID;
+ this.userPrincipalFormat = nameIDformat;
+ return this;
+ }
+
+ public SAML2LogoutRequestBuilder sessionIndex(String index) {
+ this.sessionIndex = index;
+ return this;
+ }
+
+ public Document buildDocument() throws ProcessingException, ConfigurationException, ParsingException {
+ Document document = new SAML2Request().convert(createLogoutRequest());
+ return document;
+ }
+
+ private LogoutRequestType createLogoutRequest() throws ConfigurationException {
+ LogoutRequestType lort = new SAML2Request().createLogoutRequest(issuer);
+
+ NameIDType nameID = new NameIDType();
+ nameID.setValue(userPrincipal);
+ //Deal with NameID Format
+ String nameIDFormat = userPrincipalFormat;
+ nameID.setFormat(URI.create(nameIDFormat));
+ lort.setNameID(nameID);
+
+ if (issuer != null) {
+ NameIDType issuerID = new NameIDType();
+ issuerID.setValue(issuer);
+ lort.setIssuer(issuerID);
+ }
+ if (sessionIndex != null) lort.addSessionIndex(sessionIndex);
+
+
+ if (assertionExpiration > 0) lort.setNotOnOrAfter(XMLTimeUtil.add(lort.getIssueInstant(), assertionExpiration * 1000));
+ lort.setDestination(URI.create(destination));
+ return lort;
+ }
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutResponseBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutResponseBuilder.java
new file mode 100755
index 0000000..6710f71
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/SAML2LogoutResponseBuilder.java
@@ -0,0 +1,75 @@
+package org.keycloak.saml;
+
+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.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
+import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
+import org.keycloak.dom.saml.v2.assertion.NameIDType;
+import org.keycloak.dom.saml.v2.protocol.StatusCodeType;
+import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
+import org.keycloak.dom.saml.v2.protocol.StatusType;
+import org.w3c.dom.Document;
+
+import java.net.URI;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAML2LogoutResponseBuilder {
+
+ protected String logoutRequestID;
+ protected String destination;
+ protected String issuer;
+
+ public SAML2LogoutResponseBuilder logoutRequestID(String logoutRequestID) {
+ this.logoutRequestID = logoutRequestID;
+ return this;
+ }
+
+ public SAML2LogoutResponseBuilder destination(String destination) {
+ this.destination = destination;
+ return this;
+ }
+
+ public SAML2LogoutResponseBuilder issuer(String issuer) {
+ this.issuer = issuer;
+ return this;
+ }
+
+
+ public Document buildDocument() throws ProcessingException {
+ Document samlResponse = null;
+ try {
+ StatusResponseType statusResponse = new StatusResponseType(IDGenerator.create("ID_"), XMLTimeUtil.getIssueInstant());
+
+ // Status
+ StatusType statusType = new StatusType();
+ StatusCodeType statusCodeType = new StatusCodeType();
+ statusCodeType.setValue(URI.create(JBossSAMLURIConstants.STATUS_SUCCESS.get()));
+ statusType.setStatusCode(statusCodeType);
+
+ statusResponse.setStatus(statusType);
+ statusResponse.setInResponseTo(logoutRequestID);
+ NameIDType issuer = new NameIDType();
+ issuer.setValue(this.issuer);
+
+ statusResponse.setIssuer(issuer);
+ statusResponse.setDestination(destination);
+
+ SAML2Response saml2Response = new SAML2Response();
+ samlResponse = saml2Response.convert(statusResponse);
+ } catch (ConfigurationException e) {
+ throw new ProcessingException(e);
+ } catch (ParsingException e) {
+ throw new ProcessingException(e);
+ }
+ return samlResponse;
+
+ }
+
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/SAML2NameIDPolicyBuilder.java b/saml-core/src/main/java/org/keycloak/saml/SAML2NameIDPolicyBuilder.java
new file mode 100755
index 0000000..446ca36
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/SAML2NameIDPolicyBuilder.java
@@ -0,0 +1,44 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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;
+
+import org.keycloak.dom.saml.v2.protocol.NameIDPolicyType;
+
+import java.net.URI;
+
+/**
+ * @author pedroigor
+ */
+public class SAML2NameIDPolicyBuilder {
+
+ private final NameIDPolicyType policyType;
+
+ private SAML2NameIDPolicyBuilder(String format) {
+ this.policyType = new NameIDPolicyType();
+ this.policyType.setFormat(URI.create(format));
+ }
+
+ public static SAML2NameIDPolicyBuilder format(String format) {
+ return new SAML2NameIDPolicyBuilder(format);
+ }
+
+ public NameIDPolicyType build() {
+ this.policyType.setAllowCreate(Boolean.TRUE);
+ return this.policyType;
+ }
+}
\ No newline at end of file
diff --git a/saml-core/src/main/java/org/keycloak/saml/SAMLRequestParser.java b/saml-core/src/main/java/org/keycloak/saml/SAMLRequestParser.java
new file mode 100755
index 0000000..fb4fa0a
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/SAMLRequestParser.java
@@ -0,0 +1,80 @@
+package org.keycloak.saml;
+
+import org.keycloak.saml.common.PicketLinkLogger;
+import org.keycloak.saml.common.PicketLinkLoggerFactory;
+import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
+import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
+import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
+import org.keycloak.saml.processing.web.util.PostBindingUtil;
+import org.keycloak.saml.processing.web.util.RedirectBindingUtil;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SAMLRequestParser {
+ private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();
+
+ public static SAMLDocumentHolder parseRequestRedirectBinding(String samlMessage) {
+ InputStream is;
+ is = RedirectBindingUtil.base64DeflateDecode(samlMessage);
+ SAML2Request saml2Request = new SAML2Request();
+ try {
+ saml2Request.getSAML2ObjectFromStream(is);
+ return saml2Request.getSamlDocumentHolder();
+ } catch (Exception e) {
+ logger.samlBase64DecodingError(e);
+ }
+ return null;
+
+ }
+
+ public static SAMLDocumentHolder parseRequestPostBinding(String samlMessage) {
+ InputStream is;
+ byte[] samlBytes = PostBindingUtil.base64Decode(samlMessage);
+ is = new ByteArrayInputStream(samlBytes);
+ SAML2Request saml2Request = new SAML2Request();
+ try {
+ saml2Request.getSAML2ObjectFromStream(is);
+ return saml2Request.getSamlDocumentHolder();
+ } catch (Exception e) {
+ logger.samlBase64DecodingError(e);
+ }
+ return null;
+ }
+
+ public static SAMLDocumentHolder parseResponsePostBinding(String samlMessage) {
+ byte[] samlBytes = PostBindingUtil.base64Decode(samlMessage);
+ return parseResponseDocument(samlBytes);
+ }
+
+ public static SAMLDocumentHolder parseResponseDocument(byte[] samlBytes) {
+ InputStream is = new ByteArrayInputStream(samlBytes);
+ SAML2Response response = new SAML2Response();
+ try {
+ response.getSAML2ObjectFromStream(is);
+ return response.getSamlDocumentHolder();
+ } catch (Exception e) {
+ logger.samlBase64DecodingError(e);
+ }
+ return null;
+ }
+
+ public static SAMLDocumentHolder parseResponseRedirectBinding(String samlMessage) {
+ InputStream is = RedirectBindingUtil.base64DeflateDecode(samlMessage);
+ SAML2Response response = new SAML2Response();
+ try {
+ response.getSAML2ObjectFromStream(is);
+ return response.getSamlDocumentHolder();
+ } catch (Exception e) {
+ logger.samlBase64DecodingError(e);
+ }
+ return null;
+
+ }
+
+
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/SignatureAlgorithm.java b/saml-core/src/main/java/org/keycloak/saml/SignatureAlgorithm.java
new file mode 100755
index 0000000..8df4bc3
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/SignatureAlgorithm.java
@@ -0,0 +1,69 @@
+package org.keycloak.saml;
+
+import java.security.Signature;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public enum SignatureAlgorithm {
+ RSA_SHA1("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "http://www.w3.org/2000/09/xmldsig#sha1", "SHA1withRSA"),
+ RSA_SHA256("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "http://www.w3.org/2001/04/xmlenc#sha256", "SHA256withRSA"),
+ RSA_SHA512("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "http://www.w3.org/2001/04/xmlenc#sha512", "SHA512withRSA"),
+ DSA_SHA1("http://www.w3.org/2000/09/xmldsig#dsa-sha1", "http://www.w3.org/2000/09/xmldsig#sha1", "SHA1withDSA")
+ ;
+ private final String xmlSignatureMethod;
+ private final String xmlSignatureDigestMethod;
+ private final String javaSignatureAlgorithm;
+
+ private static final Map<String, SignatureAlgorithm> signatureMethodMap = new HashMap<>();
+ private static final Map<String, SignatureAlgorithm> signatureDigestMethodMap = new HashMap<>();
+
+ static {
+ signatureMethodMap.put(RSA_SHA1.getXmlSignatureMethod(), RSA_SHA1);
+ signatureMethodMap.put(RSA_SHA256.getXmlSignatureMethod(), RSA_SHA256);
+ signatureMethodMap.put(RSA_SHA512.getXmlSignatureMethod(), RSA_SHA512);
+ signatureMethodMap.put(DSA_SHA1.getXmlSignatureMethod(), DSA_SHA1);
+
+ signatureDigestMethodMap.put(RSA_SHA1.getXmlSignatureDigestMethod(), RSA_SHA1);
+ signatureDigestMethodMap.put(RSA_SHA256.getXmlSignatureDigestMethod(), RSA_SHA256);
+ signatureDigestMethodMap.put(RSA_SHA512.getXmlSignatureDigestMethod(), RSA_SHA512);
+ signatureDigestMethodMap.put(DSA_SHA1.getXmlSignatureDigestMethod(), DSA_SHA1);
+ }
+
+ public static SignatureAlgorithm getFromXmlMethod(String xml) {
+ return signatureMethodMap.get(xml);
+ }
+
+ public static SignatureAlgorithm getFromXmlDigest(String xml) {
+ return signatureDigestMethodMap.get(xml);
+ }
+
+ SignatureAlgorithm(String xmlSignatureMethod, String xmlSignatureDigestMethod, String javaSignatureAlgorithm) {
+ this.xmlSignatureMethod = xmlSignatureMethod;
+ this.xmlSignatureDigestMethod = xmlSignatureDigestMethod;
+ this.javaSignatureAlgorithm = javaSignatureAlgorithm;
+ }
+
+ public String getXmlSignatureMethod() {
+ return xmlSignatureMethod;
+ }
+
+ public String getXmlSignatureDigestMethod() {
+ return xmlSignatureDigestMethod;
+ }
+
+ public String getJavaSignatureAlgorithm() {
+ return javaSignatureAlgorithm;
+ }
+
+ public Signature createSignature() {
+ try {
+ return Signature.getInstance(javaSignatureAlgorithm);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java b/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java
new file mode 100755
index 0000000..78ff2f3
--- /dev/null
+++ b/saml-core/src/main/java/org/keycloak/saml/SPMetadataDescriptor.java
@@ -0,0 +1,35 @@
+package org.keycloak.saml;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class SPMetadataDescriptor {
+ public static String getSPDescriptor(String binding, String assertionEndpoint, String logoutEndpoint, boolean wantAuthnRequestsSigned, String entityId, String nameIDPolicyFormat, String certificatePem) {
+ String descriptor =
+ "<EntityDescriptor xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"" + entityId + "\">\n" +
+ " <SPSSODescriptor AuthnRequestsSigned=\"" + wantAuthnRequestsSigned + "\"\n" +
+ " protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol http://schemas.xmlsoap.org/ws/2003/07/secext\">\n" +
+ " <NameIDFormat>" + nameIDPolicyFormat + "\n" +
+ " </NameIDFormat>\n" +
+ " <SingleLogoutService Binding=\"" + binding + "\" Location=\"" + logoutEndpoint + "\"/>\n" +
+ " <AssertionConsumerService\n" +
+ " Binding=\"" + binding + "\" Location=\"" + assertionEndpoint + "\"\n" +
+ " index=\"1\" isDefault=\"true\" />\n";
+ if (wantAuthnRequestsSigned) {
+ descriptor +=
+ " <KeyDescriptor use=\"signing\">\n" +
+ " <dsig:KeyInfo xmlns:dsig=\"http://www.w3.org/2000/09/xmldsig#\">\n" +
+ " <dsig:X509Data>\n" +
+ " <dsig:X509Certificate>\n" + certificatePem + "\n" +
+ " </dsig:X509Certificate>\n" +
+ " </dsig:X509Data>\n" +
+ " </dsig:KeyInfo>\n" +
+ " </KeyDescriptor>\n";
+ }
+ descriptor +=
+ " </SPSSODescriptor>\n" +
+ "</EntityDescriptor>\n";
+ return descriptor;
+ }
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
index eb25ff0..308fb67 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
@@ -155,12 +155,16 @@ public class KeycloakServer {
}
File dir = new File(resources).getAbsoluteFile();
- if (!dir.isDirectory() || !new File(dir, "forms").isDirectory()) {
- throw new RuntimeException("Invalid resources directory");
+ if (!dir.isDirectory()) {
+ throw new RuntimeException("Invalid base resources directory");
+
+ }
+ if (!new File(dir, "themes").isDirectory()) {
+ throw new RuntimeException("Invalid resources forms directory");
}
if (!System.getProperties().containsKey("keycloak.theme.dir")) {
- System.setProperty("keycloak.theme.dir", file(dir.getAbsolutePath(), "forms", "common-themes", "src", "main", "resources", "theme").getAbsolutePath());
+ System.setProperty("keycloak.theme.dir", file(dir.getAbsolutePath(), "themes", "src", "main", "resources", "theme").getAbsolutePath());
} else {
String foo = System.getProperty("keycloak.theme.dir");
System.out.println(foo);