概要
認証の方式や、それを活用するOAuthについて基本的な部分を学んだので整理する
- セッショントークン認証
- JWT認証
- OAuth
各認証方法について
セッショントークン認証
サーバ側で生成したセッションIDをクライアントに渡し、クライアントはそれをcookieなどで保持する。
サーバ側もセッションIDをもとに認証状態を管理する。
認証は、クライアントから送信されたセッションIDが、サーバ側で有効なセッションとして存在していれば完了するステートフルな方式。
JWT認証
サーバ側で利用者に紐づく一意な情報
・秘密鍵
・指定したハッシュアルゴリズム
を用いてトークンを生成する。
そのトークンをクライントに送信、クライアントが保持する。
サーバはトークンを保持しないHTTPステートレスな認証方法。
トークンの構成としては、ヘッダー(json)
・ペイロード(json)
・署名(文字列)
の3つで成り立っている。
認証は、クライアントから送られたJWTトークンの署名を、サーバ側がクライアントのJWTトークンに含まれるヘッダー・ペイロードを基に秘密鍵で署名を生成し、改ざんされていないか確認する。
- ヘッダーについて
JWTに関する静的な情報を格納する部分。
トークンのタイプ「JWT」、署名アルゴリズム等を設定している。 - ペイロード
トークンに関する動的な情報を格納する部分。
トークンの期限や利用者に紐づく一意な情報等を設定している。 - 署名
ヘッダーとペイロード、それに秘密鍵でハッシュ化して生成した文字列。改ざんを検知するために使う。
ヘッダー・ペイロードはBase64URLエンコードされているため、ブラウザで簡単にデコードして中身を見ることができる。そのためペイロード部分の利用者情報に個人情報を含めないよう注意する必要がある
OAuth(認可フロー)
他社サービスの認証情報を利用して、ユーザーにアプリへのアクセス許可(認可)を与えてもらう仕組み。
ユーザーが認可すると、アクセストークンを取得でき、そのトークンを使って他社API(例:Google、GitHubなど)にアクセスできる。
アクセストークンの形式は仕様で厳密に決まっていないが、JWT形式であることが多い。
OAuth2.0の代表的なフロー(Authorization Code Flow)
-
ブラウザ(クライアント) → 認可サーバ
クライアントが認可リクエストを送信(例:Googleログインボタンを押す) -
認可サーバ → ブラウザ
ユーザーが認可を許可する(許可しますか画面が認可サーバ経由で表示される)と、認可コード付きでクライアントにリダイレクト -
ブラウザ → アプリサーバ
認可コードをアプリサーバに送信 -
アプリサーバ → 認可サーバ
認可コードとクライアントID・シークレットなどを送信して、アクセストークンを要求 -
認可サーバ → アプリサーバ
アクセストークンを返却 -
アプリサーバ ⇔ リソースサーバ
アクセストークンを使って保護されたAPIにアクセス、データの取得や操作を行う
各認証方法のメリット・デメリット
セッショントークン認証
-
メリット
- サーバ側でセッション情報を保持しているため、不正アクセスや疑わしい操作を検知した際に即セッションを無効化できる
- セッションIDのみ送信すればよいため、トラフィックが軽い
-
デメリット
- サーバでセッション状態を管理するため、スケールアウト(ドメインの異なる複数サーバ)でのセッション共有や管理コストがかかる。
- Cookieに保存することからCSRF攻撃のように、リクエスト内容は正規だが利用者に意図してない操作をさせる攻撃には弱い
JWT認証
-
メリット
- クライアント側でトークンを保持し、サーバ側は秘密鍵さえ保持していればよいため、スケールアウト時の共有コストが低い
- 有効期限をトークン自体に埋め込めるため、ログイン状態の管理をサーバ側で行わずに済む
-
デメリット
- サーバ側でトークンの状態を保持しないため、不正アクセスがあっても有効期限を過ぎるまではトークンを取り消せないため、即無効化ができない
- ドメインの異なるサーバへ送信する場合、httpOnly属性やSameSite=Strictを設定したCookieには保存できないため、結果としてスクリプトからアクセス可能な領域に保存するケースが増え、XSSなどに対するリスクが高まる
- トークンサイズが大きくなる傾向によるって、トラフィックの負担大になる可能性が高い
OAuth
- メリット
- 他社サービスへアクセスする際、アプリ側でユーザーの認証情報を直接管理しなくてよいため、セキュリティ負担が軽減される
- 利用者が既存のアカウント(Google、GitHubなど)で手軽にログインできる
- デメリット
- OAuth自体は認可フローであり、単体ではユーザー認証の仕組みを持たない
- サーバ側の実装がやや複雑で、トークンの取り扱いやリダイレクト処理などの制御が必要になる
備考
各認証方法のデメリット対策(リフレッシュトークンなど)や用途の使い分けについては、今後追記していく予定。