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

Raise exception on CSRF failure #1394

Merged
merged 1 commit into from
May 20, 2024
Merged

Conversation

chrisroos
Copy link
Contributor

This was previously enabled in PR #1375 but then reverted in PR #1383 when it was discovered that enabling it had silently broken the ability for Release API clients to create deployment records because they don't (and shouldn't need to) send the CSRF token in the request.

I'm avoiding the problem seen in PR #1375 by skipping forgery protection if we detect a Bearer token in the Authorization HTTP Header. I'm doing this in the same way that GDS::SSO checks whether the gds_sso Warden strategy is valid or whether it needs to use the gds_bearer_token strategy instead so I'm fairly confident this is good enough to distinguish an API request from a browser request.

One of the two new controller tests should fail if we either:

  • remove the with: :exception option to protect_from_forgery
  • require the CSRF token when an API client authenticates using a Bearer token and creates a deployment

Note that I'm assuming that Deployments#create is the only API endpoint. If it turns out there are more API endpoints then we'll need to make the same change to those.

I was interested to learn that raising an exception is the default behaviour in new Rails apps but that we were overriding that default with our explicit call to protect_from_forgery without any arguments. Adding protect_from_forgery with: :exception is the same as removing protect_from_forgery entirely, although I think the former is more explicit.

@chrisroos
Copy link
Contributor Author

Hi @theseanything and @sengi. I spent some time looking into this after @theseanything suggested that we might need to make a change to gds-sso to handle the problem you were seeing. If I've understood the problem correctly then I think this PR demonstrates that we don't need to make a change to gds-sso but I'd appreciate getting your thoughts on it.

Copy link
Contributor

@theseanything theseanything left a comment

Choose a reason for hiding this comment

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

@chrisroos thanks for the PR! I think this would be okay to go in for now. This implementation might not scale well if we find more apps and places with a mix of APIs and HTML endpoints - (in which case might be useful to have a helper in GDS::SSO).

@MuriloDalRi
Copy link
Contributor

@chrisroos @theseanything is this still needed or being worked on? Can we close it or make it a draft?

@theseanything
Copy link
Contributor

@chrisroos @theseanything is this still needed or being worked on? Can we close it or make it a draft?

This issue still needs to be resolved, as I said this implementation is fine to fix the immediate problem. @chrisroos is no longer able to work on this.

@AgaDufrat
Copy link
Contributor

Created a Trello card for this and reverting to draft.

@AgaDufrat AgaDufrat marked this pull request as draft May 3, 2024 08:43
This was previously enabled in PR #1375 but then reverted in PR #1383
when it was discovered that enabling it had silently broken the ability
for Release API clients to create deployment records because they don't
(and shouldn't need to) send the CSRF token in the request.

I'm avoiding the problem seen in PR #1375 by skipping forgery protection
if we detect a Bearer token in the Authorization HTTP Header. I'm doing
this in the same way that GDS::SSO checks whether the `gds_sso` Warden
strategy is valid[1] or whether it needs to use the `gds_bearer_token`
strategy instead[2] so I'm fairly confident this is good enough to
distinguish an API request from a browser request.

One of the two new controller tests should fail if we either:

- remove the `with: :exception` option to `protect_from_forgery`
- require the CSRF token when an API client authenticates using a Bearer
  token and creates a deployment

Note that I'm assuming that `Deployments#create` is the only API
endpoint. If it turns out there are more API endpoints then we'll need
to make the same change to those.

I was interested to learn that raising an exception is the default
behaviour in new Rails apps[3] but that we were overriding that default
with our explicit call to `protect_from_forgery` without any arguments.
Adding `protect_from_forgery with: :exception` is the same as removing
`protect_from_forgery` entirely, although I think the former is more
explicit.

[1]: https://github.com/alphagov/gds-sso/blob/8cc1427bfcd3cbfa24904040c8eaccff45434322/lib/gds-sso/warden_config.rb#L38
[2]: https://github.com/alphagov/gds-sso/blob/8cc1427bfcd3cbfa24904040c8eaccff45434322/lib/gds-sso/warden_config.rb#L64
[3]: https://guides.rubyonrails.org/security.html#required-security-token
@AgaDufrat AgaDufrat force-pushed the raise-exception-on-forged-requests branch from fce2d50 to 201b97b Compare May 17, 2024 15:04
@AgaDufrat AgaDufrat marked this pull request as ready for review May 17, 2024 15:26
@AgaDufrat AgaDufrat merged commit cad067f into main May 20, 2024
10 checks passed
@AgaDufrat AgaDufrat deleted the raise-exception-on-forged-requests branch May 20, 2024 09:55
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.

4 participants