オリジン間リソース共有 (Cross-Origin Resource Sharing, CORS)において、Rails APIとフロントのfetch API間でCookieを送受信できるようにする方法について紹介します。
rack-corsの設定
rack-corsはRailsアプリケーションのCORS設定用のgemです。
CORSでCookieを送信する場合はcredentials: true
を追加します。
config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
unless Rails.env.production?
allow do
### 『localhost』『localhost:[ポート番号]』『[サブドメイン].local.example-dev.com』のオリジンを許可
origins(['localhost', /localhost:\d+\Z/, /(.+).local.example-dev.com\Z/])
resource '*',
headers: :any,
- methods: [:get, :post, :put, :patch, :delete, :options, :head]
+ methods: [:get, :post, :put, :patch, :delete, :options, :head],
+ credentials: true
end
end
end
上記の設定により、レスポンスヘッダのSet-Cookie
にCookieがセットされます。
credentials: true
がないとSet-Cookie
にCookieがセットされないため、フロント(ブラウザ)はCookieの取得ができません。
fetch APIの設定
fetch APIでCookieを取得する場合はcredentials: 'include'
を追加します。
### APIのドメインが『api.local.example-dev.com』の場合
- fetch("http://api.local.example-dev.com/[エンドポイント名]")
+ fetch("http://api.local.example-dev.com/[エンドポイント名]", { credentials: 'include' })
Rails API側のCORS設定でcredentials: true
をしていてもfetch APIでcredentials: 'include'
を追加しなければ、Set-Cookie
にセットされたCookieをブラウザにセットできません。
逆に、fetch APIでcredentials: 'include'
を設定しているのにRails API側のCORS設定でcredentials: true
をしていない場合はAccess to fetch at 'http://[APIのエンドポイント]' from origin 'http://[フロントのエンドポイント]' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.
というエラーがブラウザに発生します。
さいごに
Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!