質問: クライアントサイドにReactを用いて、ユーザー登録を機能に持つ新規SPA開発を考えております。 その際にユーザーのサインイン時のセッション管理にJWTを用いようと思っているのですが、TokenのExpiration Time の扱いについて質問させて頂きたいです。 実現したいUX ------- ユーザーが何らかのアクション(例えば、ここでは「ページ遷移」とする)行ってから、1時間以内にページ遷移を行わなかった場合セッションアウトとして、次のアクションもしくはSPAへのアクセス時にサインインページへとリダイレクトする。 実装・開発に関する疑問 ----------- 色々調べてみて、以下の実装が一般的?であるとわかったので、このように実装しようと考えております。 1. サインインリクエスト時に期限付きのJWT(例えば、1時間)を発行しレスポンス 2. それをクライアントサイドでlocalStorageなどに保存する 3. 認証が必要なAPIに関してはヘッダーに、Bearer Token としてJWTを付与して、サーバーサイドで認証する しかし、上記の実現したいUXを達成する際に、最後のアクションをしてから1時間のセッション維持を実現するには、どうするのがベストなのか疑問に思いました。 現状考えつくのは、 1. 新しくトークンを発行するAPIを作成して、認証が必要なAPIをリクエストする前に毎回新規JWTを発行し受け取り、localStorageを書き換える。 2. 認証が必要なAPIに関して一つ一つにJWTの発行を実装しレスポンス、localStorageを書き換える 3. 実現したいUXを諦めて、サインインから1時間以内。それを超えたら毎回サインインページヘリダイレクトさせる(1時間以上のアクティブ利用の可能性があるサービスなので避けたい。ただセキュリティ上なるべく短いセッション維持にしたい) です。 ネット上にたくさん情報がある分野だとは思うのですが、ご経験者が具体的にどのように実装されているのか知りたく思い質問させて頂きました。 よろしくお願い致します。
回答: おすすめは「3. 実現したいUXを諦める」です。 まず、長時間アクションのないセッションを自動的にログアウトさせたい理由をはっきりさせましょう。 A. セッション情報をサーバ側で保持しており、長時間利用していないものを破棄したい →もし、サーバ側にセッション情報を保持しているのであれば、その有効期限で管理できるので、この問題は発生しません。質問の文脈から、サーバ側にセッション情報を保持していないものと思われ、この理由は当てはまりません。 B. 長時間放置したアプリの画面は他者に横取りされている可能性があり、セキュリティ上横取り防止のためにログアウトさせたい → 昔は共用パソコンを使用していたので、アプリによるログアウト機能は重要でしたが、今やほぼ専有デバイスであり、PCでもスマホでもスクリーンロック機能で横取りを防止することができます。専有デバイスであれば、アプリごとに横取り防止機能を提供する必要性はありません。 昔は上記の A. B. の理由からユーザが最後に画面を触った時間から一定時間経過すると自動的にログアウトする機能がありましたが、今のSPAでは考え方を変える必要があります。 > > セキュリティ上なるべく短いセッション維持にしたい > > > この理由の詳細によるのですが、 業務アプリであれば、利用者にスクリーンロックの利用を推奨することでセキュリティを確保し、セッションの時間をできるだけ長く(20時間とか)するのが良いと思います。この時間を何時間にするかはアカウントを無効化してから実際に利用できなくなるまでの時間のリミットで決定します。 コンシューマ向けアプリであれば、セッションは長くしておいて、重要な操作を行うときは毎回パスワードを聞くというのがよくある手法です。たとえば、個人情報の参照、金銭の決済などの操作のときだけパスワードを入力させ、それ以外の商品の検索などは、セッションの権限で行わせるなど。