Cookie の Secure と SameSite 不整合
目次
この記事でわかること
- Cookie(クッキー:ブラウザに保存される小さなデータ)の
Secure属性とSameSite属性が食い違うと、なぜログインやカート維持ができなくなるのか SameSite=Lax(既定)/Strict/Noneの違いと、NoneにはSecureが必須という前提- 「ログインできない」「カートが消える」が起きる代表的な不整合パターンと、その直し方
なぜ Cookie の不整合でログインできなくなるのか
ログイン状態やショッピングカートの中身は、多くのサイトで Cookie に保存したセッション情報で維持しています。この Cookie がブラウザに保存されない、またはサーバーに送り返されないと、利用者は「ログインしたのにすぐ弾かれる」「カートに入れた商品が消える」といった状態に陥ります。
原因の上位にあるのが、Cookie に付ける Secure 属性と SameSite 属性の不整合です。この 2 つは現在のブラウザが厳しくチェックしており、組み合わせを誤ると Cookie そのものが拒否されたり、必要な場面で送信されなくなったりします。
ビジネスへの影響は単純で、会員サイトならログインできない、EC ならカートが維持できない、つまり売上と問い合わせに直結します。設定ミスのまま放置すると「特定のブラウザだけログインできない」という再現しにくい不具合として、サポート負荷だけが増えていきます。まずは 2 つの属性が何を意味するのかを押さえます。
SameSite と Secure の正しい組み合わせ
Secure 属性(HTTPS のときだけ送られる印)
Secure 属性が付いた Cookie は、HTTPS(暗号化された通信)でアクセスしたときだけサーバーに送られます。HTTP(暗号化なし)の通信では送られません。盗み見を防ぐための仕組みで、ログイン用 Cookie には付けるのが基本です。
注意点は、サイトの一部でも HTTP が残っていると、その画面では Secure Cookie が送られないことです。HTTP と HTTPS が混在した状態はログイン不具合の温床になります。混在の是正手順はWordPress の混在コンテンツを直す方法にまとめています。HTTPS そのものの前提は中小企業のための SSL/HTTPS 入門もあわせてご覧ください。
SameSite 属性(別サイトからの送信を制御する印)
SameSite は、別のサイト(クロスサイト:自社とは異なるドメインのページ)から自社サイトへリクエストが飛んだときに、Cookie を送るかどうかを決める属性です。値は 3 つあります。
Strict(厳格): 別サイトからのリクエストでは一切送らない。最も安全だが、外部サイトのリンクから来た直後はログイン状態が反映されないことがあるLax(緩やか・既定値): 別サイトからのリンクをたどってページを開く「トップレベルナビゲーション」(アドレスバーの URL が変わる移動)のときだけ送る。SameSiteを書かない場合は現在のブラウザがこのLaxとして扱うNone(制限なし): 別サイトに埋め込まれた場面でも送る。ただしSecure属性が必須
None には Secure が必須
最重要のルールがこれです。SameSite=None を指定するなら、必ず Secure も一緒に付けなければなりません。Secure が無い SameSite=None の Cookie は、現在のブラウザに拒否され保存すらされません。正しい書き方は次の 1 行です。
Set-Cookie: session=abc123; SameSite=None; Secure
なお Secure は HTTPS でしか働かないため、SameSite=None; Secure の Cookie は実質的に HTTPS でしか使えません。クロスサイトで Cookie を使う構成は、サイト全体が HTTPS であることが前提になります。
よくある不整合パターンと直し方
パターン 1: SameSite=None なのに Secure が無い
決済代行やシングルサインオン(SSO:1 回のログインで複数サービスを使える仕組み)、外部に埋め込むウィジェットなどで SameSite=None を指定したのに、Secure を付け忘れたケースです。ブラウザが Cookie を保存しないため、戻ってきた瞬間にセッションが消え、ログインや決済が完了しません。
直し方は単純で、SameSite=None には必ず Secure をセットで付けます。同時に、その Cookie を発行する画面が HTTPS で配信されているかも確認してください。
パターン 2: リバースプロキシ配下で Secure Cookie が落ちる
ロードバランサーやリバースプロキシ(手前で通信を受けて内部へ振り分ける装置)で HTTPS を終端し、内部のアプリには HTTP で渡す構成でよく起きます。利用者から見れば HTTPS なのに、アプリ側は「HTTP で来た」と誤認し、Secure Cookie を発行しない、あるいは送られないと判断してログインがループします。
直し方は、X-Forwarded-Proto ヘッダーなどでアプリに「元は HTTPS だった」と正しく伝え、フレームワーク側の「プロキシを信頼する」設定を有効にすることです。利用するアプリやフレームワークのプロキシ設定項目を確認してください。
パターン 3: 既定の Lax を前提にした iframe 埋め込み
自社サイトの管理画面やフォームを、別ドメインのページに iframe で埋め込んで使う構成です。SameSite を指定していないと既定の Lax 扱いになり、別サイト内の埋め込み(トップレベルナビゲーションではない)では Cookie が送られず、埋め込み先だけログインできません。
クロスサイトの埋め込みで Cookie を使う必要があるなら、その Cookie を SameSite=None; Secure に変更します。逆に埋め込みが不要なら、Strict か Lax に寄せたほうが安全です。
パターン 4: HTTP ページが残っていて Secure Cookie が届かない
サイトは HTTPS 化したつもりでも、一部の固定ページや画像、リダイレクト設定で HTTP が残っていると、その画面では Secure Cookie が送られません。「特定のページからだけログインできない」症状はこれが疑われます。
サイト全体を HTTPS に統一し、HTTP は HTTPS へ転送します。混在の洗い出しと是正はWordPress の混在コンテンツを直す方法を、サイト全体の安全設定の見直しはWordPress のセキュリティヘッダー設定を参考にしてください。
よくある質問
SameSite を指定していない Cookie はどう扱われますか
現在の主要ブラウザは、SameSite を書いていない Cookie を Lax として扱います。Chrome ではこの挙動が標準になっています。クロスサイトで送りたい Cookie は明示的に None; Secure を指定する必要があります。
Strict にすればいちばん安全ですか
セキュリティ面では Strict が最も堅牢ですが、外部サイトのリンクからたどり着いた直後にログイン状態が反映されないなど、利便性を損なう場面があります。一般的な会員サイトでは Lax、クロスサイト連携が必要な部分だけ None; Secure、という使い分けが現実的です。
ローカル環境(localhost)では Secure を付けると動きませんか
Secure は HTTPS が前提ですが、多くのブラウザは開発用の localhost を例外として扱います。本番は必ず HTTPS で、SameSite=None には Secure を付ける前提で設計してください。
まずは自社サイトの土台を確認しませんか
Cookie の不整合トラブルの多くは、サイト全体が HTTPS で正しく統一されているかという土台に行き着きます。Secure Cookie が確実に届くには、HTTP の取りこぼしや証明書の不備が無いことが前提です。
ドメイン番人の無料診断では、HTTPS の構成や証明書、セキュリティ設定の状態を数秒でチェックできます。診断結果を見ても原因の切り分けに迷う場合は、お問い合わせフォームから状況をお知らせください。専門家が一緒に確認いたします。