SAML-Toolkits / java-saml

Java SAML toolkit
MIT License
633 stars 395 forks source link

Invalid AuthnRequest because of & #305

Open lucasmenezesaurea opened 3 years ago

lucasmenezesaurea commented 3 years ago

In assertionConsumerServiceUrl if URL contains & it is decoded to & . Consequently, AuthnRequest XML is invalid because contains & without encoding. Some IdP can't parse the XML because it is invalid. This does not happens for OneLogin IdP.

mauromol commented 3 years ago

I think this is due to #309.

mauromol commented 3 years ago

@lucasmenezesaurea I provided a PR that I hope @pitbulk will evaluate. Re-reading again your report, though, I'm not sure I understood it right. You say that if your ACS URL contains &amp it gets decoded to &... but when? Perhaps after signing?

Before my PR, the com.onelogin.saml2.authn.AuthnRequest.getAuthnRequestXml() method returned an XML message containing all text strings specified in settings literally, so if your URL contained &, the unsigned XML was generated containing &, with no change. I guess that, if you sign that XML file, the signature process, which parses back the XML and then produces a signed version of the same XML file, may indeed parse & as & and hence produce the wrong result.

With my PR, any text (URLs, organization names, other string configuration parameters) are properly escaped when generating the unsigned XML messages, so a URL which should contain & will be escaped as & and hence the signing process should correctly parse it back as & to produce its own output.

Perhaps you may try to build from my branch (https://github.com/mauromol/java-saml/tree/escape-strings-in-xml) and see?

lucasmenezesaurea commented 3 years ago

This is the SP metadata:

<?xml version="1.0"?>

<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://mygnx-qualif/ace202-webgce">

                <md:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">

                               <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://mygnx-qualif/java-saml-tookit-jspsample/sls.jsp"/>

                               <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>

                               <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://mygnx-qualif/ace202-webgce/GCE/ServletControl?cinematic=login%28Login%29&amp;chp%3AENTITY=1&amp;sourceview=LOGIN" index="1"/>

                </md:SPSSODescriptor>

                <md:Organization>

                               <md:OrganizationName xml:lang="en">Aurea</md:OrganizationName>

                               <md:OrganizationDisplayName xml:lang="en">Aurea Collaborative Enterprise</md:OrganizationDisplayName>

                               <md:OrganizationURL xml:lang="en">https://www.aurea.com/library/collaborative-enterprise/</md:OrganizationURL>

                </md:Organization>

</md:EntityDescriptor>

This is AuthnRequest:

<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="ONELOGIN_11baec22-8fe2-49cc-8cf4-6e60977f6a60" Version="2.0" IssueInstant="2021-03-29T08:11:11Z" ProviderName="Aurea Collaborative Enterprise" Destination="https://ssopp.ramsaygds.fr/samlv2/AccueilAuth/IdPAccess/Generix_Qualif" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="https://mygnx-qualif/ace202-webgce/GCE/ServletControl?cinematic=login%28Login%29&chp%3AENTITY=1&sourceview=LOGIN"><saml:Issuer>https://mygnx-qualif/ace202-webgce</saml:Issuer><samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" AllowCreate="true" /><samlp:RequestedAuthnContext Comparison="exact"><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></samlp:RequestedAuthnContext></samlp:AuthnRequest>

The error happens when IdP tries to proccess this AuthnRequest. See &chp is not scaped into &amp;chp . If you try to format this XML (e.g. https://www.freeformatter.com/xml-formatter.html) you will se the AuthnRequest is invalid.

mauromol commented 3 years ago

The error is clear, what I still don't fully understand, since your AuthRequest seems not to be signed, is how you generate the AuthRequest. In particular, do you specify the ACS URL in the settings file (or in a dynamic settings map)?

lucasmenezesaurea commented 3 years ago

Hello @mauromol replace all & by %26 after authnRequest.getEncodedAuthnRequest(); IdP will accept the request

workaround is to avoid & in your md:AssertionConsumerService , by replacing all & to %26

mauromol commented 3 years ago

I believe this is closed by #315.