← eli5

セッションと認証

ロッカーの鍵、
とりちがえ事件

ログインの途中で「ログアウト」が走ると、ログインが失敗する。
原因はぜんぶ、鍵の番号の話でした。

S1
まえおき 01
あなた S1 返事の封筒 中に鍵が1本 S1 ロッカー

やりとりは、ぜんぶ窓口ごし

あなたがサイトに何かを頼むと、窓口から返事の封筒が返ってきます。この封筒が、このあと何度も出てきます。

封筒には必ず番号つきの鍵が1本。ログインで手に入る「持ちもの」は、その番号のロッカーにしまわれます。
鍵 S1 → ロッカー S1

まえおき 02
S1 守衛所 いってきます スタンプ、もらった

ログインは、往復する

となりの守衛所の窓口まで自分で行って、スタンプをもらって戻ってくる。運ぶのはあなたです。

その間、サイトの窓口はメモを1枚持っています。
「鍵 S1 の人が、帰りを待っている」

まえおき 03
S1 からっぽに S1 S2 鍵は付け替え

ログアウトは、鍵の付け替え

ロッカーをからっぽにして、鍵を新しい番号にする。

これでいい。ログアウトとは、そういうものだから。

こまった 04
ログアウトが走る S2 鍵が変わった 受付のメモ まってる人 = S1 帰ってきた人 S2 どなたですか?

まだログインしてないのに、鍵を替えられた

ログアウトのボタンは、ログインしていなくても押せてしまいました。ロッカーはからっぽ。なのに鍵だけ S1 → S2 に付け替わる。

スタンプを持って戻ると、受付のメモは S1 のまま。照合できず、ログイン失敗。

なおした ① 05
からっぽ なら S1 なにもしない

からっぽなら、なにもしない

しまうものが無いロッカーは、開ける意味がない。鍵はそのまま。

返事は今までどおり「はい、ログアウトしました」。二度押しても平気という、ログアウト本来の性質はそのまま守ります。

ここが大事 06
S1 返ってきた封筒 あなたのポケット S1 だまって入れ替わる

封筒の鍵で、ポケットが上書きされる

封筒を受け取るたび、あなたはポケットの鍵を中の鍵と入れ替えます。考えずに、機械的に。

ふだんは同じ番号が入っているので、入れ替わったことに誰も気づきません

ここが大事 07
窓口 ログインの封筒 ログアウトの封筒 ? どっちが後に返ってくる?

お願いは、2つ同時に出せる

ログインの手続きと、割り込んだログアウト。別々の窓口に出しています。

封筒は出来た順に返ってくるので、どちらが後になるかは決まっていません

こまった ② 08
時間 ログインの封筒 · 鍵 S7 ポケット → S7 ✓ ログアウトの封筒 · 鍵 S1 ポケット → S1 に逆戻り S7 もう開かない

後から返ってきた封筒に、古い鍵が入っていた

鍵を替えるのはやめました。でも返事の封筒には、まだ古い鍵 S1 が入ったままだったんです。

先にログイン成功の封筒が返ってきて、ポケットは S7。荷物も S7 のロッカーへ。
そのあとログアウトの封筒が返ってくると、ポケットが S1 に上書きされ、S7 のロッカーが開かなくなる。

なおした ② 09
鍵は入れない なにもしなかった時 → 後から返ってきても何も起きない S2 新しい鍵を同封 本当にログアウトした時 → 返ってくることが、効いたということ

なにもしなかったなら、鍵の話もしない

ロッカーに手をつけていないなら、封筒に鍵を入れないあとから返ってきても、ポケットは何も入れ替わりません。

ほんとうにログアウトしたときは、これまでどおり新しい鍵を同封します。それが届くことが、ログアウトが効いたということなので。

ほんとうは、こういう話でした

たとえほんとう
あなたブラウザ
サイトの窓口API サーバ
返事の封筒HTTP レスポンス
ロッカーの鍵セッション Cookie
鍵の番号セッション ID
ロッカーの中身OAuth トークン一式
守衛所へ往復/authorize → 認可サーバ → /callback
受付のメモ認可リクエストの session binding
鍵の付け替えsession()->invalidate() による ID ローテーション
返事に鍵が同封されているレスポンスの Set-Cookie
ポケットの鍵が入れ替わるブラウザが Cookie を上書きする
お願いを2つ同時に出す並行リクエスト(返る順は保証されない)
鍵を入れない封筒Set-Cookie を付けないレスポンス