一本の石造りの通路に、二つの扉が前後に続いている。

プロダクトノート

ログアウトの連鎖

ユーザーがログインするのは一度きりです。でも、その裏で作られる「鍵」は一本ではありません。ログアウトするときは、どの鍵を回収し、どこまでログイン状態を終了するのかを考える必要があります。

ログインは一度。でも鍵は三本できる

自社サービスに「Googleでログイン」を付けたとします。ユーザーの体感は「ボタンを一回押した」だけです。 ところが内部では、ログインの通り道にあるシステムがそれぞれ自分の鍵(セッション)を発行して保管します

Google が一本、Authrim が一本、自社アプリが一本。合計で三本です。 セッションが残った場所では、操作を続けられたり、パスワードを再入力せずに入り直せたりすることがあります

ログアウトとは、画面に「ログアウトしました」と出すことではなく、
終了させたい範囲を決め、その範囲のセッションを終了させることです。

トークンの失効は、別の話です

ここで「鍵」と呼んでいるのはセッションです。 アクセストークンやリフレッシュトークンは別の仕組みで、 セッションを終了しても、発行ずみのトークンが自動的に失効するとは限りません。 トークンを止めるには失効(revocation)という別の操作が必要です。

OIDC の用語で言えば、セッションのログアウト・トークンの失効・上流IdPでのアカウント無効化は それぞれ別の操作です。この記事が扱うのはセッションの側だけで、 トークンがいつ効かなくなるかは トークンのイントロスペクションと失効で扱っています。

Authrim は「中間」に立っている

ここで押さえておきたいのが、Authrim のポジションです。 この連携では、上流のIdP、Authrim、自社アプリがそれぞれ役割を持ちます。

上流IdPは、自社サービスから見て「ログインさせる側」。 自社アプリは「ログインを頼む側」。 ところが Authrim は、上を向くか下を向くかで立場が入れ替わります

上流IdP Google・Entra ID・Apple など Authrim 自社のIDサービス 自社アプリ / SaaS ユーザーが実際に使う画面 ログインを頼む = お客の立場(RP) ログインさせる = 受付の立場(OP) 上下で立場が 逆になる
旅行代理店に似ています。あなたから見れば旅行を手配してくれる会社ですが、航空会社から見れば座席を買いに来た客です。 Authrim も同じで、受付とお客を同時に務めます。これが「中間」という言葉の意味です。

ログアウトは、たいてい途中で止まる

問題はここからです。ログインは上から下へ自然に流れますが、ログアウトは誰かが能動的に伝えないと伝わりません

上流IdPのセッションを終了しても、Authrimや自社アプリのセッションまで自動的に消えるとは限りません。 下流にも終了を伝え、受信した側が対象セッションを終了する処理が必要です。次の図は、必要な通知方式と設定が揃った場合の連鎖を示しています。

連鎖が切れている場合 上流IdP セッション終了ずみ 通知が届かない Authrim 鍵がまだ生きている 自社アプリ 鍵がまだ生きている 結果 ── ユーザーはまだ入れる 連鎖がつながっている場合 上流IdP セッション終了ずみ 「この人を切って」 署名つきの通知 Authrim 受け取って回収 / 下流へ中継 「この人を切って」 署名つきの通知 自社アプリ 受け取って回収 結果 ── 三本とも回収された
違いは真ん中の矢印だけです。Authrim が通知を受け取れて、かつ下流へ流し直せるか。 この経路に加え、上流IdPと各アプリの対応・設定が揃って、連鎖が成立します。

現場では、こう見える

「鍵が残る」と言われてもピンと来ないと思うので、実際に問い合わせや監査で表面化する形に翻訳します。

場面 連鎖がないと起きること
退職・アカウント停止 人事側で権限を止めたのに、当人のPCではアプリが開いたままで、翌朝まで社内データが見えていた。
共有端末 店舗・病院・コールセンターで、前の担当者がログアウトしたはずなのに、別タブを開いたら前の人の画面が出た。
端末の紛失・盗難 「全デバイスからログアウト」を押したのに、実際には手元の端末のセッションしか切れていなかった。
インシデント対応 不正アクセスを検知して該当ユーザーを止めたが、攻撃者のセッションだけは有効期限まで生き続けた。
監査・審査 「ログアウトが全システムに伝わることを示してください」と言われ、示す材料がない。

どれも「ログアウト機能がない」わけではありません。ボタンはあるし、押せば画面も切り替わります。 効く範囲が思っているより狭い、というのがこの問題の厄介なところです。

昔の伝え方が、使えなくなってきている

では、どうやって下流に伝えるのか。方法は大きく二つあります。 そして今、片方が壊れつつあります

ブラウザ経由でお願いする Authrim ブラウザ 見えない小窓を並べて通知 自社アプリ ブラウザのプライバシー保護で遮断されることがある。ユーザーがタブを閉じていたら届かない。 サーバー同士で直接伝える Authrim 署名つきの通知を直接送る ブラウザを一切経由しない 自社アプリ
上の方式は、ブラウザに「見えない小窓」を並べて各アプリに通知する仕組みです。 Safari・Firefox・Chrome のプライバシー強化によって、この小窓が遮断される方向に進んでいます。 下の方式(バックチャネル)はサーバー同士の直接通信なので、ブラウザの状態に左右されずに送れます。 ただし「必ず届く」わけではありません。ネットワーク障害、受信側アプリの停止、タイムアウト、5xx応答では届きません。 再送・キュー・失敗の記録は実装側で用意すべき領域です。

Authrim が対応しているのは、この下の方式を受け取る側の能力です。 受信側の処理と、下流アプリへの送信側の処理を、それぞれ確かめる必要があります。

受け取る側と、配る側を確かめる

Authrimは、上流のIdPに対してはログインを頼む側(RP)、アプリに対してはログインを提供する側(OP)になります。ログアウトを中継するためにも、それぞれの立場で仕様に沿って動く必要があります。

  • RP側:上流から届いたログアウト通知を検証し、対象となるAuthrimのセッションを終了する。
  • OP側:連携先アプリへログアウト通知を送り、アプリ側で対象セッションを終了できるようにする。

この二つの役割を確認する材料が、OP・RPそれぞれのログアウトプロファイル認定です。Authrimは、OpenID Foundationの公式適合性テストを使ったセルフ認定手続きを経て、両側のログアウトプロファイル認定を取得しています。

認定が示すのは、対象バージョンの実装が、申請したプロファイルの適合性テストを通過したことです。お客様の接続先やネットワークを含めて、すべてのセッションが即座に終了することを保証するものではありません。

実際に連鎖をつなぐには、上流IdPと各アプリが必要な方式に対応し、通知先と対象セッションの対応付けが設定されている必要があります。上流でのアカウント停止が必ずログアウト通知を発生させるとも限りません。通知が届かなかった場合の再送や失敗の確認を含め、利用する構成で確かめます。

認定の対象とバージョンは、OpenID Foundationの Certified OpenID Relying Parties & Logout Profiles認定制度の説明 から確認できます。

ログアウトしたあと、どこにログイン状態が残るのか。

共有端末を次の人へ渡すときも、退職者のアクセスを止めるときも、確認したいのはこの範囲です。Authrimは通知を受け取る側と配る側を担い、上流IdPとアプリの間でセッション終了をつなぎます。認定をその実装の確認材料にしながら、接続先も含めて意図した範囲に届くかを確かめていきます。