Skip to content

Commit

Permalink
Enable Request Forgery Protection in test
Browse files Browse the repository at this point in the history
If we're feeling skeptical that the application's behavior _does_ meet
the criteria as defined in our test suite, we can boot it locally and
visit it in a web browser ourselves:

```bash
$ rails server --port 3000
```

Once it's running, we can follow the instructions described in our
system test by opening a web browser and:

* visiting [http://localhost:3000/][]
* clicking on "Share a Note"
* filling in the text box labelled "Message" with the value "Hello,
  World"
* clicking on "Share"

Oh no!

Surprisingly, our server responds to our submission with an error page.

If we inspect our `rails server` process log, it contains the following
output:

```
Started POST "/notes" for ::1 at 2019-05-04 13:37:35 -0400
Processing by NotesController#create as HTML
  Parameters: {"content"=>"Hello, World"}
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms | Allocations: 461)

ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
```

By default, Rails comes with some security-minded default behavior. In
this case, the error's mention of being unable to `verify CSRF token
authenticity` stems from Rails' [Cross Site Request Forgery
Protection][csrf].

The Rails Security Guidelines describe <abbr title="Cross Site Request
Forgery">CSRF</abbr>:

> This attack method works by including malicious code or a link in a
> page that accesses a web application that the user is believed to have
> authenticated. If the session for that web application has not timed
> out, an attacker may execute unauthorized commands.

By default, this protective measure is in place in every [Rails
Environment][rails-env] _except for `test`_.

To ensure that _all_ environments have this protection in place, this
commit [enables CSRF protection in `test.rb`][configuring-controllers].

When we run the test again, it is no longer passing.

It fails with a new error:

```
Error:
UserSharesAMessageTest#test_visiting_the_index:
DRb::DRbRemoteError: ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken)
```

In this instance, regressing from the Green Phase to the Red Phase has a
positive effect. Since our `test` environment's behavior did not have
[parity] with the other environments, a test failure uncovering that
fact is helpful and important to address.

In cases like this that uncover important gaps in behavior, we can
consider transitioning from the Green Phase to Red Phase as a temporary
(but helpful!) detour toward the Refactoring Phase.

[csrf]: https://guides.rubyonrails.org/v5.2/security.html#cross-site-request-forgery-csrf
[rails-env]: https://guides.rubyonrails.org/v5.2/configuring.html#creating-rails-environments
[configuring-controllers]: https://guides.rubyonrails.org/v5.2/configuring.html#configuring-action-controller
[parity]: https://12factor.net/dev-prod-parity
  • Loading branch information
seanpdoyle committed May 4, 2019
1 parent ff053f6 commit e2a17db
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion config/environments/test.rb
Expand Up @@ -27,7 +27,7 @@
config.action_dispatch.show_exceptions = false

# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
config.action_controller.allow_forgery_protection = true

# Store uploaded files on the local file system in a temporary directory.
config.active_storage.service = :test
Expand Down

0 comments on commit e2a17db

Please sign in to comment.