OAuth2.0について勉強したので認可コードフローについてまとめてみる
概要シーケンス認可エンドポイント(/authorize)トークンエンドポイント(/token)セキュリティ対策statecodeVerifier/codeChallengeクライアント(認可リクエスト)認可サーバー(認可エンドポイント)クライアント(トークンリクエスト)認可サーバー(トークンエンドポイント)実装メモ
概要
OAuth2.0は、ユーザーが認証情報を直接渡すことなく、第三者アプリケーションに限定的なアクセス権を与えるための認可(権限委譲)フレームワーク。アクセストークンを介して保護対象リソースへアクセスできる。認可コードフローなど複数のフローが存在する。
シーケンス
認可コードフロー(Authorization Code Grant
)の基本的なシーケンス
💡アクターの説明
シーケンス図に登場するアクターについての説明と、Google Calendarに保存してある画像を読み込む場合の例
リソース所有者
- リソースへのアクセス権を持つ人
- e.g. Google Calendarに予定を登録しているユーザー
クライアント
リソース所有者
に代わってリソースにアクセスしようとするアプリやサービス- e.g. Google Calendarに保存してある予定を参照できるアプリ(Notionなど)
認可サーバー
リソース所有者
の同意を確認し、クライアント
にアクセストークンを発行するサーバー- e.g. GoogleのOAuth認可サーバー
保護対象リソース
リソース所有者
がアクセス権を持つリソース、または、そのリソースへアクセスできるAPIサーバー- e.g. Google Calendar API
sequenceDiagram participant RO as リソース所有者<br/>(Resource Owner) participant C as クライアント<br/>(Client) participant AS as 認可サーバー<br/>(Authrization Server) participant PR as 保護対象リソース<br/>(Protected Resource) C-->>RO: 認可エンドポイントへの<br/>リダイレクトを行わせる RO->>AS: 認可エンドポイントにアクセス<br/>(リダイレクト) AS->>RO: 認証を要求 RO->>AS: 認証を実施<br/>クライアントを許可 AS-->>RO: 認可コードを返却<br/>リダイレクトを行わせる RO->>C: リダイレクトで<br/>認可コードなどを送信 C->>AS: 自身のクレデンシャルと認可コードを送信 AS->>C: アクセストークンを返す C->>PR: アクセストークンを併せてリソース取得のリクエスト PR->>C: 保護対象リソースを返す
認可エンドポイント(/authorize
)
クライアントから保護対象リソースへアクセスしようとすると、まずは認可サーバーの認可エンドポイント(/authorize
)へリダイレクトされる。ここで、認証を行うことで、クライアントからリソースへのアクセスを許可することができる。このとき、許可するスコープを指定することができ、必要最低限の権限のみをクライアントに付与することが可能。認証に成功すると、認可コードが発行/返却される。
トークンエンドポイント(/token
)
認可コードをトークンエンドポイントに送信することで、アクセストークンを取得することができる。以降では、このアクセストークンを使うことで、保護対象リソースにアクセスできるようになる。
セキュリティ対策
state
CSRF対策として機能する。下記を行うことで、意図しない認可リクエスト(攻撃者が誘導したもの)ではなく、自分自身がリクエストしたものだと判別することができる。
- ランダムな文字列を認可リクエストに付与
- 認可サーバーがその値をそのまま返却
- リクエスト時に生成した値と返却された値が一致することを確認
codeVerifier/codeChallenge
中間者攻撃を防ぐために使われる。発行された認可コードがクライアントに届く前に横取りされた場合でも、攻撃者はcodeVerifier
を知ることができないため、攻撃を防ぐことができる。
クライアント(認可リクエスト)
- ランダムな文字列を生成し、codeVerifierとする
- codeVerifierをハッシュ化し、Base64文字列に変換し、codeChallengeとする
- (stateをキーに、)codeVerifierとcodeChallengeを保存
- codeChallengeとハッシュ化時に使用したアルゴリズム(codeChallengeMethod)を認可リクエストに付与する
認可サーバー(認可エンドポイント)
- codeChallengeとcodeChallengeMethodがリクエストに含まれることを確認
- 上記の値を認可コードと併せて保存
クライアント(トークンリクエスト)
- 返却されたstateに紐づくcodeVerifier/codeChallengeを取得
- codeVerifierをトークンリクエストに付与
認可サーバー(トークンエンドポイント)
- 送られてきた認可コードに紐づくcodeChallenge/codeChallengeMethodを取得
- 送られてきたcodeVerifierとcodeChallengeMethodを使用し、codeChallengeを計算
- 認可リクエスト時に送られてきたCodeChallengeの値を一致するか確認
実装メモ
試しに書いてみたコード