晴耕雨読

working in the fields on fine days and reading books on rainy days

OAuth (OAuth 2.0 認可フレームワーク)

OAuth

OAuthは認可のプロトコルです。OAuthによってリソースサーバへのアクセス権限をサードパーティのアプリ(クライアント)に移譲することができます。

  • OAuthはHTTPS上で使用されます。
  • OAuthは認可のためのプロトコルであり、認証のプロトコルではありません。
  • OAuthでは認証トークンの形式(フォーマット)を定義していません。※OpenID Connectでは定義しています。

ロール(Role)

OAuthには4つのロールが存在します。

  • リソースオーナー : リソースの所有者。エンドユーザ。例えばGoogleアカウントの利用者
  • クライアント : リソースサーバを利用するアプリ
  • リソースサーバ : Web APIでリソースを提供するサーバ
  • 認可サーバ : アクセストークンを発行するサーバ

認可タイプ(Grant Type)

一般的にOAuthフローとして知られています。 認可タイプは認証を付与する種類のことで、「グラントタイプ」や「グラント種別」、「付与方式」とも呼ばれます。

  • 認可コードによる付与方式 (Authorization Code Grant Type)
  • インプリシット付与方式 (Implicit Grant Type)
  • リソースオーナーのクレデンシャルによる付与方式 (Resource Owner Credentials Grant Type)
    • 別名として、パスワードによる付与方式 (Password Grant Type) とも呼ばれる
  • クライアントのクレデンシャルによる付与方式 (Client Credentials Grant Type)

認可タイプのフロー

認可の流れ(フロー)は認可タイプによって異なります。

フロー 認可エンドポイント トークンエンドポイント 説明
認可コードフロー 使用 使用 一般的に使用されるフロー
インプリシットフロー 使用 不使用 認可エンドポイントから直接トークンを返す(省略化されたフロー)
リソースオーナーフロー 不使用 使用 利用者が入力したユーザIDとパスワードを使ってトークンを取得する
クライアントフロー 不使用 使用 クライアント自身のクレデンシャルを使ってトークンを取得する(利用者に入力を求めたりしない)

認可コードフロー

認可タイプのフローの1つで、一般的に使用される認可コードフローは、以下の流れです。

  1. リソースオーナーは、クライアント上の画面でボタンを押下します。
  2. クライアントは、認可サーバの認可エンドポイントに対してリソースサーバへのアクセス権を要求します(リダイレクト発生)。
  3. 認可サーバは、リソースオーナーに対して、リソースサーバへのアクセス権をクライアントに移譲しても問題ないか意思を確認します。
  4. リソースオーナーは、権限を移譲することに同意します。
  5. 認可サーバは、認可コードを発行してクライアントに渡します(リダイレクト発生)。
  6. クライアントは、認可コードを利用して認可サーバのトークンエンドポイントにアクセストークンの発行を要求します。
  7. 認可サーバは、アクセストークンを発行してクライアントに渡します。
  8. クライアントは、アクセストークンを利用してリソースサーバにアクセスします。
  9. リソースサーバは、アクセストークンの有効性と権限(スコープ)を確認し、問題がなければ情報を返します。
     +----------+
     | Resource |
     |   Owner  |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier      +---------------+
     |         -+----(A)-- & Redirection URI ---->|               |
     |  User-   |                                 | Authorization |
     |  Agent  -+----(B)-- User authenticates --->|     Server    |
     |          |                                 |               |
     |         -+----(C)-- Authorization Code ---<|               |
     +-|----|---+                                 +---------------+
       |    |                                         ^      v
      (A)  (C)                                        |      |
       |    |                                         |      |
       ^    v                                         |      |
     +---------+                                      |      |
     |         |>---(D)-- Authorization Code ---------'      |
     |  Client |          & Redirection URI                  |
     |         |                                             |
     |         |<---(E)----- Access Token -------------------'
     +---------+       (w/ Optional Refresh Token)

認可コードフローの図は RFC 6749 – 4.1. Authorization Code Grant を参照ください。

インプリシットフロー

インプリシットフロー(Implicit Grant)は、トークンエンドポイントが不要で、認可エンドポイントから直接トークンを返す、認可コードフローの一部を省略したフローになります。

     +----------+
     | Resource |
     |  Owner   |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier     +---------------+
     |         -+----(A)-- & Redirection URI --->|               |
     |  User-   |                                | Authorization |
     |  Agent  -|----(B)-- User authenticates -->|     Server    |
     |          |                                |               |
     |          |<---(C)--- Redirection URI ----<|               |
     |          |          with Access Token     +---------------+
     |          |            in Fragment
     |          |                                +---------------+
     |          |----(D)--- Redirection URI ---->|   Web-Hosted  |
     |          |          without Fragment      |     Client    |
     |          |                                |    Resource   |
     |     (F)  |<---(E)------- Script ---------<|               |
     |          |                                +---------------+
     +-|--------+
       |    |
      (A)  (G) Access Token
       |    |
       ^    v
     +---------+
     |         |
     |  Client |
     |         |
     +---------+

インプリシットフローの図は RFC 6749 – 4.2. Implicit Grant を参照ください。

リソースオーナーフロー

リソースオーナーフロー(Resource Owner Password Credentials Grant)は、リソースオーナーが入力したユーザIDとパスワードを使ってトークンを取得するフローになります。

     +----------+
     | Resource |
     |  Owner   |
     |          |
     +----------+
          v
          |    Resource Owner
         (A) Password Credentials
          |
          v
     +---------+                                  +---------------+
     |         |>--(B)---- Resource Owner ------->|               |
     |         |         Password Credentials     | Authorization |
     | Client  |                                  |     Server    |
     |         |<--(C)---- Access Token ---------<|               |
     |         |    (w/ Optional Refresh Token)   |               |
     +---------+                                  +---------------+

リソースオーナーフローの図は RFC 6749 – 4.3. Resource Owner Password Credentials Grant を参照ください。

クライアントフロー

クライアントフロー(Client Credentials Flow)は、他のフローとは異なり、ブラウザ上での入力などは発生しないフローになります。

     +---------+                                  +---------------+
     |         |                                  |               |
     |         |>--(A)- Client Authentication --->| Authorization |
     | Client  |                                  |     Server    |
     |         |<--(B)---- Access Token ---------<|               |
     |         |                                  |               |
     +---------+                                  +---------------+

クライアントフローの図は RFC 6749 – 4.4. Client Credentials Grant を参照ください。


OAuth認証

OAuthは認可のプロトコルですが、リソースサーバがユーザ情報を返す場合、OAuthでも認証ができるようになります。

認可コードフローに基づいた、OAuth認証の流れは以下のようになります。

  1. リソースオーナーは、クライアント上の画面でボタンを押下します。
  2. クライアントは、認可サーバ(Facebook OAuth)に対してリソースサーバへのアクセス権を要求します(この際リダイレクトが発生します)。
  3. 認可サーバは、リソースオーナー(Facebookユーザ)に対して、リソースサーバ(Facebook UserInfo Endpoint)へのアクセス権をクライアントに移譲することについての意思を確認します。
  4. リソースオーナーは、権限を移譲することに同意します。
  5. 認可サーバは、アクセストークンを発行してクライアントに渡します(この際リダイレクトが発生します)。
  6. クライアントは、アクセストークンを使用してリソースサーバにアクセスします。
  7. リソースサーバは、アクセストークンの有効性と権限(スコープ)を確認し、問題がなければ情報を返します。

認証にOAuth2.0を使用する際の注意事項

  • アクセストークンを持っていても認証の証明にはなりません。どのようにアクセストークンが発行されたかに依存します。例えば、別のクライアントによって発行された意図しないアクセストークンの可能性があります。この問題を解決するためにはトークンにユーザーと認証情報を持たせる必要がありますが、OAuth 2.0 ではアクセストークンのフォーマットや構造について定義していないため、各実装が独自のフォーマットを定義して使用しているのが現状です(この問題を解決するためにOpenID Connectプロトコルがあります)。
  • アクセストークンでリソースサーバにアクセスできることは認証の証明になりません。リフレッシュトークンの仕組みを使えば、ユーザがいなくてもトークンを取得することができるためです。アクセストークンを持っていてもユーザが必ず存在するわけではありません。
  • OAuth認証をインプリシットフローで運用してはいけません。トークンエンドポイントにリクエストしなくてもアクセストークンを取得できるインプリシットフローでは、攻撃者がアクセストークンをコピーして、それを別のアプリのログインに使用できるようになるからです。この問題はインプリシットフローの代わりに認可コードフローを使うことで解決できます。

トークンイントロスペクションによるアクセストークンの情報取得

リソースサーバは、Authorizationヘッダで渡されたアクセストークンをOAuth認可サーバのトークンイントロスペクションAPI (RFC 7662) に送信します。そこから返却されるアクセストークンの情報を取得して、アクセストークンの検証を行い、アクセス可否を判断します。 トークンイントロスペクションAPIの結果で検証が必須の項目・推奨の項目は以下の通りです。

  • 検証が必須の項目
    • active属性(有効性)の値が「true」であること
    • exp属性(有効期限)の有効期限が切れていないこと
    • scope属性(スコープ)の値に要求されているAPIに対応するスコープが含まれていること
  • 検証が推奨されている項目
    • iss属性(発行者)の値がOAuth認可サーバを表す値と一致すること
    • token_type属性(タイプ)の値が「Bearer」であること
    • iat属性(発行時刻)が現在時刻よりも過去であること

OAuth 2.0 関連のRFC一覧


OpenID Connect

OpenID Connect (OIDC) は、OAuth 2.0 を使ってユーザ認証を行うための方法を定義しています。 OpenID Connect は OAuth 2.0 に加えて JOSE (JSON Object Signing and Encryption) や JWT (JSON Web Tokens) の仕様を採用しており、送信する情報を署名や暗号化ができるようになっています。 OpenID Connect は OAuth 2.0 で認証をする際の落とし穴に落ちないようにするための仕様です。

OAuthとOpenID Connectではロールの呼び方が異なります。

OAuth OpenID Connect
リソースオーナー (Resource Owner) エンドユーザー (End User)
クライアント (Client) リライングパーティ (RP; Relying Party)
認可サーバ (Authorization Server) IDプロバイダー (IdP; ID Provider)
リソースサーバ (Resource Server) UserInfoエンドポイント

OpenID Connectの用語を以下に示します。

  • IDトークン (ID Token) は、認証と認可の情報を含む署名付きのJWT(JSON Web Token)形式のトークンのことです。
  • UserInfoエンドポイントは、提示するクライアントに対してアイデンティティ情報を提供するエンドポイントのことです。
  • OpenID Provider (OP) は、ユーザの認証を行うサーバのことです。IDプロバイダーとUserInfoエンドポイントの両方の機能を含みます。

OpenID Connectを使うことで、以下のことを実現できます。

  • 複数のリライングパーティ (RP) の間でシングルサインオン (SSO) ができます。
  • リライングパーティ (RP) におけるIDと認証の実装の負担を軽減できます。

OpenID Connectでは以下の2種類のフローだけが定義されています。

  • 認可コードフロー (Authorization Code Flow)
  • インプリシットフロー (Implicit Flow)

参考文献