Skip to content

モバイルのセッション管理:トークンと複数アカウントの分離

セッションの不具合は再起動後に現れやすい。前の利用者の画面が一瞬表示され、複数のリクエストが同時にトークンを更新し、ログアウト後の遅い応答が古い状態を書き戻す。認証情報と業務キャッシュの寿命を一緒に設計する。

保存とキャッシュの境界 ​

機密トークンは OS の安全な保存領域を利用する。通常の業務キャッシュは URL だけでなく利用者 ID ごとに分ける。トークンをログ、ディープリンク、平文ファイルに入れない。起動時はセッションを復元・確認してから個人データを見せる。

更新要求は一つにまとめる ​

失効時の複数リクエストは同じ更新 Promise / Future を共有する。更新が拒否されたら中央でセッションを無効化し、待機中の要求を止める。画面ごとにログイン画面を開かない。ログアウトやアカウント切り替えで世代番号を進め、旧世代の応答は新しい状態に書き込まない。

text
セッション A、世代 7 → リクエスト開始
ログアウト/切り替え → 世代 8、A の個人キャッシュを削除
古い応答 → 世代が違うため破棄

プロセス再起動、時計のずれ、同時 401、オフラインでのログアウト、素早い切り替えを検証する。クライアント側の分離だけでサーバーの権限検査を省略してはならない。

セッションを失効し得る状態として扱う ​

起動時、保護ストレージにトークンがあるだけでログイン済み画面を表示しない。認証情報とローカルのアカウントを読み、サーバーでセッションを検証または更新する間は明確に restoring とする。アクセストークンは短命にし、更新用の資格情報は OS の保護ストレージへ置く。設定、ログ、クラッシュ報告に秘密を含めない。オフライン閲覧を認めるなら、検証前に表示できるキャッシュと隠すべき機密情報を先に決める。

同時に 5 件の要求が 401 を返しても、それぞれ更新処理を開始して結果を上書きしてはいけない。アカウントごとに更新タスクを一つにし、ほかは同じ結果を待つ。更新失敗やサーバー側の失効時には、資格情報、アカウント別キャッシュ、保留中の機密操作を一つの状態遷移で消してからログイン画面へ移る。A がログアウトして B がすぐログインした場合、A の遅い応答はセッション世代で捨てる。

text
restoring → authenticated → refreshing → authenticated
                        ↘ refresh rejected → signedOut
signedOut → signingIn → authenticated(new account generation)

ログアウトとオフラインの境界を決める ​

利用者がログアウトしたら新しい認証要求を止め、機密のローカル状態を直ちに消す。オフラインならサーバー側の失効は後で再試行しても、画面はすでにログアウト済みとして扱う。高リスク操作はサーバーが毎回権限を確認し、ボタンを隠すだけに依存しない。プロセス終了、端末時計のずれ、同時 401、オフラインログアウト、A/B の素早い切替、更新資格情報のローテーションを試す。記録するのは状態遷移と失敗の種類であり、トークン値ではない。

MIT Licensed