'ActionDispatch::Cookies not setting Set-Cookie header in response but response.set_cookie does
I have a Rails 5 API only app and want to send cookies in the response of a JSON request. When I use ActionDispatch::Cookies to set a cookie in the response of the request it doesn't set Set-Cookie
header in the response. Although response.set_cookie
does work.
I also tested with making an after_action
hook in the application controller, and what I saw is Set-Cookie
header is not present in response.headers but cookies['name_of_cookie'] is present. One question I also want to ask is when do these cookies(ActionDispatch::Cookies) set header in response? Does it happen in rack?
Requirement
- We want to set cookies in CORS request.
- We want to set cookies for all the origin's
What is already implemented
- The client send a request with
withCredentials
- In the response
Access-Control-Allow-Credentials: true
andAccess-Control-Allow-Origin: <origin (request.headers['origin'])>
are present - As it is Rails API only app we have included the following middlewares in the application
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore, key: '_namespace_key'
Question
- Why ActionDispatch::Cookies is not working but response.set_cookie is working?
- When does ActionDispatch::Cookies set headers in response? Does it happen in any
after
callback hook in rails app, or it happen in rack? Because untilafter_action
in applicaton_controller the headers wasn't there.
Strange
- While in development env and on my local machine it works, but not in production. Does it have to do something with the
domain
setting of cookie? I also use secure and httponly cookie in production, but only httponly in development.
What am I missing here? I have spend days searching for the problem but I couldn't find a fix. Any lead will be very helpful. Thanks
Edit 1
cookies[@name.to_sym] = {
value: @value,
expires: @expire,
httponly: true,
same_site: 'None',
secure: false # It works when I set it to false but doesn't work with `true` in production. In development env it works with either one.
}
response.set_cookie(
@name.to_sym,
value: @value,
expires: @expire,
httponly: true,
secure: true
)
I observed one thing. If I set secure: false
in cookies then it works in production but not with secure: true
. On other hand secure: true
works with response.set_cookie in production.
My request.protocol is HTTP. Is it possible that ActionDispatch::Cookies does not even set cookies if request protocol is HTTP and secure: true
option is configured.
But I think secure: true
is for client side. Like if a cookie is secure then browser will only send it over https protocol only. What am I missing?
Solution 1:[1]
I got the reason for this behavior. Actually other team deployed an application gateway
on production. This result in the Rails server getting HTTP request which was HTTPS initially.
Now as I have marked my cookies to be secure: true
, it looks like ActionDispatch::Cookies does not even send cookies in response to a request if the protocol is HTTP. It will only send if protocol is HTTPS. If I disable the secure by secure: false
then it work or if I disable the application gateway then it work with ActionDispatch::Cookie.
It seems strange as secure
is a client side attribute, but from behaviour of ActionDispatch::Cookies it looks like it don't even send cookies from server if protocol is HTTP and secure is set to true.
Although I didn't find any documentation of this behavior, but this is how it's working.
Solution 2:[2]
Faced a similar issue but cookie was being passed as an Header. Issue was with session_expiry
which was getting set on initiation (session_store.rb
) as it was from different Time.zone
which forced the cookie to be removed by browser as soon as it got created.
Instead, I've used expire_after: 20.minutes
which made it work for me.
Posting this here, just in-case anyone faces similar issue.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Raounak Sharma |
Solution 2 | Tanmay Jain |