開発環境
- フロントはReact、バックはLaravelのSPA
- フロントの開発はwebpack-dev-serverを立ち上げ、LaravelのAPIを叩きにいく感じ
- 本番環境はbuildしたJSを含むLaravelで動いている
- 認証はセッションで行う
序章
フロントの開発環境からログインできない事態が発生。
ログイン後も色々とAPIを叩いているので今更モック作ってとかも辛い状況。
結論
ログイン時にサーバーが発行したCookieをクライアントが受け取れていなかった。
認証はセッションで行なっているので、Cookieを受け取れないとForeverステートレスな状態。
原因
Chrome84からCookieの属性であるSameSite
のデフォルト値がNone
からLax
変更されたことにより、異なるオリジン間でCookieが受け取れなくなっていた。
明示的にSameSite=None
を設定することでCookieを受け取れるようにはなるが、そうすると次はCookieの属性であるSecure
も必須となる。
Secure 属性がついたクッキーは HTTPS プロトコル上の暗号化されたリクエストでのみサーバーに送信され、安全でない HTTP では決して送信されない
ちなみにSameSite
の設定exampleがGitHubで公開されています
なぜ今気がついたのか
- 前任者から引き継いだ後、プロジェクトがしばらく動いていなかった
- プロジェクトが動き始めた当初はログイン前のUI構築がメインだった
どうするのか
ローカル環境をSSLする必要があるのかと思ったらdevserver
のproxy
オプションで解決した。
同一オリジン扱いになるのでCORS問題も解決できそう。
module.exports = {
//...
devServer: {
static: {
directory: path.join(__dirname, 'public'),
},
port: 3000,
},
proxy: {
'/api': 'http://localhost:5000',
},
},
}
上記の場合、http://localhost:3000/api/user
へのリクエストはhttp://localhost:5000/api/user
にプロキシされる。
HTTPSで動作しているバックエンドサーバーの場合
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'https://other-server.example.com',
secure: false,
},
},
},
}
複数のパスをプロキシしたい場合
module.exports = {
//...
devServer: {
proxy: [
{
context: ['/auth', '/api'],
target: 'http://localhost:5000',
},
],
},
}
参考資料