laracasts / Behat-Laravel-Extension

Laravel extension for Behat functional testing.
MIT License
260 stars 73 forks source link

CSRF token empty when using this extension #62

Open Harrisonbro opened 7 years ago

Harrisonbro commented 7 years ago

We're trying to use this extension to test our application but are finding that then CRSF tokens put into forms with csrf_field () are empty. When using the application normally through a web browser the tokens are included in the form and work correctly. However, when running a Behat test and dumping the page output I can see that we just get <input name="_token" type="hidden"> (i.e. it contains no value).

In my attempts to debug it does seem that a token is getting generated since Illuminate\Session\Store::regenerateToken() is being called. However, it seems that the session store object that first generates the CSRF token and the one that is subsequently asked for it in the form as different objects — see output below from a var_dump in both Collective\Html\FormBuilder::token() (which we're using to build our forms) and Illuminate\Session\Store::regenerateToken(). You can see that the spl_object_hash values are different so I can only assume that the token is getting lost between the two instances of Illuminate\Session\Store.

How are CSRF tokens supposed to be stored? If it's in the Laravel session, should this extension be able to cope with that and use a persistent session? If not, is there anything obvious that I need to change.

array(4) {
  [0]=>
  string(51) "★★★ Illuminate\Session\Store::regenerateToken"
  ["session class"]=>
  string(24) "Illuminate\Session\Store"
  ["spl_object_hash"]=>
  string(32) "000000001223f2a1000000001315d23b"
  ["current result of Illuminate\Session\Store::getToken()"]=>
  string(40) "1mRtRhUV3ZZifXHIZmzxYIqFrzDzqDyHqnsyZPEl"
}
array(4) {
  [0]=>
  string(44) "★★★ Collective\Html\FormBuilder::token"
  ["session class"]=>
  string(24) "Illuminate\Session\Store"
  ["session object hash"]=>
  string(32) "000000001223f215000000001315d23b"
  ["current result of Illuminate\Session\Store::getToken()"]=>
  NULL
}
alnutile commented 7 years ago

16 days later @Harrisonbro sorry for the delay.

I tried a few scenarios to get a sense of the error.

Here are the 4 results

csrf token before and after a form entry with the @javascript tag

https://github.com/alnutile/recipes/blob/master/tests/fixtures/login_page_javascript_before_fail.txt

https://github.com/alnutile/recipes/blob/master/tests/fixtures/login_page_javascript_after_fail.txt

and now with no @javascript tag

https://github.com/alnutile/recipes/blob/master/tests/fixtures/login_page_no_javascript_before_fail.txt

https://github.com/alnutile/recipes/blob/master/tests/fixtures/login_page_no_javascript_after_fail.txt

Both have the <input name="_token" type="hidden"> as expected.

I just happen to use the Login form since it is doing a POST features/bootstrap/LoginTrait.php:9

BUT maybe I am not fully understanding the goal or the issue?

Harrisonbro commented 7 years ago

No problem, @alnutile!

Yes, the example outputs you linked to do indeed show the _token inputs as expected. The issue I'm finding is that the token inputs are output with no value — i.e. they are just <input name="_token" type="hidden" />, not <input name="_token" type="hidden" value="E1Rc16To..." /> as you have in your outputs.

As I said, when I use a browser manually the token inputs appear as expected with a value. When I run in Behat and dump out the page I see the empty token inputs with no value.

Is there anything I can do to help debug this or provide you with more information to diagnose?