簡単にできそうなのですが、なかなか良い方法がなく。。質問させていただきます。
▼ゴールは、下記のように devtoolで SameSiteの値に「None」が入っていることです。 ※図はJavaScriptで実装しました
▼apidockのcookieのページをみても、 httponly
や secure
はあるのに、samesite
はありません…。
https://apidock.com/rails/ActionDispatch/Cookies
session_storeはredisを使っていて、cookiesは別の値を管理しています。
以下、試してみたことです。
1. cookiesのリファレンスにはないが、かき加えてみた
▼元の記述
cookies.permanent[:key] = value
▼書き換えてみた
cookies.permanent[:key] = { value: value, samesite: 'none' }
反映されませんでした。
2.secureheader(gem)を使ってみた
https://morizyun.github.io/ruby/library-secureheaders.html
入れてみましたが、cookiesにはSameSiteは反映されず、またgemインストール直後から他で予期せぬ設定変更が起きてしまい、外しました。
(丁寧に設定をオーバーライドしていけば正常に動くかもしれませんが、影響範囲が大きく確認の工数が上がりそうなので諦めました)
直接cookie文字列の書き換えができたらと思うのですが…
何か良い方法ご存知の方がいらっしゃいましたら、ご教示いただけますと幸いです。
ちなみにこの変更の目的は、chromeのcookieがデフォルトでSameSite=Laxになるらしいというものの対策になります。(プロダクトがWebにiframeで埋め込むタイプのものになるので、必要なものかと)
https://www.chromestatus.com/feature/5088147346030592
何卒、よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答3件
0
最終的に、プルリクがあがっている修正部分を、initializers/にmonkey patchを置いて、オーバーライドする形で実装しました。
今回は、SameSite=None
であればよいので直接かいています。
正式アップデートがあれば、アップデート対応したいと思います。
わりと裏技的実装だと思うのですが、まずい点等あれば教えてもらえたら嬉しいです。。
▼対象コミット
rails/actionpack/lib/action_dispatch/middleware/cookies.rb
https://github.com/rails/rails/commit/e3e79fc0e167a00749731708991b650e3828e8d2#diff-69714203ccef60fcead8d4eff741a883
rack/utils.rb
https://github.com/rack/rack/commit/c859bbf7b53cb59df1837612a8c330dfb4147392#diff-7c1a24d5b2fe58a6f925c7cacc6c55e7
initializers/cookie_samesite_patch.rb
Ruby
1 2module ActionDispatch 3 class Cookies 4 class CookieJar #:nodoc: 5 def handle_options(options) # :nodoc: 6 if options[:expires].respond_to?(:from_now) 7 options[:expires] = options[:expires].from_now 8 end 9 10 options[:path] ||= "/" 11 12 options[:same_site] = 'None' 13 14 if options[:domain] == :all || options[:domain] == "all" 15 # If there is a provided tld length then we use it otherwise default domain regexp. 16 domain_regexp = options[:tld_length] ? /([^.]+.?){#{options[:tld_length]}}$/ : DOMAIN_REGEXP 17 18 # If host is not ip and matches domain regexp. 19 # (ip confirms to domain regexp so we explicitly check for ip) 20 options[:domain] = if (request.host !~ /^[\d.]+$/) && (request.host =~ domain_regexp) 21 ".#{$&}" 22 end 23 elsif options[:domain].is_a? Array 24 # If host matches one of the supplied domains without a dot in front of it. 25 options[:domain] = options[:domain].find { |domain| request.host.include? domain.sub(/^./, "") } 26 end 27 end 28 end 29 end 30end 31 32module Rack 33 module Utils 34 def add_cookie_to_header(header, key, value) 35 case value 36 when Hash 37 domain = "; domain=#{value[:domain]}" if value[:domain] 38 path = "; path=#{value[:path]}" if value[:path] 39 max_age = "; max-age=#{value[:max_age]}" if value[:max_age] 40 # There is an RFC mess in the area of date formatting for Cookies. Not 41 # only are there contradicting RFCs and examples within RFC text, but 42 # there are also numerous conflicting names of fields and partially 43 # cross-applicable specifications. 44 # 45 # These are best described in RFC 2616 3.3.1. This RFC text also 46 # specifies that RFC 822 as updated by RFC 1123 is preferred. That is a 47 # fixed length format with space-date delimited fields. 48 # 49 # See also RFC 1123 section 5.2.14. 50 # 51 # RFC 6265 also specifies "sane-cookie-date" as RFC 1123 date, defined 52 # in RFC 2616 3.3.1. RFC 6265 also gives examples that clearly denote 53 # the space delimited format. These formats are compliant with RFC 2822. 54 # 55 # For reference, all involved RFCs are: 56 # RFC 822 57 # RFC 1123 58 # RFC 2109 59 # RFC 2616 60 # RFC 2822 61 # RFC 2965 62 # RFC 6265 63 expires = "; expires=" + 64 rfc2822(value[:expires].clone.gmtime) if value[:expires] 65 secure = "; secure" if value[:secure] 66 httponly = "; HttpOnly" if (value.key?(:httponly) ? value[:httponly] : value[:http_only]) 67 same_site = 68 case value[:same_site] 69 when false, nil 70 nil 71 when :none, 'None', :None 72 '; SameSite=None' 73 when :lax, 'Lax', :Lax 74 '; SameSite=Lax'.freeze 75 when true, :strict, 'Strict', :Strict 76 '; SameSite=Strict'.freeze 77 else 78 raise ArgumentError, "Invalid SameSite value: #{value[:same_site].inspect}" 79 end 80 value = value[:value] 81 end 82 value = [value] unless Array === value 83 84 cookie = "#{escape(key)}=#{value.map { |v| escape v }.join('&')}#{domain}" \ 85 "#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}" 86 87 case header 88 when nil, '' 89 cookie 90 when String 91 [header, cookie].join("\n") 92 when Array 93 (header + [cookie]).join("\n") 94 else 95 raise ArgumentError, "Unrecognized cookie header value. Expected String, Array, or nil, got #{header.inspect}" 96 end 97 end 98 module_function :add_cookie_to_header 99 end 100end 101 102
投稿2019/09/09 05:26
総合スコア24
0
ベストアンサー
Rails 本体に関してはまさに PR が開かれているようです。
rails/rails #28297
そのためRails デフォルトの方法ではまだ不可能ということになりますので、 Rack middleware なりを用意して Rack レベルでセットする必要がありそうです。
参考 How do I set a cookie with a (ruby) rack middleware component?
投稿2019/09/04 01:12
編集2019/09/04 01:13総合スコア1531
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
※自己解決方法にかいたつもりでしたが回答してました。。削除がすぐにできなかったので、重複しますがこちらにもかいておきます。
最終的に、プルリクがあがっている修正部分を、initializers/にmonkey patchを置いて、オーバーライドする形で実装しました。
今回は、SameSite=None
であればよいので直接かいています。
正式アップデートがあれば、アップデート対応したいと思います。
わりと裏技的実装だと思うのですが、まずい点等あれば教えてもらえたら嬉しいです。。
▼対象コミット
rails/actionpack/lib/action_dispatch/middleware/cookies.rb
https://github.com/rails/rails/commit/e3e79fc0e167a00749731708991b650e3828e8d2#diff-69714203ccef60fcead8d4eff741a883
rack/utils.rb
https://github.com/rack/rack/commit/c859bbf7b53cb59df1837612a8c330dfb4147392#diff-7c1a24d5b2fe58a6f925c7cacc6c55e7
initializers/cookie_samesite_patch.rb
Ruby
1 2module ActionDispatch 3 class Cookies 4 class CookieJar #:nodoc: 5 def handle_options(options) # :nodoc: 6 if options[:expires].respond_to?(:from_now) 7 options[:expires] = options[:expires].from_now 8 end 9 10 options[:path] ||= "/" 11 12 options[:same_site] = 'None' 13 14 if options[:domain] == :all || options[:domain] == "all" 15 # If there is a provided tld length then we use it otherwise default domain regexp. 16 domain_regexp = options[:tld_length] ? /([^.]+.?){#{options[:tld_length]}}$/ : DOMAIN_REGEXP 17 18 # If host is not ip and matches domain regexp. 19 # (ip confirms to domain regexp so we explicitly check for ip) 20 options[:domain] = if (request.host !~ /^[\d.]+$/) && (request.host =~ domain_regexp) 21 ".#{$&}" 22 end 23 elsif options[:domain].is_a? Array 24 # If host matches one of the supplied domains without a dot in front of it. 25 options[:domain] = options[:domain].find { |domain| request.host.include? domain.sub(/^./, "") } 26 end 27 end 28 end 29 end 30end 31 32module Rack 33 module Utils 34 def add_cookie_to_header(header, key, value) 35 case value 36 when Hash 37 domain = "; domain=#{value[:domain]}" if value[:domain] 38 path = "; path=#{value[:path]}" if value[:path] 39 max_age = "; max-age=#{value[:max_age]}" if value[:max_age] 40 # There is an RFC mess in the area of date formatting for Cookies. Not 41 # only are there contradicting RFCs and examples within RFC text, but 42 # there are also numerous conflicting names of fields and partially 43 # cross-applicable specifications. 44 # 45 # These are best described in RFC 2616 3.3.1. This RFC text also 46 # specifies that RFC 822 as updated by RFC 1123 is preferred. That is a 47 # fixed length format with space-date delimited fields. 48 # 49 # See also RFC 1123 section 5.2.14. 50 # 51 # RFC 6265 also specifies "sane-cookie-date" as RFC 1123 date, defined 52 # in RFC 2616 3.3.1. RFC 6265 also gives examples that clearly denote 53 # the space delimited format. These formats are compliant with RFC 2822. 54 # 55 # For reference, all involved RFCs are: 56 # RFC 822 57 # RFC 1123 58 # RFC 2109 59 # RFC 2616 60 # RFC 2822 61 # RFC 2965 62 # RFC 6265 63 expires = "; expires=" + 64 rfc2822(value[:expires].clone.gmtime) if value[:expires] 65 secure = "; secure" if value[:secure] 66 httponly = "; HttpOnly" if (value.key?(:httponly) ? value[:httponly] : value[:http_only]) 67 same_site = 68 case value[:same_site] 69 when false, nil 70 nil 71 when :none, 'None', :None 72 '; SameSite=None' 73 when :lax, 'Lax', :Lax 74 '; SameSite=Lax'.freeze 75 when true, :strict, 'Strict', :Strict 76 '; SameSite=Strict'.freeze 77 else 78 raise ArgumentError, "Invalid SameSite value: #{value[:same_site].inspect}" 79 end 80 value = value[:value] 81 end 82 value = [value] unless Array === value 83 84 cookie = "#{escape(key)}=#{value.map { |v| escape v }.join('&')}#{domain}" \ 85 "#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}" 86 87 case header 88 when nil, '' 89 cookie 90 when String 91 [header, cookie].join("\n") 92 when Array 93 (header + [cookie]).join("\n") 94 else 95 raise ArgumentError, "Unrecognized cookie header value. Expected String, Array, or nil, got #{header.inspect}" 96 end 97 end 98 module_function :add_cookie_to_header 99 end 100end 101 102
投稿2019/09/09 05:29
総合スコア24
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。