ステートフルな認証とステートレスな認証について調べてみた :)

1 min read読了の目安(約1400字

この記事を書くモチベーション

とある勉強会でステートフルな認証とステートレスな認証をうまく説明できなくて悔しかったので記事にまとめてみました。

JWTについて

JWTに関してはそのシステムの文脈によって様々な使われ方がしますが、今回はSPA + APIサーバーの構成でのWebサービスの認証に関してとりあげさせていただきたいと思います。

ステートフルな認証

主なステートフルな認証

  • Cookie認証

SPA構成時のメリット

  • フロントエンドの実装が簡単
  • 認証の状態をサーバー側で管理するので、ユーザーのセッションIDが攻撃者の手に渡った場合にそのセッションIDを無効化できる。

SPA構成時のデメリット

  • 例えば上記の構成を考えてみてください。サービスがスケールしてきてサーバーを大量にスケールアウトした場合に認証状態を管理しているRedisにアクセスが集中してしまいます。ステートフルな認証を使った場合はサービスがスケールしたあとにどういうインフラ構成にするか戦略が必要になってきそうです
  • 複数ドメインにアクセスする場合にCookieの共有設定をする必要があります
  • Cookieを利用しているため、CSRF対策などCookie関連の脆弱性の対応は必須になります

ステートレスな認証

主なステートレスな認証

  • JWT認証

SPA構成時のメリット

  • ステートフルな認証の項でも登場した上記の例ですが、Redisのサーバーがきれいさっぱりなくなっています。サーバーがスケールアウトした上記のような場合でもステートレスな認証を採用した場合は各App server内でJWTの検証ができるのでRedisのサーバー代が節約できます

SPA構成時のデメリット

  • 認証の状態をサーバー側で管理できないので、JWTが攻撃者の手に渡った場合に該当のJWTのみを無効化できません。無効化したい場合、サーバー側でJWTの検証に利用する公開鍵をリフレッシュすることで対応することはできます。

結局どれを選べばいい?

基本的にどちらの認証方式もメリット・デメリットはありますが、ケースバイケースなので上記のメリット・デメリットを参考に選択していくのがいいと思いました。
例えば僕は業務でよくLaravelを使うのですが、Laravel公式のSPA認証用ライブラリのSanctumを使っています。選定基準として一番大きいのはLaravel公式の認証ライブラリというところと、ステートフルな認証の方がセッションのトークンに問題が発生したときに対応しやすいかなと思ったからです。

参考文献