1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

クロスオリジン間でCookieを共有する

Posted at

概要

構成はNuxt.jsとRailsのAPIモード。

ローカルでは問題なかったのですが、
STGと本番環境にあげた際にクロスオリジン間でCookiesの保存ができなかった経験があり、
色々と設定に苦しんだので備忘録としてまとめます。

この記事で話すこと

  • クロスオリジン間でのCookieを共有するための設定方法

この記事で話さないこと

  • クロスオリジンとは何か
  • gem 'rack-cors'によるCORSの設定

本題

実現したかったこと

ActionCable使って特定のユーザーに配信を行いたく、
以下のようにユーザーの識別のためにランダムな文字列を発行しcookieに保存したかった。

# 例 ※実際の実装内容とは異なります
def set_code
  # cookieを見て識別子が保存されていなければ発行
  cookies[:user_code] ||= SecureRandom.hex
end

が、毎回保存できておらず識別子が生成されてしまっていた。

解決方法

バックエンドとフロントエンドの両方で諸々の設定をしました。
まずはバックエンドのRailsから。

Cookieを使うための準備

RailsのAPIモードの場合、このままではcookieが使えないので設定をする必要があります。

application_controller.rb
class ApplicationController < ActionController::API
    include ActionController::Cookies # これを追加する

次に、RailsのAPIモードではCookieを処理するミドルウェアがないため、
application.rbに次の設定を追加します。

application.rb
module App
  class Application < Rails::Application
    # ・・・
    config.middleware.use ActionDispatch::Cookies
    config.action_dispatch.cookies_same_site_protection = :none
    # ・・・
  end
end

※cookies_same_site_protectionはRails6.1で追加された設定のようです。
参考:https://qiita.com/SoarTec-lab/items/10280dbea1195bf21b3c

CORSの設定

現状の設定ではフロントエンドとバックエンドのオリジンが異なる場合に
ブラウザに保存ができないので、次はCORSの設定をします。

許可したいオリジンを指定するのに加え、
credentials: trueの設定が必要となります。

これでクロスオリジン間でcookieが使用できます。

cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins "http://localhost:8080" # ここに許可するオリジンの指定。正規表現も使えるので、可能であればそれで指定する方がベターだと思います。

    resource "*",
      headers: :any,
      credentials: true, # これが必要!!!
      methods: [:get, :post, :options, :delete, :put, :patch]
  end
end

CookieのSecure属性を追加

SameSite属性がNoneの場合、
Secure属性も付与しなければいけないため次のようにします。
(※開発環境ではなくても動きました)

def set_code
  # cookieを見て識別子が保存されていなければ発行
- cookies[:user_code] ||= SecureRandom.hex
+ cookies[:user_code] ||= {value: SecureRandom.hex, http_only: true, secure: true}
end

Nuxt.jsの設定

フロントエンドはNuxt.jsを使用していたため、
次のように設定を追加しました。

credentials: trueを追加することで、リクエストヘッダーのwithCredentialsをtrueにします。
参考:https://axios.nuxtjs.org/options/#credentials

ドメインにcookieを設定する際にこちらが必要となるようです。

異なるドメインからの XMLHttpRequest のレスポンスは、リクエストを行う前に withCredentials を true に設定しない限り、自身のドメインの Cookie 値を設定することができません。
https://developer.mozilla.org/ja/docs/Web/API/XMLHttpRequest/withCredentials

nuxt.config.js
// ・・・
axios: {
    // ・・・
    credentials: true
  },
// ・・・

最後に

これだけ諸々の設定をしてようやく望み通りの動作が実現できました。
CORSやCookieのいい勉強になりました。

もし間違っている点や、
もっとこうした方がいいよなどあればコメント頂けますと幸いです。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?