やりとりは、ぜんぶ窓口ごし
あなたがサイトに何かを頼むと、窓口から返事の封筒が返ってきます。この封筒が、このあと何度も出てきます。
封筒には必ず番号つきの鍵が1本。ログインで手に入る「持ちもの」は、その番号のロッカーにしまわれます。
鍵 S1 → ロッカー S1
ログインは、往復する
となりの守衛所の窓口まで自分で行って、スタンプをもらって戻ってくる。運ぶのはあなたです。
その間、サイトの窓口はメモを1枚持っています。
「鍵 S1 の人が、帰りを待っている」
ログアウトは、鍵の付け替え
ロッカーをからっぽにして、鍵を新しい番号にする。
これでいい。ログアウトとは、そういうものだから。
まだログインしてないのに、鍵を替えられた
ログアウトのボタンは、ログインしていなくても押せてしまいました。ロッカーはからっぽ。なのに鍵だけ S1 → S2 に付け替わる。
スタンプを持って戻ると、受付のメモは S1 のまま。照合できず、ログイン失敗。
からっぽなら、なにもしない
しまうものが無いロッカーは、開ける意味がない。鍵はそのまま。
返事は今までどおり「はい、ログアウトしました」。二度押しても平気という、ログアウト本来の性質はそのまま守ります。
封筒の鍵で、ポケットが上書きされる
封筒を受け取るたび、あなたはポケットの鍵を中の鍵と入れ替えます。考えずに、機械的に。
ふだんは同じ番号が入っているので、入れ替わったことに誰も気づきません。
お願いは、2つ同時に出せる
ログインの手続きと、割り込んだログアウト。別々の窓口に出しています。
封筒は出来た順に返ってくるので、どちらが後になるかは決まっていません。
後から返ってきた封筒に、古い鍵が入っていた
鍵を替えるのはやめました。でも返事の封筒には、まだ古い鍵 S1 が入ったままだったんです。
先にログイン成功の封筒が返ってきて、ポケットは S7。荷物も S7 のロッカーへ。
そのあとログアウトの封筒が返ってくると、ポケットが S1 に上書きされ、S7 のロッカーが開かなくなる。
なにもしなかったなら、鍵の話もしない
ロッカーに手をつけていないなら、封筒に鍵を入れない。あとから返ってきても、ポケットは何も入れ替わりません。
ほんとうにログアウトしたときは、これまでどおり新しい鍵を同封します。それが届くことが、ログアウトが効いたということなので。
ほんとうは、こういう話でした
| たとえ | ほんとう |
|---|---|
| あなた | ブラウザ |
| サイトの窓口 | API サーバ |
| 返事の封筒 | HTTP レスポンス |
| ロッカーの鍵 | セッション Cookie |
| 鍵の番号 | セッション ID |
| ロッカーの中身 | OAuth トークン一式 |
| 守衛所へ往復 | /authorize → 認可サーバ → /callback |
| 受付のメモ | 認可リクエストの session binding |
| 鍵の付け替え | session()->invalidate() による ID ローテーション |
| 返事に鍵が同封されている | レスポンスの Set-Cookie |
| ポケットの鍵が入れ替わる | ブラウザが Cookie を上書きする |
| お願いを2つ同時に出す | 並行リクエスト(返る順は保証されない) |
| 鍵を入れない封筒 | Set-Cookie を付けないレスポンス |