Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4: How to set cookies in redirect?

I have a controller that attempts takes form inputs, set values in a cookie and then redirect to a page that will pull from that cookie.

The problem is that the cookie is never set in the redirect headers.

Notes: I've tested in Chrome and FF. Rails version is 4.0.13. Setting cookies w/o a redirect works as expected.

Here's the controller code:

def create
  request.cookies[:foo] = "bar"

  # also tried:
  #   cookies[:foo]="bar"
  #   cookies.signed[:foo]="bar"
  #   cookies[:foo] = {
  #     value: "bar",
  #     expires: 1.month.from_now,
  #     domain: ".myapplicationhostname.com"
  #   }

  redirect_to root_url
end

The response header on the redirect doesn't contain a Set-Cookie attribute and as such, the cookie values aren't available in the controller/action in the redirected-to path.

I've found some contradictory evidence that some browsers don't accept cookies in redirects, but it appears that that's not the case anymore? And anyways, neither FF or Chrome are showing a Set-Cookie in the response header, so it doesn't appear this is a browser issue.

Here's the header response from cURL, note the lack of Set-Cookie:

HTTP/1.1 302 Moved Temporarily
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-UA-Compatible: chrome=1
Location: http://app.mydomain.com:3000/
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
X-Request-Id: 1fc1c7e5-7489-4720-bb70-28588f3abcb6
X-Runtime: 4.688166
Connection: close
Server: thin 1.6.2 codename Doc Brown

How do I get rails to set cookies (or at least set the header) on redirects?

like image 973
Bryan Marble Avatar asked Apr 11 '15 11:04

Bryan Marble


1 Answers

It appears that the cause of this is actually CSRF protection kicking in. The controller had instantiated a NullCookieJar which prevents the writing of cookies when there's a potentially forged POST.

This is because my controller was being set up to respond to an off-site form, thus no access to the CSRF token.

So, if you're running into this when submitting an off-site form to your Rails app, you'll need to disable the CSRF check or write your own verification method as described in the answer to the SO question: "Receive POST from External Form".

Summarized here:

Disabling Check

skip_before_filter :verify_authenticity_token, only: :my_action

Custom Check

skip_before_filter :verify_authenticity_token, :only => :my_action
before_filter :verify_custom_authenticity_token, :only => :my_action

def verify_custom_authenticity_token
  # checks whether the request comes from a trusted source
end
like image 130
Bryan Marble Avatar answered Nov 14 '22 21:11

Bryan Marble