リダイレクトで Cookie が送信されない
◆ リダイレクトは外部ページからのアクセスというコンテキストを維持するみたい
◆ 途中で SameSite=Strict の set-cookie があると保存はされてるけど送信はされない
◆ 送信されなかったページでリロードしても送信されないまま
◆ ヘッダじゃなく JavaScript リダイレクトにすれば送信できるようになった
◆ 途中で SameSite=Strict の set-cookie があると保存はされてるけど送信はされない
◆ 送信されなかったページでリロードしても送信されないまま
◆ ヘッダじゃなく JavaScript リダイレクトにすれば送信できるようになった
set-cookie してるはずなのに Cookie が送信されなくて困ってたら またも SameSite 問題でした
リダイレクトまで影響するみたいです
[/redirect1.php]
[/redirect2.php]
[/cookie.php]
redirect1.php → redirect2.php → cookie.php という順でリダイレクトします
redirect1.php では c1 という Cookie をセットして redirect2.php では c2 という cookie をセットします
cookie.php では送信された Cookie データを表示します
redirect1.php にアクセスしたら cookie.php のページが開かれて
と表示されるのが期待する結果です
単純に /redirect1.php を開くとこうなります
しかし 外部サイトから /redirect1.php を開くと
だけになり c2 はサーバへ送信されていません
適当な外部サイトでコンソールを開いて
みたいな JavaScript を実行して試せば良いです
フォームからの POST でも一緒です
そこからリダイレクトしてるのでもう SameSite は関係ないと思ってました
実際 redirect2.php では SameSite=Strict ですが set-cookie はエラーはなくセットできています
外部からアクセスしたページで SameSite=None でない set-cookie をレスポンスで返す場合は Cookie がセットされず devtools で確認するとエラーが表示されます
セットできてるので関係ないと思っていたのに その次のリダイレクトの cookie.php では SameSite=None の方の c1 は送信されますが SameSite=Strict の c2 は送信されません
しかもこれ Cookie.php のページでリロードしても送られないままです
devtools でみてもキャッシュされてるわけではなく cookie ヘッダーが送られていません
Firefox も同じなのでバグではなくこれが正しい動きのようです
外部から POST されてきたら一時的に SameSite=None で保存して 次のリダイレクトで SameSite=Strict の Cookie に保存して そのまま SameSite=Strict にセットした Cookie を使う画面に移動したいのですけどね……
ヘッダーによるリダイレクトだとそのコンテキストを持ち続けるみたいなので JavaScript でリダイレクトさせてみると Cookie が送信されました
SameSite とか入ると変に Cookie 周りが複雑になるのが嫌なところです
これまでどおり全部 None にして 外部からの攻撃を防ぐのは サーバの API の共通前処理で Origin チェックとかトークンチェックとかでいいかなという気持ちになってきました
リダイレクトまで影響するみたいです
問題点
再現させるために次のページを用意します[/redirect1.php]
<?php
header("set-cookie: c1=value; HttpOnly; Secure; SameSite=None; Path=/");
header("Location: /redirect2.php");
[/redirect2.php]
<?php
header("set-cookie: c2=value; HttpOnly; SameSite=Strict; Path=/");
header("Location: /cookie.php");
[/cookie.php]
<?php
echo $_SERVER['HTTP_COOKIE'];
redirect1.php → redirect2.php → cookie.php という順でリダイレクトします
redirect1.php では c1 という Cookie をセットして redirect2.php では c2 という cookie をセットします
cookie.php では送信された Cookie データを表示します
redirect1.php にアクセスしたら cookie.php のページが開かれて
c1=value; c2=value
と表示されるのが期待する結果です
単純に /redirect1.php を開くとこうなります
しかし 外部サイトから /redirect1.php を開くと
c1=value
だけになり c2 はサーバへ送信されていません
適当な外部サイトでコンソールを開いて
location.href = "https://my-server/redirect1.php"
みたいな JavaScript を実行して試せば良いです
フォームからの POST でも一緒です
原因
外部からアクセスされる redirect1.php では SameSite=None の必要があるのはわかりますそこからリダイレクトしてるのでもう SameSite は関係ないと思ってました
実際 redirect2.php では SameSite=Strict ですが set-cookie はエラーはなくセットできています
外部からアクセスしたページで SameSite=None でない set-cookie をレスポンスで返す場合は Cookie がセットされず devtools で確認するとエラーが表示されます
セットできてるので関係ないと思っていたのに その次のリダイレクトの cookie.php では SameSite=None の方の c1 は送信されますが SameSite=Strict の c2 は送信されません
しかもこれ Cookie.php のページでリロードしても送られないままです
devtools でみてもキャッシュされてるわけではなく cookie ヘッダーが送られていません
Firefox も同じなのでバグではなくこれが正しい動きのようです
外部から POST されてきたら一時的に SameSite=None で保存して 次のリダイレクトで SameSite=Strict の Cookie に保存して そのまま SameSite=Strict にセットした Cookie を使う画面に移動したいのですけどね……
回避策
redirect2.php で SameSite=Strict の Cookie がセットできてしまっていますが 一応外部サイトからのリクエストというコンテキストを維持してるようですヘッダーによるリダイレクトだとそのコンテキストを持ち続けるみたいなので JavaScript でリダイレクトさせてみると Cookie が送信されました
// これを
header("Location: /cookie.php");
// こうする
echo '<script>location.href = "/cookie.php"</script>';
SameSite とか入ると変に Cookie 周りが複雑になるのが嫌なところです
これまでどおり全部 None にして 外部からの攻撃を防ぐのは サーバの API の共通前処理で Origin チェックとかトークンチェックとかでいいかなという気持ちになってきました