Skip to content

Check recipient/destination metadata before sender/source metadata wh…#1303

Open
dub357 wants to merge 1 commit into
simplesamlphp:masterfrom
dub357:redirect_dest_message_sigining
Open

Check recipient/destination metadata before sender/source metadata wh…#1303
dub357 wants to merge 1 commit into
simplesamlphp:masterfrom
dub357:redirect_dest_message_sigining

Conversation

@dub357

@dub357 dub357 commented Mar 26, 2020

Copy link
Copy Markdown
Contributor

Check recipient/destination metadata before sender/source metadata when determining whether or not to sign messages (sign.authnrequest/sign.logout) in the HTTP-REDIRECT profile. If in IdP metadata, allows the SP that would normally sign authn requests/logout requests (because these options are 'true' in its own metadata) to not do so if the IdP doesn't want it. When in SP metadata, allows an IdP to that would normally want to logout requests/responses (because these options are 'true' in its own metadata) to not do so if the SP doesn't want it.
The documentation seems to suggest that this should already be the case but it turns out the code doesn't respect those rules because each side checks its own metadata first before determining if the recipient/destination has the option.

Fix for issue (I closed the older PR referenced in issue):
#687

…en determining whether or not to sign messages (sign.authnrequest/sign.logout) in the HTTP-REDIRECT profile. If in IdP metadata, allows the SP that would normally sign authn requests/logout requests (because these options are 'true' in its own metadata) to not do so if the IdP doesn't want it. When in SP metadata, allows an IdP to that would normally want to logout requests/responses (because these options are 'true' in its own metadata) to not do so if the SP doesn't want it.

The documentation seems to suggest that this should already be the case but it turns out the code doesn't respect those rules because each side checks its own metadata first before determining if the recipient/destination has the option.

Fix for issue (I closed the older PR referenced in issue):
simplesamlphp#687
@codecov

codecov Bot commented Mar 26, 2020

Copy link
Copy Markdown

Codecov Report

Merging #1303 into master will not change coverage by %.
The diff coverage is 50.00%.

@@            Coverage Diff            @@
##             master    #1303   +/-   ##
=========================================
  Coverage     37.87%   37.87%           
  Complexity     3430     3430           
=========================================
  Files           129      129           
  Lines          9735     9735           
=========================================
  Hits           3687     3687           
  Misses         6048     6048           

@tvdijen

tvdijen commented Mar 26, 2020

Copy link
Copy Markdown
Member

If in IdP metadata, allows the SP that would normally sign authn requests/logout requests [..] to not do so if the IdP doesn't want it.

I'm sorry, but that's just not how it works.. An IDP can demand signed requests, but it can't demand unsigned requests

@dub357

dub357 commented Mar 26, 2020

Copy link
Copy Markdown
Contributor Author

Perhaps I'm missing something then? In the IdP metadata, the IdpSSODescriptor can have the "WantAuthnRequestsSigned" attribute which tells the SP if they want the AuthnRequest signed or not...

@tvdijen

tvdijen commented Mar 26, 2020

Copy link
Copy Markdown
Member

https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf

Paragraph 2.4.3:

WantAuthnRequestsSigned [Optional]Optional attribute that indicates a requirement for the samlp:AuthnRequest messages received by this identity provider to be signed. If omitted, the value is assumed to be false.

False here meaning 'not a requirement'.. Not 'unwanted'

@dub357

dub357 commented Mar 26, 2020

Copy link
Copy Markdown
Contributor Author

https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf

Paragraph 2.4.3:

WantAuthnRequestsSigned [Optional]Optional attribute that indicates a requirement for the samlp:AuthnRequest messages received by this identity provider to be signed. If omitted, the value is assumed to be false.

False here meaning 'not a requirement'.. Not 'unwanted'

The spec is unclear about this so it would seem that this is up for interpretation by implementers. The problem I'm trying to solve is where IdPs allow "anonymous" relying parties (something that can be enabled by Shibboleth) and have no metadata of an SP but receive an SP AuthnRequest that is signed and they have no way to verify the signature so the request fails. If the SP was "smart enough" to not send a signed request in the first place, this wouldn't be a problem. But since SSP acting as an SP checks its own metadata first before checking the IdP, this comes up as a problem integrating with those IdPs. Its worth noting that this is the only case where SSP fails to check the destination metadata prior to checking its own to determine if a request should be signed.

@tvdijen

tvdijen commented Mar 26, 2020

Copy link
Copy Markdown
Member

I don't think it's unclear at all... The SP will indicate in it's metadata (2.4.4) whether requests are signed or not.. the idp should just act accordingly... Maybe the others think differently

@dub357

dub357 commented Mar 26, 2020

Copy link
Copy Markdown
Contributor Author

Maybe I'm misunderstanding the spec, but I fail to see how this is any different from the "WantAssertionsSigned" attribute in SP metadata. If this set to true (corresponding SSP metadata config 'saml20.sign.assertion'), the IdP either signs the assertion or not. It doesn't do whatever it wants to unless the attribute isn't present in the SP metadata. So it makes sense for the reverse to be true. If the IdP doesn't want authn requests signed, the SP shouldn't sign them.
In fact SSP already works in this same manner if neither the SP nor IdP have 'sign.authnrequest' defined but the IdP does have the 'redirect.sign' set to false. It checks the destination metadata first, then its own (lines 110-115 of modules/saml/lib/Message.php). All I'm looking for is the same behavior if both have 'sign.authnrequest' set....use the value that the destination wants...

@thijskh

thijskh commented Mar 26, 2020

Copy link
Copy Markdown
Member

Can you make the usecase a bit more specific so I can understand it better? Some concrete example of such IdPs that do this?

@dub357

dub357 commented Mar 26, 2020

Copy link
Copy Markdown
Contributor Author

Obviously use cases all depend on how the IdPs and SPs are configured, but internal to my organization we have a Shibboleth IdP that allows anonymous or unverified relying parties.
https://wiki.shibboleth.net/confluence/display/IDP30/RelyingPartyConfiguration

To the IdP, these are SPs that it has no metadata for. Its useful for us internally because we don't have to manage metadata for these parties. Or they don't have a common endpoint (the reason for my other pull request). The IdP simply receives the authn requests, authenticates the user and sends the assertion in the response - it does absolutely no verification of whether or not it should interoperate with the SP - it just does. When SSP sends an AuthnRequest to one of these IdPs it signs the requests (even though the IdP metadata has 'sign.authnrequests' to false). However when the Shibboleth IdP sees the request is signed, it tries to validate it but it has no metadata (certificate/public key) to use for validation. So it immediately fails the request.
Again - what I'm I'm asking for SSP already does if the 'sign.authnrequest' option isn't set in either party's metadata (as defined by how it uses the 'redirect.sign' option), I just want it to use the same logic for the more detailed scenario (sign.authnrequest and sign.logout).

@tvdijen tvdijen force-pushed the master branch 3 times, most recently from 1c686ab to eb20457 Compare August 17, 2020 20:43
@tvdijen

tvdijen commented Aug 26, 2020

Copy link
Copy Markdown
Member

To the IdP, these are SPs that it has no metadata for. Its useful for us internally because we don't have to manage metadata for these parties.

This just raises red flags to me.. You should never want this, not even internally.. Security 101.. It's just not safe.. And so are unsolicited responses..

When SSP sends an AuthnRequest to one of these IdPs it signs the requests (even though the IdP metadata has 'sign.authnrequests' to false). However when the Shibboleth IdP sees the request is signed, it tries to validate it but it has no metadata (certificate/public key) to use for validation. So it immediately fails the request.

That's up to the IDP.. They are free to ignore the signature if they like to.. Remember this is XML, and the base-rule in XML is; if you don't know it, or don't want to know it > ignore it!

@thijskh What's your opinion on this, because I'm not eager at all to merge this?

@dub357

dub357 commented Aug 26, 2020

Copy link
Copy Markdown
Contributor Author

To the IdP, these are SPs that it has no metadata for. Its useful for us internally because we don't have to manage metadata for these parties.

This just raises red flags to me.. You should never want this, not even internally.. Security 101.. It's just not safe.. And so are unsolicited responses..

When SSP sends an AuthnRequest to one of these IdPs it signs the requests (even though the IdP metadata has 'sign.authnrequests' to false). However when the Shibboleth IdP sees the request is signed, it tries to validate it but it has no metadata (certificate/public key) to use for validation. So it immediately fails the request.

That's up to the IDP.. They are free to ignore the signature if they like to.. Remember this is XML, and the base-rule in XML is; if you don't know it, or don't want to know it > ignore it!

@thijskh What's your opinion on this, because I'm not eager at all to merge this?

Please do not get confused by my particular use case as it makes no difference for this PR. The fact is that I simply want a way for SSP to NOT to sign an AuthnRequest if the metadata for the IdP requests that it shouldn't be signed.

As I mentioned before, the behavior I'm FIXING in this PR is the exact behavior SSP performs when it has no "sign.logout" or "sign.authnrequest" config option in metadata and therefore checks for the "redirect.sign" option. Regardless of whether or not you guys want to check the source metadata first or the destination metadata, it needs to be consistent. Please at least review the method in question for behavior consistency before you make a decision about whether or not to merge my PR.

@dub357

dub357 commented Aug 26, 2020

Copy link
Copy Markdown
Contributor Author

I'll also mention that this PR addresses behavior inconsistencies in documentation (referenced in my original issue #687 )

Per the current documentation for saml:SP authentication source and its "sign.authnrequest" config option:
"Note that this option also exists in the IdP-remote metadata, and any value in the IdP-remote metadata overrides the one configured in the SP configuration."

The current implementation of the 'addRedirectSign' does not conform to the documented behavior as the IdP-remote metadata does NOT override the SP configuration. It should - hence my PR.

@tvdijen

tvdijen commented Aug 26, 2020

Copy link
Copy Markdown
Member

I'm not confusing anything, I'm just disagreeing with you on the specs (which is an issue with the specs, because specs should by definition be non-debatable).. We should obviously fix any inconsistencies in the documentation..

I'd also like to point out the core-specs that says: The <AuthnRequest> message SHOULD be signed or otherwise authenticated and integrity protected by the protocol binding used to deliver the message.. That indicates to me that even if WantAuthnRequestsSigned = false, it still should be signed by default and that non-signing should be an agreement between IDP/SP rather than automated behaviour ..
I also believe that SPSSODescriptor::AuthnRequestsSigned prevails over IDPSSODescriptor::WantAuthnRequestsSigned, because in the SAML SSO paradigm it's up to the SP to request whatever it wants and the IDP should follow this (or not use the service at all)..

I'd be happy to hear from my colleages on this matter. We can always put up our questions on the Oasis maling list..

@dub357

dub357 commented Aug 26, 2020

Copy link
Copy Markdown
Contributor Author

Fair enough - however our disagreement over the spec is a result of the inconsistent method behavior and the documentation discrepancies. Are you also disagreeing that the current method behavior is inconsistent with regards to 'sign.authnrequests/sign.logoutrequests' and 'redirect.sign' options? Because its clear that in one case the method favors the source metadata and the destination metadata in the other.
It also sounds like you would rather change the documentation to match the current implementation of the method rather than pull in my change, is that right? This seems like more work to me, not to mention something I would think would be undesirable as it currently prevents SSP acting as an SP to selectively sign authn requests...

@tvdijen

tvdijen commented Aug 26, 2020

Copy link
Copy Markdown
Member

Because its clear that in one case the method favors the source metadata and the destination metadata in the other

This is undesirable and as stated should be taken care of, one way or another.

It also sounds like you would rather change the documentation to match the current implementation of the method rather than pull in my change, is that right?

To me personally, yes. But I'm no authority here, so I'd like to agree on something with the other devs.. Even if it's against my personal preference. I just want to make clear and weighted decisions and document them to avoid having the same discussions next year.

This seems like more work to me, not to mention something I would think would be undesirable as it currently prevents SSP acting as an SP to selectively sign authn requests...

I don't care about the extra work.. If we need to be able to selectively sign, then so be it and we have to work towards that. I do however think it's already possible by setting the redirect.sign flag on the SP authsource?

@thijskh

thijskh commented Aug 26, 2020

Copy link
Copy Markdown
Member

To me it seems only relevant what the recipient wants to happen. So the IdP in the case of the authnrequest. They indicate they want it, we should sign it because they want it (and one may expect it not to work otherwise).

They indicate they don’t want it, we should not sign because:
a) Probably they will then not be checking the signature or relying on any sensitive information in the request;
b) There’s no use case for signing the request if you’re not sure that the relying party checks the signature; you as the sender cannot assume you can put something signworthy in it;
c) They will probably not do anything with the signature, so it’s a waste of cycles.

So I agree that if the destination does not want a signature there’s really no need to do it anyway. Because the signature is only relevant to the party receiving, verifying and acting on it.

Does this answer the question posed?

@dub357

dub357 commented Aug 26, 2020

Copy link
Copy Markdown
Contributor Author

They indicate they don’t want it, we should not sign because:
a) Probably they will then not be checking the signature or relying on any sensitive information in the request;
b) There’s no use case for signing the request if you’re not sure that the relying party checks the signature; you as the sender cannot assume you can put something signworthy in it;
c) They will probably not do anything with the signature, so it’s a waste of cycles.

Or for my particular use case (dealing with a Shibboleth IdP that allows anonymous relying parties ie. SPs without metadata)

d) They will try to validate the signature, but have no metadata for the SP so the AuthnRequest cannot be validated and the request fails.

@thijskh

thijskh commented Aug 26, 2020

Copy link
Copy Markdown
Member

That last item I do not follow. Why would you check a signature and not continue when it fails, but would continue when the signature is absent? How does that combination make sense?

Either you require signatures or you don’t?

@tvdijen

tvdijen commented Aug 26, 2020

Copy link
Copy Markdown
Member

I think the flag's name is misleading, because of the want and then the spec talking about requirement. To NOT WANT something means something completely different to NOT REQUIRE.. It's semantics really..

I also agree to Thijs.. If you don't care about it, then ignore it; it's XML basic rules.. To me this feels like an issue with Shib IDP.

@thijskh

thijskh commented Aug 26, 2020

Copy link
Copy Markdown
Member

Well Tim, I do agree that there’s no use in sending signatures to a party that does not want them.

I indeed do not understand why the IdP then checks signatures in the first place if they do not want them.

@dub357

dub357 commented Aug 26, 2020

Copy link
Copy Markdown
Contributor Author

That last item I do not follow. Why would you check a signature and not continue when it fails, but would continue when the signature is absent? How does that combination make sense?

Either you require signatures or you don’t?

The only way Anonymous relying parties only work for the Shibboleth IdP if no signatures or encryption happens because the request cannot be validated. Shibboleth always tries to validate a signature if it exists. It doesn't first check to see if it can find metadata for the SP and then ignore the signature if none exists. If no metadata exists and the request is signed, Shibboleth says the request is not valid. This may be a bug or issue that should be brought up with them, but all I really want is for SSP to respect the IdP metadata with respect to authn request signing.

@tvdijen

tvdijen commented Aug 26, 2020

Copy link
Copy Markdown
Member

@dub357 What about setting the redirect.sign flag on the SP authsource? Doesn't that resolve your issue?

@thijskh

thijskh commented Aug 26, 2020

Copy link
Copy Markdown
Member

Agreed that what shib does is in the end not very relevant to this question. Let me review the concrete change later and give you an update on where I stand (have to understand a bit more about the conext of the changed lines)

@dub357

dub357 commented Aug 26, 2020

Copy link
Copy Markdown
Contributor Author

@dub357 What about setting the redirect.sign flag on the SP authsource? Doesn't that resolve your issue?

Not really....I want to default to signing requests to all other IdPs except this one. Without setting 'sign.authnrequests' or 'redirect.sign' to true, I have to rely on the IdP metadata to ensure it has 'sign.authnrequests=true'. The problem is, that isn't always the case...an IdP may not have that setting set in its metadata. Basically, I want to default to always signing the request unless the IdP doesn't want it.

@tvdijen

tvdijen commented Aug 26, 2020

Copy link
Copy Markdown
Member

Tell be a bit more about your setup..
Do you have one saml:SP and multiple remote IDP's? You should be able to set the redirect.sign on the IDP-metadata as well, and therefore set it to false for the one IDP..
Or are you running SSP in a bridge mode? I guess the same rule should apply as above..
I'm trying to understand your use-case a bit more, because it's more than anonymous SP's... I wouldn't be surprised if the logics are reversed and the IDP-local setting would be overruled by the saml:SP authsource..

Good discussion btw!! ::rocket::

@dub357

dub357 commented Aug 26, 2020

Copy link
Copy Markdown
Contributor Author

Tell be a bit more about your setup..
Do you have one saml:SP and multiple remote IDP's? You should be able to set the redirect.sign on the IDP-metadata as well, and thus set it to false for the one IDP..
Or are you running SSP in a proxy/bridge mode? I guess the same rule should apply as above..
I'm trying to understand your use-case a bit more, because it's more than anonymous SP's...

I'm running SSP as a proxy/bridge. Like I stated to Tim, my particular use case shouldn't really matter and seems that it is just confusing everyone. All I want is SSP to prefer the IdP metadata over its own with respect to authnrequest signing. The documentation states that it does, but the behavior is actually inconsistent depending on the metadata options set.

@tvdijen tvdijen force-pushed the master branch 7 times, most recently from 7b173cf to 3326beb Compare March 20, 2023 22:59
@tvdijen tvdijen force-pushed the master branch 2 times, most recently from 8ac729b to a16cf6e Compare April 25, 2023 08:33
@tvdijen tvdijen force-pushed the master branch 2 times, most recently from fc454de to 7ac76ae Compare May 3, 2023 08:31
@tvdijen tvdijen force-pushed the master branch 6 times, most recently from 29f7b69 to 1a911ce Compare May 12, 2023 16:07
@tvdijen tvdijen force-pushed the master branch 3 times, most recently from c7c8357 to fdbe001 Compare June 12, 2023 14:28
@tvdijen tvdijen force-pushed the master branch 8 times, most recently from 3b5f5ba to 96357ee Compare July 19, 2023 12:37
@tvdijen tvdijen force-pushed the master branch 2 times, most recently from d7f25d2 to 41d9254 Compare July 30, 2023 08:37
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants