問題
domain.tld (frontend) -> login.domain.tld (backend)
- frontendとbackendがある
- backendはサブドメインだ(その反対、両方でも可)
- 両方のドメインでセッションクッキーを保持したい
- 認証はgraphql経由(ApolloClient使用)
- とりあえずbackendはRailsだ(API only)
解決
- corsの問題はクリアしておく
- サーバー側のcookie関係なくgraphqlで通信は可能な状態にしておく
- API onlyモードのRailsではcookieはデフォルトONではない
- セッションcookieももちろんONではない
- cookieをONにしてもデフォルトではサブドメインとcookietは共有しない
Rails側
cookieをONにする
application.rb
# dev、prod関係なく全体にcookieは必要だと思うのでここで設定
module App
class Application < Rails::Application
...
...
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore,
domain: :all,
tld_length: 2,
secure: true,
same_site: :strict
end
end
- domain:
:all
でどんなサブドメインとも共有 - tld_length: 自分のドメインが
domain.tld
、サブドメインがa.domain.tld
だったとして、tld_length: 2
はdomain.tld
になる。
これがbase.domain.tld
、sub.base.domain.tld
とかでbase.domain.tld
を軸としてのサブドメイン共有であればtld_length: 3
=base.domain.tld
とする。 - secureとsame_siteは別の話
tld_length
a.b.c.domain.tld
- tld_length: 2 => domain.tld ベース
- tld_length: 3 => c.domain.tld ベース
- tld_length: 4 => b.c.domain.tld ベース
application_controller.rb
class ApplicationController < ActionController::API
include ActionController::Cookies
end
これがないとcookieは動かない。
sessionをgraphqlで使う
graphql_controller.rb
class GraphqlController < ApplicationController
def execute
...
...
context = {
session: session,
}
end
context経由でsessionオブジェクトを渡しておいて、query、mutationでcontext[:session]
経由で使う。
subscriptionをActionCable経由で使う場合
ActionCable内でsessionをとってくる事前の設定は全て済んでいるとして
graphql_channel.rb
class GraphqlChannel < ApplicationCable::Channel
def execute(data)
...
...
...
context = { channel: self, session: session }
ここでも同じようにcontext経由でsessionオブジェクトを渡す。
Apollo側の設定
You just need to pass the credentials option. e.g. credentials: 'same-origin' as shown below, if your backend server is the same domain or else credentials: 'include' if your backend is a different domain.
linkオブジェクト
- credentials: include
これだけ
動作確認
domain.tldからbackend.domain.tldへのgraphql呼び出し
sessionを使うgraphqlを呼んだ時に、こういう風にcookieができていればOK。