I'm trying to make an authenticated post request, and I need the CSRF. When I log in, it isn't generating the _csrf_token
for some reason:
2.0.0p247 :126 > app.post '/community_members/login', {"refinery_user[login]"=>'chloe', 'refinery_user[password]'=>'test'}
=> 302
2.0.0p247 :127 > app.session
=> {"warden.user.refinery_user.key"=>[[56], "$2a$10$gr/rTcQfuXnes1Zml3qOPu"], "session_id"=>"f77d89cef9ff1710890f575b479bb690"}
I tried app.session[:_csrf_token] ||= SecureRandom.base64(32)
before login, but it is always deleted. I also tried to get the login form first, but _csrf_token
is still not set.
2.0.0p247 :133 > app.get '/community_members/sign_in'
2.0.0p247 :134 > app.response # authenticity_token is burried in the raw HTML
2.0.0p247 :136 > app.post '/community_members/login', {"refinery_user[login]"=>'chloe', 'refinery_user[password]'=>'test'}
2.0.0p247 :137 > app.session
=> {"warden.user.refinery_user.key"=>[[56], "$2a$10$gr/rTcQfuXnes1Zml3qOPu"], "session_id"=>"c2c564229e55b81ca788788558d7d11a"}
How do I manually generate the token to pass to the post request?
Oh ok, I think I need to submit the authenticity_token (that is set in the session after GETing the login form) to the login form, then it puts it in the session permanently! This worked:
app.post '/community_members/login', {'authenticity_token'=>'GfT5GtcUmYQ927oNQmh2MR0NKQucGSx8mtMg3Ph9kXw=', "refinery_user[login]"=>'chloe', 'refinery_user[password]'=>'test'}
Here is a full example: https://stackoverflow.com/a/23899701/148844
I felt like using Nokogiri to parse the response was a little heavy so I wrote a simple regex to pull the authenticity token out of the response.
app.get '/api_with_form'
authenticity_token = app.response.body.match(/<[^<]+authenticity_token[^>]+value="([^"]+)"[^>]+>/)[1]
I'm using this to log in
app.get '/users/sign_in'
authenticity_token = app.response.body.match(/<[^<]+authenticity_token[^>]+value="([^"]+)"[^>]+>/)[1]
app.post '/users/sign_in', 'user[email]' => 'my_username', 'user[password]' => 'my_password', authenticity_token: authenticity_token
Unless you load the page before you do app.post
, there is no CSRF token generated to begin with. Manually generating a new one will not help because it won't match what is stored on the server, which is likely to be some null
value.
You need to load the page, parse out the CSRF token, and then use that one.
Alternately, you can load the form, try to read the CSRF token out of app.session[:_csrf_token]
and use that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With