Search code examples
ruby-on-railscsrfrefinerycms

How do I generate a CSRF token from the Rails console?


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


Solution

  • 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