Skip to content
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

Merged

Conversation

stevegsa
Copy link
Contributor

@stevegsa stevegsa commented Apr 27, 2018

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 helper
    instead of the session helper so the data does not persist beyond the user's
    session.

  • When adding a new controller that requires the user to be fully
    authenticated, make sure to add before_action :confirm_two_factor_authenticated.

@stevegsa stevegsa force-pushed the stevegsa-fix-saml-logout-double-render-error-on-bad-packet branch from fc117a3 to 7466da6 Compare April 27, 2018 15:52
@monfresh
Copy link
Contributor

Are you still working on this? Will you be adding a test for the scenario you are trying to fix?

@stevegsa stevegsa force-pushed the stevegsa-fix-saml-logout-double-render-error-on-bad-packet branch 2 times, most recently from 3536190 to bfc460e Compare April 28, 2018 14:45
@@ -85,7 +85,7 @@ def prepare_saml_logout_response
end

def prepare_saml_logout_request
validate_saml_request
return if validate_saml_request
Copy link
Contributor

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?

Copy link
Contributor Author

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.

@stevegsa stevegsa force-pushed the stevegsa-fix-saml-logout-double-render-error-on-bad-packet branch 2 times, most recently from bf6797a to 271dfdc Compare April 29, 2018 15:00
sign_in user

post :logout, params: { SAMLRequest: 'foo' }
expect(response.status).to eq(400)
Copy link
Contributor

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?

Copy link
Contributor

@monfresh monfresh May 1, 2018

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.
@stevegsa stevegsa force-pushed the stevegsa-fix-saml-logout-double-render-error-on-bad-packet branch from d63443c to 0401ada Compare April 30, 2018 21:05
Copy link
Contributor

@monfresh monfresh left a comment

Choose a reason for hiding this comment

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

LGTM

@stevegsa stevegsa merged commit c9fa980 into master May 1, 2018
@amathews-fs amathews-fs deleted the stevegsa-fix-saml-logout-double-render-error-on-bad-packet branch January 7, 2021 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants