Skip to content

Add support for validation of InResponseTo attribute when validating SAML2 responses #10849

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

fast-reflexes
Copy link
Contributor

@fast-reflexes fast-reflexes commented Feb 19, 2022

… a SAML2 response given that this attribute is set and that the request can be found.

#9174

What do you think so far?

Left to do that I know of:

  • Perhaps add some test
  • Go through submission guidelines again

@pivotal-cla
Copy link

@fast-reflexes Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

@pivotal-cla
Copy link

@fast-reflexes Thank you for signing the Contributor License Agreement!

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 19, 2022
@eleftherias eleftherias added in: saml2 An issue in SAML2 modules status: duplicate A duplicate of another issue type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Feb 21, 2022
Copy link
Contributor

@jzheaux jzheaux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @fast-reflexes! I've left some feedback inline.

Additionally, will you please format your commit message like this:

Commit Title

Closes gh-9174

@fast-reflexes
Copy link
Contributor Author

fast-reflexes commented Feb 26, 2022

@jzheaux I updated the branch and also included eviction of stale stored requests.

Updated behaviour:

  • If valid request exists and InResponseTo is set in response, it is validated
  • If no valid request exists and InResponseTo is set in response, it is rejected
  • If valid stored request exists and no InResponseTo in response, it is rejected
  • A stored request that is more than 30 seconds old is considered invalid

Questions:

  • Do we need more tests in OpenSamlAuthenticationRequestResolverTests?
  • What is the purpose of including the response argument in HttpSessionSaml2AuthenticationRequestRepository? (removeAuthenticationRequest(HttpServletRequest request, HttpServletResponse response))
  • Any comments on the use of Long or long for issuingInstantEpochSeconds?
  • I see some different practices; sometimes Instant.now() is used, other times a Clock is stored in the class and Instant.now(clock) is used, yet other times, clock.millis() is used.. any preference?
  • Do we need to think about log out requests in connection to the changes in this PR?

@fast-reflexes fast-reflexes changed the title -Add support for validation of InResponseTo attribute when validating… Add support for validation of InResponseTo attribute when validating SAML2 responses Feb 26, 2022
Copy link
Contributor

@jzheaux jzheaux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @fast-reflexes! I've left some feedback inline.

In addition to that feedback, will you do me the favor of making your commit title just a tad shorter? ~50 characters is ideal. This helps when scanning through Git logs.

@fast-reflexes
Copy link
Contributor Author

fast-reflexes commented Mar 5, 2022

I updated based on your feedback.

  • What I mean is that converting the request to a string and then decoding it is less straightforward than storing the domain representation of a request (be it locked down to the OpenSAML implementation or some thin wrapper around it). Transforming it into a string is a preparation for the actual outgoing request and therefore something that I think should be done right before sending the actual request. It also makes testing more cumbersome when the request is stored as a string.
  • I really think we should have a flag / property for whether applications want to use validation of InResponseTo or not. Of course they can add their own validators and so on but it's more cumbersome than just opting in or out of such a feature via a Spring property.

These are my remarks as a programmer and a Spring user :) In here, I'm nothing but someone who wants to get more involved and learn to contribute so I respect your decisions to 100% and without debate, just letting you know what I think :)

Let me know what you think of the current state of the code :)

Copy link
Contributor

@jzheaux jzheaux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @fast-reflexes! Glad this is taking shape. I've left some feedback inline.

@jzheaux
Copy link
Contributor

jzheaux commented Mar 7, 2022

What I mean is that converting the request to a string and then decoding it is less straightforward than storing the domain representation of a request (be it locked down to the OpenSAML implementation or some thin wrapper around it).

I see your point, but not how to apply it. AuthnRequest is not Serializable, so how would you expect the AuthnRequest to be able to be stored in the session?

I really think we should have a flag / property for whether applications want to use validation of InResponseTo or not.

We can always add this in a separate PR down the road. I think boolean properties should be added quite slowly and with more usage data than we have now. You are welcome to add a ticket and then we can see if the community votes for it.

@fast-reflexes
Copy link
Contributor Author

I see your point, but not how to apply it. AuthnRequest is not Serializable, so how would you expect the AuthnRequest to be able to be stored in the session?

Aha.. so THAT'S the problem ... hmm .. ok, then I'll rest my case for now!

Factored out repeatedly used code for signing a request.
@fast-reflexes fast-reflexes force-pushed the gh-9174 branch 2 times, most recently from a172bcb to 2f1d161 Compare March 11, 2022 05:54
context.put(SAML2AssertionValidationParameters.SC_VALID_IN_RESPONSE_TO, requestId);
}
else {
context.put(SAML2AssertionValidationParameters.SC_VALID_IN_RESPONSE_TO, "");
Copy link
Contributor Author

@fast-reflexes fast-reflexes Mar 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we set the empty string so that we know that the validation will fail (since the very prerequisite for even doing the validation is that the some of the assertion subject confirmation has a non-empty InResponseTo). The reason for failing is either that there was no stored request, it could not be deserialized or it lacked id. You think this solution is ok?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could trigger a false positive if we have multiple confirmations and one has the (invalid) empty string as InResponseTo whereas a later one has a proper one ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps better to stay with the override anyways?

  • Won't be more code than is added by this solution
  • Easier to understand what's going on
  • Will cover all cases since we can control directly whether to consider valid or not

Copy link
Contributor

@jzheaux jzheaux Mar 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just leave it unset. The OpenSAML code works as follows:

  • If no InResponseTo in subject confirmation -> valid
  • Or, if no SC_VALID_IN_RESPONSE_TO set -> invalid
  • Or, if SC_VALID_IN_RESPONSE_TO mismatches InResponseTo -> invalid

Could trigger a false positive

If any assertions are wrong, then we should fail. We don't accept a response that is in response to multiple requests.

override anyways ... Easier to understand what's going on

Ideally, we don't write code that we don't have to as this lowers maintenance. I don't see why it's easier to understand what is going on. The code that you have written is virtually the same as OpenSAML's BearerSubjectConfirmationValidator#validateInResponseTo.

Copy link
Contributor Author

@fast-reflexes fast-reflexes Mar 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah of course, can be unset, I don't know what I was thinking... and what I meant by

Could trigger a false positive if we have multiple confirmations and one has the (invalid) empty string as
InResponseTo whereas a later one has a proper one ...

was that if an assertion has a subject confirmation with the empty string as InResponseTo and SC_VALID_IN_RESPONSE_TO was set to the empty string due to problems with deserialization, then the subject confirmation would falsely be valid no matter the value of the actual request id. I was talking about multiple confirmations (not assertions) because apparently it seems it is enough with one confirmation passing the test on the subject (see SAML20AssertionValidator::validateSubjectConfirmation). I now realized that the false positive does not require two confirmations even, just one with the empty string. However, since we can leave it unset, it should not be a problem.

I've updated the code, let me know what you think!

Whenever an InResponseTo is present in the SAML2 response and / or any of its assertions, it will be validated against the stored SAML2 request. If the request is missing or the ID of the request does not match the InResponseTo, validation fails. If there is no InResponseTo, no validation of it is done (as opposed to checking whether there is a saved request or not and then failing based on that).

Closes spring-projectsgh-9174
@jzheaux
Copy link
Contributor

jzheaux commented Mar 15, 2022

Thanks, @fast-reflexes! I've merged your commits into 5.7.x and into main. I also added a polish commit to make the code more consistent with the rest of Spring Security.

@jzheaux jzheaux closed this Mar 15, 2022
@jzheaux jzheaux added this to the 5.7.0-M3 milestone Mar 15, 2022
@fast-reflexes
Copy link
Contributor Author

Great, thanks @jzheaux ! I looked into your changes to learn the style... what do you mean by

Refactored methods to have only immutable method parameters

Just curious :)

@fast-reflexes fast-reflexes deleted the gh-9174 branch March 16, 2022 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: saml2 An issue in SAML2 modules status: duplicate A duplicate of another issue type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants