SPAにおけるJWTを用いた認証認可について
認証認可についてメモを残す。一般的な仕組みをざっくり把握することを目的とする。
JWTとは
- JSON Web Tokenの略称でJSON形式のトークン
- ヘッダー、ペイロード、署名から構成される
- ヘッダーにトークンの種類、暗号化アルゴリズム等を含む
- ペイロードにクライアントの識別情報や権限、有効期限等(クレーム)を含む
- 署名はヘッダーとペイロードをインプットに生成し、改ざん検知に用いる
- HS256、若しくはRS256がアルゴリズムとして用いられることが多い
- 7payで署名されてないために改ざんされたインシデントあり
- base64エンコードされたJSON形式のデータでクライアント、サーバ間で使用する
- JWE(JSON Web Encryption)という規格でJWTの暗号化も可能
認証フロー
言葉だけで理解するのは難しいと思うので、認証フロー図を先にパッと見るのが早い。
トークン生成
認証サーバにて、ユーザー名とパスワードで認証を行い(+認証コードやMFAの仕組み等)、アクセストークンとリフレッシュトークンを生成する。
アクセストークン
リソースサーバーにアクセスするためのトークン。一回限りの使用、若しくは1時間以内の有効期限を短く設定することが一般的であると思われる。Firebaseのトークンもデフォルトが1時間、チャットワークの事例でも30分である。理由はステートレスであり(サーバで状態を管理しない)、クライアント側でのセキュリティリスクがあるためである。例えば、トークンを窃取されても、サーバ側で無効化できない。(無効化する仕組みを別途用意する等ないことはないが、一般的には上記の考え方がある)
リフレッシュトークン
アクセストークンの有効期間が切れたり、漏洩した際に、新しいトークンを生成してもらうためのトークンである。新しいアクセストークンの生成だけではなく、同じタイミングで新しいリフレッシュトークンも生成する。
新しいトークン生成後、悪意のある攻撃者が古いアクセストークンを用いてリソースへのアクセスを試行したり、古いリフレッシュトークンを用いて新しいトークンを生成することをした場合に検知する仕組みを構築することも可能である。実際、Auth0ではそのような仕組みがある。
トークン検証
Cookieとほぼ同じ。CookieはCookieヘッダを使用するが、TokenはAuthorizationヘッダのBearerスキームを使用する。リソースサーバーにて検証する。
トークンの保存場所
ローカルストレージ、セッションストレージ、Cookie、インメモリ、Auth0等の色々な選択肢がある。保存場所の比較は他にまとめられているので、ここでは特に記載しない。
リフレッシュトークンはサーバ側(データベース)で状態を保持し、無効化できる仕組み(ブラックリスト等)を持っておくことが一般的なようである。リフレッシュトークンは有効期間が長いので、特にセキュリティについて考慮が必要となる。
開発する場合
- リスクアセスメントした上でサービスの特性に応じて、軽減するのか、需要するのかどのようにコントロールするのかを判断したい。
- 基本的にはAuth0等のSaaSを活用するのが早くて安全。決済周りの実装等と同様でビジネスのコアでない限り、ドメインに集中する方が良い。
PKCE
アクセストークンを取得するためには、認可コードを用いて、クライアントを認証する仕組み。クライアントは毎回ランダムな文字列(verifier)を生成、ハッシュ化し、認可リクエストを送り、認可サーバーはそれを元に認可コードを発行する。クライアントはverifierと認可コードをリクエストし、アクセストークンを取得する。既定のシークレット情報を繰り返し使ったり、毎回異なる認可コードを使用するので利点がある。
参考
Discussion