A cookie associated with a cross-site resource at https://example.com/ was set without the SameSite
attribute. It has been blocked, as Chrome now only delivers
Action dispatch cookies is responsible for writing cookies to browser set in application, this uses Rack::Utils.set_cookie_header!
.
Support for SameSite
has been added after rack version 1.6, you need to check your rack version in Gemfile and if it is < 1.6 you need to add the following code in config/initializers
require 'rack/utils'
module Rack
module Utils
def self.set_cookie_header!(header, key, value)
case value
when Hash
domain = "; domain=" + value[:domain] if value[:domain]
path = "; path=" + value[:path] if value[:path]
max_age = "; max-age=" + value[:max_age] if value[:max_age]
expires = "; expires=" +
rfc2822(value[:expires].clone.gmtime) if value[:expires]
secure = "; secure" if value[:secure]
httponly = "; HttpOnly" if value[:httponly]
same_site =
case value[:same_site]
when false, nil
nil
when :none, 'None', :None
'; SameSite=None'
when :lax, 'Lax', :Lax
'; SameSite=Lax'
when true, :strict, 'Strict', :Strict
'; SameSite=Strict'
else
raise ArgumentError, "Invalid SameSite value: #{value[:same_site].inspect}"
end
value = value[:value]
end
value = [value] unless Array === value
cookie = escape(key) + "=" +
value.map { |v| escape v }.join("&") +
"#{domain}#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}"
case header["Set-Cookie"]
when nil, ''
header["Set-Cookie"] = cookie
when String
header["Set-Cookie"] = [header["Set-Cookie"], cookie].join("\n")
when Array
header["Set-Cookie"] = (header["Set-Cookie"] + [cookie]).join("\n")
end
nil
end
end
end
Once done you can set SameSite
attribute while creating a new cookie, for ex:
cookies['testing'] = {
value: 'test',
path: '/',
expiry: 1.weeks.from_now,
same_site: :none
}
you can also add the same_site: <value>
to your session store as well.
Hope this helps!
In Rails 6.0 and 6.1 the same_site attribute has been added:
cookies["foo"] = {
value: "bar",
secure: Rails.application.config.secure_cookies,
same_site: "None"
}
For Rails 5.x and lower, the rails_same_site_cookie gem is a good option for adding SameSite=None;
to all your app's cookies. It uses middleware to do it.
A backport of fixes to rack was contributed here.
https://github.com/rack/rack/pull/1547
It won't be released, so you'll likely need to use a fork of rack in your Gemfile
.
https://bundler.io/v1.17/guides/git.html
The way to set custom headers is to add the line below to your controller action:
response.headers['Set-Cookie'] = 'Secure;SameSite=None'
.
What I did is the following:
In session_store.rb
I configured:
MyApp::Application.config.session_store :cache_store, key: COOKIE_NAME, :expire_after => 1.days, :expires_in => 1.days, :domain => 'mydomain.com', same_site: :none
And I added this monkey patch:
require 'rack/utils'
module Rack
module Utils
def self.set_cookie_header!(header, key, value)
case value
when Hash
domain = "; domain=" + value[:domain] if value[:domain]
path = "; path=" + value[:path] if value[:path]
max_age = "; max-age=" + value[:max_age] if value[:max_age]
expires = "; expires=" +
rfc2822(value[:expires].clone.gmtime) if value[:expires]
# Make it always secure, even in HTTP
# secure = "; secure" if value[:secure]
secure = "; secure"
httponly = "; HttpOnly" if value[:httponly]
same_site =
case value[:same_site]
when false, nil
nil
when :none, 'None', :None
'; SameSite=None'
when :lax, 'Lax', :Lax
'; SameSite=Lax'
when true, :strict, 'Strict', :Strict
'; SameSite=Strict'
else
raise ArgumentError, "Invalid SameSite value: #{value[:same_site].inspect}"
end
value = value[:value]
end
value = [value] unless Array === value
cookie = escape(key) + "=" +
value.map { |v| escape v }.join("&") +
"#{domain}#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}"
case header["Set-Cookie"]
when nil, ''
header["Set-Cookie"] = cookie
when String
header["Set-Cookie"] = [header["Set-Cookie"], cookie].join("\n")
when Array
header["Set-Cookie"] = (header["Set-Cookie"] + [cookie]).join("\n")
end
nil
end
end
end