要件
要件として
- ブラウザ版はセッション保持期間を30分間。
- スマホ版は明示的にログアウトしない限りセッションは切れない。
こんなアプリケーションを作る場合、セッション管理ってどうやるのがいいのか。
Webブラウザでセッション管理をすると?
Webブラウザでは一度認証したあとのログイン状態の保持にはCookieを使ったセッション管理でするのが一般的。
- ユーザは一度ログインを済ませるとサーバ側から払い出されたセッションIDをCookieに保持する
- 次のアクセスにはCookieからセッションIDを取り出して付与しサーバにアクセスする
- サーバ側は送られてきたセッションIDが正しいものか検証する
サーバ側はRedisのようなKVSを用意してセッションIDとユーザIDを管理し、一定期間が過ぎると削除する。
みたいな実装。これでセッションを管理出来る。といった感じ。
スマホネイティブアプリでセッション管理をする?
ではスマホネイティブアプリではどうなのか。
ネイティブアプリではユーザビリティ向上のためログイン状態を出来るだけ保持しつづける必要がある事が多い。
確かによく使うスマホアプリの挙動を思い出してみてもそうなっている。
そしてそもそそもの問題としてCookieはブラウザの概念なのでスマホネイティブアプリは使うことは出来ない。
そうなんだ!でもCookie使えなくてもセッションIDをなんらかのセキュアな場所で保存しておけばいいのでは?
と思ったが、まるっとそう収まらない。
それはCookie自体がある程度セキュリティ面での取り扱いも仕様上制限されてる上での前提があってセキュアに使われてるだけであって、「じゃあ代わりのストレージでセッションIDを保持しよう!」となることは一般的ではない。
つまりどういうことか
つまり、やろうと思えばブラウザのように
「サーバ側にセッション情報を保持し、クライアントはなんらかのストレージでセッションIDを保持する」
のような実装も出来ることはできる。でもやらない。
スマホネイティブアプリは一般的には「トークンベースの認証」を採用するパターンが多い。
「Cookie使えないからプラットフォーム毎に異なるかもしれないけどいい場所でセッションIDを保持するね!」としてもセキュリティ的にも不安で、セッション管理が複雑になる。
それだったらステートフルなトークンベースの認証を採用しようね、って流れは理解できそう。
認証が違うので当初想定していた
「プラットフォーム毎にセッション期限を柔軟に変えたいな・・・」という問題も手っ取り早く対応できそう。
めでたしめでたし(?)
たとえばこうなる
最初の話に戻る。
要件として
- ブラウザ版はセッション保持を30分間。
- スマホ版は明示的にログアウトしない限りセッションは切れない。
とした場合。まずログイン用の受け口を2つ作る。
ブラウザからは
- 初回ログイン時にサーバから払い出されたセッションIDをCookieで管理してリクエストの都度送信する。
- セッション情報はRedisのようなKVSで管理してリクエストされたセッションIDと検証。
- Redis側でセッションの保持期限(30分)を決めておけばセッションタイムアウトを制御出来る。
スマホからは
- 初回ログイン時に秘密鍵で暗号化したアクセストークン&シークレットトークン(JWT)を払い出す。
- クライアント側で両方のトークンを保持してサーバ側ではシークレットトークンをRDBで保持する。
- セキュリティのため有効期限を短く設定してあるアクセストークンをリクエスト毎に投げる。
- 有効期限が切れた場合にリフレッシュトークンをサーバ側に送信する。検証が成功すればリフレッシュトークンとアクセストークンを再生成してアクセストークンをクライアント側に払い出して再度アクセスを行う。
- リフレッシュトークンで設定した期限が来るまでセッションは維持される
的なことをやれば要件を満たすユーザ体験を提供できた。
参考
そもそもJWTに関する私の理解は完全に間違っていた! / koduki
https://koduki.hatenablog.com/entry/2019/11/03/163014
JWTでセッション管理してはいけない / @hakaicode
https://qiita.com/hakaicode/items/1d504a728156cf54b3f8
セッションについてまとめる / ハガユウキ
https://zenn.dev/yukihaga/scraps/1f4601f0a676b8
Webアプリのセッション管理とデータ保存を学ぶ#1(社内勉強会)/ hachi8833 & morimorihoge
https://techracho.bpsinc.jp/hachi8833/2018_09_19/61260
CookieとWeb Storageの仕様を比較する / sjbworks
https://zenn.dev/sjbworks/articles/cookie-webstorage
モバイルアプリの認証アーキテクチャ / owasp-mastg-ja
https://coky-t.gitbook.io/owasp-mastg-ja/mobairuapuritesutogaido/0x04e-testing-authentication-and-session-management
セキュアなトークン管理方法 / Junpei Tsuji
https://christina04.hatenablog.com/entry/secure-token-management
APIトークン認証の論理設計 / Roku
https://zenn.dev/ad5/articles/fae2e929fca79e
ユーザーをログアウトから守れ!―シーケンス図から読み解くログイン状態維持【Webアプリ編】/ 都元ダイスケ
https://dev.classmethod.jp/articles/persisten-login-for-webapp/
ユーザーをログアウトから守れ!―シーケンス図から読み解くログイン状態維持【Mobileアプリ編】/ 都元ダイスケ
https://dev.classmethod.jp/articles/persistent-login-for-mobileapp/
JWT認証、便利やん? / auth0
https://auth0.hatenablog.com/entry/2018/09/21/004131
クロスサイトスクリプティング(XSS)対策としてCookieのHttpOnly属性でどこまで安全になるのか / 徳丸浩のウェブセキュリティ講座
https://www.youtube.com/watch?v=4JREwhSC2dQ
コメント