-
Notifications
You must be signed in to change notification settings - Fork 116
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
LG-226 Fix Double Render Error with Bad Saml Packet on Logout #2125
LG-226 Fix Double Render Error with Bad Saml Packet on Logout #2125
Conversation
fc117a3
to
7466da6
Compare
Are you still working on this? Will you be adding a test for the scenario you are trying to fix? |
3536190
to
bfc460e
Compare
@@ -85,7 +85,7 @@ def prepare_saml_logout_response | |||
end | |||
|
|||
def prepare_saml_logout_request | |||
validate_saml_request | |||
return if validate_saml_request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bug that we used to have was that we were expecting the SAML request validation to stop the logout process from continuing if the request was invalid, but because we are calling validate_saml_request
from within a method inside the logout
action, it will still continue executing the rest of the method if the request is invalid.
While your solution works, it is hard to understand IMO. When I read return if validate_saml_request
, at first glance it means to me that if the request was valid, then we want to stop preparing the logout request, which is the opposite of what is actually happening.
I propose an alternative solution, which is to add a before_action
that validates the request, like so:
before_action :validate_saml_logout_request, only: :logout
def validate_saml_logout_request(raw_saml_request = params[:SAMLRequest])
track_logout_event
return unless raw_saml_request
decode_request(raw_saml_request)
head :bad_request unless valid_saml_request?
end
and then remove the call to track_logout_event
from the top of the logout
action.
I would also suggest updating track_logout_event
to capture whether or not the SAML request was valid:
def track_logout_event
saml_request = params[:SAMLRequest]
result = {
sp_initiated: saml_request.present?,
oidc: false,
}
result.merge!(saml_request_valid: valid_saml_request?) if saml_request
analytics.track_event(Analytics::LOGOUT_INITIATED, result)
end
Ideally, we would also update the saml_idp
gem so that the validation returns a rich object that we can fetch errors from so we can see exactly why the request failed validation. Currently, the gem just outputs the failure reason to the Rails log.
Also, note that I changed the error from a 403 forbidden to a 401 bad request, which I think is more appropriate in this case.
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great ideas. The gem's method name validate_saml_request definitely gives no indication that nil/false is the good condition so the name is misleading. Their 403 error is also not right but I think you mean we should return 400 bad request (not 401). I'd prefer their gem did the work and fix these issues but this is a good interim solution (we are effectively fixing their method and putting it in our code). I was planning on doing a separate pr for more descriptive errors like 'Signature is invalid' (LG-224). A 400 bad request still doesn't give much but at least it's an improvement.
bf6797a
to
271dfdc
Compare
sign_in user | ||
|
||
post :logout, params: { SAMLRequest: 'foo' } | ||
expect(response.status).to eq(400) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also add a test for analytics to make sure it reports saml_request_valid: false
and sp_initiated: true
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just noticed that the new one you added above is basically the same as this one. Can we combine the two, i.e. add expect(response.status).to eq(400)
to the one above?
**Why**: This error and a stack trace appear in the logs and make it difficult to diagnose saml logout issues with agency integration. Moreover we throw a 500 error when the saml idp gem is trying to return a 403 / forbidden error. **How**: Check the return value of the gem's validation of the saml packet and return from the concern. Then check if there was a valid render in the controller.
d63443c
to
0401ada
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Why: This error and a stack trace appear in the logs and make it difficult to diagnose saml logout issues with agency integration. Moreover we throw a 500 error when the saml idp gem is trying to return a 403 / forbidden error.
How: Check the return value of the gem's validation of the saml packet and return from the concern. Then check if there was a valid render in the controller.
Hi! Before submitting your PR for review, and/or before merging it, please
go through the following checklist:
For DB changes, check for missing indexes, check to see if the changes
affect other apps (such as the dashboard), make sure the DB columns in the
various environments are properly populated, coordinate with devops, plan
migrations in separate steps.
For route changes, make sure GET requests don't change state or result in
destructive behavior. GET requests should only result in information being
read, not written.
For encryption changes, make sure it is compatible with data that was
encrypted with the old code.
For secrets changes, make sure to update the S3 secrets bucket with the
new configs in all environments.
Do not disable Rubocop or Reek offenses unless you are absolutely sure
they are false positives. If you're not sure how to fix the offense, please
ask a teammate.
When reading data, write tests for nil values, empty strings,
and invalid formats.
When calling
redirect_to
in a controller, use_url
, not_path
.When adding user data to the session, use the
user_session
helperinstead of the
session
helper so the data does not persist beyond the user'ssession.
When adding a new controller that requires the user to be fully
authenticated, make sure to add
before_action :confirm_two_factor_authenticated
.