🔐

【押さえておきたい】OAuth 2.0とOpenID ConnectとFAPI 2.0の概要

に公開

はじめに

いくつかの仕事のなかで、つぎの技術を採用しました。

  • OAuth 2.0
  • OpenID Connect
  • FAPI 2.0(Financial-grade API)

仕様の理解を進めるなかで、つぎの課題を感じたため、
初級者や中級者の助けになればと、この記事を書くことにしました。

  • OAuth 2.0 / OpenID Connect
    • 日本語の情報も多いですが、中級者向けの情報は少ない。
  • FAPI 2.0
    • 日本語や英語を問わず、情報が少ない。

OAuth 2.0

HTTPのAPIを前提にした、認可のフレームワークである。

APIを呼び出すときに、
パスワードを送信するのではなく、
アクセストークンを送信することで、
セキュリティを向上しつつ、アクセス権を柔軟に制御できる。

アクセストークンの送信には、HTTP Headerが利用されることが多い。

  GET /resource/123 HTTP/1.1
  Host: server.example.com
  Authorization: Bearer mF_9.B5f-4.1J

RFC 6749: The OAuth 2.0 Authorization Framework 日本語訳
RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage 日本語訳

Access Token

アクセスの期間や範囲を示す、文字列である。

Roles

4つの登場人物が中心になる。

Roles Description
リソースオーナー リソースへのアクセスを認可するもの。

基本的には、エンドユーザーが該当する。
Client Credentialsでは、クライアントが該当する。
リソースサーバー リソースを提供するもの。

アクセストークンを検証したあと、APIのレスポンスでリソースを提供する。
クライアント リソースオーナーの認可を得て、リソースを要求するもの。

アクセストークンを送信しつつ、APIのリクエストでリソースを要求する。

サーバー上で動く、ウェブアプリのこともあれば、
デバイス上で動く、スマートフォンアプリのこともある。
認可サーバー リソースオーナーの認証と認可を確認したあと、
クライアントにアクセストークンを発行するもの。

Client Type

クライアントは2種類に分類される。

Client Type Description
コンフィデンシャル クレデンシャルの機密性を維持することができるもの。
または、セキュアなクライアント認証ができるもの。

サーバー上で動く、ウェブアプリなど。
パブリック クレデンシャルの機密性を維持することができず、
セキュアなクライアント認証もできないもの。

デバイス上で動く、スマートフォンアプリなど。

Grant Type

4つのグラントタイプがある。

  • Authorization Code
  • Implicit
  • Resource Owner Password Credentials
  • Client Credentials

グラントタイプごとに、処理の流れが異なる。

それぞれに特徴があるため、
ユースケースに合わせて、グラントタイプを選択することになる。

Authorization Code

代表的なグラントタイプである。

リダイレクトを利用するため、
クライアントはユーザーエージェント(WebBrowser)と対話できなければならない。

  +----------+
  | 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)
処理の流れ

(A)
クライアントがユーザーエージェントを、認可サーバーの認可エンドポイントに送る。

この認可リクエストには、クライアント識別子やリダイレクトURIが含まれる。

(B)
認可サーバーはリソースオーナーを認証したあと、リソースオーナーに認可を求める。

(C)
リソースオーナーが認可をすると、ユーザーエージェントはクライアントにリダイレクトされる。

リダイレクトするとき、クエリパラメータに認可コードなどを付加する。
このリダイレクトを認可レスポンスと呼ぶ。

(D)
クライアントは、認可サーバーのトークンエンドポイントを呼び出す。

このアクセストークンリクエストには、認可コードやリダイレクトURIが含まれる。

(E)
認可サーバーは認可コードなどを検証したあと、アクセストークンを返却する。

このアクセストークンレスポンスには、リフレッシュトークンを含んでもよい。

Implicit

Authorization Codeを単純化した、グラントタイプである。

通信回数が減るため、処理効率を高めることができるが、
特定条件下で攻撃が成立するため、利用には注意したほうがよい。

リダイレクトを利用するため、
クライアントはユーザーエージェント(WebBrowser)と対話できなければならない。

  +----------+
  | 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 |
  |         |
  +---------+
処理の流れ

(A)
クライアントがユーザーエージェントを、認可サーバーの認可エンドポイントに送る。

この認可リクエストには、クライアント識別子やリダイレクトURIが含まれる。

(B)
認可サーバーはリソースオーナーを認証したあと、リソースオーナーに認可を求める。

(C)
リソースオーナーが認可をすると、ユーザーエージェントはクライアントにリダイレクトされる。

リダイレクトするとき、フラグメントにアクセストークンなどを付加する。
このリダイレクトをアクセストークンレスポンスと呼ぶ。

(D)
ウェブアプリがホスティングされる、サーバーにリクエストを送信する。

(E)
サーバーのレスポンスで、スクリプトが返却される。

(F)
ユーザーエージェントはスクリプトを実行し、アクセストークンを取り出す。

(G)
ユーザーエージェントはアクセストークンをクライアントに渡す。

Resource Owner Password Credentials

エンドユーザーのパスワードなど、
クレデンシャルをクライアントに直接に入力する、グラントタイプである。

クライアントの信頼性が高いうえ、
ほかのグラントタイプが利用できないときに、利用されるべきである。

パスワードがクライアントに露呈してしまうが、
アクセストークンと交換するため、長期的な保存の必要はなくなる。

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

(A)
リソースオーナーがクライアントにパスワードを入力する。

(B)
クライアントは、認可サーバーのトークンエンドポイントを呼び出す。

このアクセストークンリクエストには、パスワードが含まれる。

(C)
認可サーバーはパスワードなどを検証したあと、アクセストークンを返却する。

このアクセストークンレスポンスには、リフレッシュトークンを含んでもよい。

Client Credentials

クライアントのパスワードなど、
クレデンシャルを直接に送信する、グラントタイプである。

クライアントがリソースオーナーとなり、
クライアントの権限でリソースを要求する。

クライアントの権限でリソースを要求するか、
エンドユーザーの権限でリソースを要求するか、
ほかのグラントタイプとは、認可の種類が異なる。

コンフィデンシャルクライアントにだけ、適用できる。

  +---------+                                  +---------------+
  |         |                                  |               |
  |         |>--(A)- Client Authentication --->| Authorization |
  | Client  |                                  |     Server    |
  |         |<--(B)---- Access Token ---------<|               |
  |         |                                  |               |
  +---------+                                  +---------------+
処理の流れ

(A)
クライアントは、認可サーバーのトークンエンドポイントを呼び出す。

このアクセストークンリクエストには、クライアントのクレデンシャルが含まれる。

(B)
認可サーバーはクレデンシャルなどを検証したあと、アクセストークンを返却する。

OpenID Connect

OAuth 2.0をベースにした、認証のフレームワークである。

OAuth 2.0では、アクセストークンが発行されるが、
OpenID Connectでは、IDトークンが発行される。

実際には、アクセストークンとIDトークンは同時に発行されることが多い。

IDトークンを検証することで、エンドユーザーの認証(本人確認)ができる。

OpenID Connect Core 1.0 日本語訳

ID Token

認証情報が含まれる、文字列である。

IDトークンの形式はJWTである。

このJWTには、各種の情報が含まれるが、
代表例として、つぎのクレームが含まれている。

Claim Description
iss IDトークンの発行者
sub エンドユーザーの識別子
aud IDトークンの発行先
exp IDトークンの有効期限
iat IDトークンの発行時刻
  {
   "iss": "https://server.example.com",
   "sub": "24400320",
   "aud": "s6BhdRkqt3",
   "exp": 1311281970,
   "iat": 1311280970,
   ...
  }

IDトークンに署名は必須だが、暗号化は任意である。

Roles

3つの登場人物が中心になる。

Roles Description
End-User エンドユーザー。

OAuth 2.0のリソースオーナーに相当する。
Relying Party IDトークンを要求するもの。

OAuth 2.0のクライアントに相当する。
OpenID Provider エンドユーザーの認証と認可を確認したあと、
Relying PartyにIDトークンを発行するもの。

OAuth 2.0の認可サーバーに相当する。

Authentication Flow(Grant Type)

3つの認証フローがある。

  • Authorization Code
  • Implicit
  • Hybrid

認証フローごとに、処理の流れが異なる。

それぞれに特徴があるため、
ユースケースに合わせて、認証フローを選択することになる。

OAuth 2.0とOpenID Connectで、流れに違いはない。

Authorization CodeとImplicitを組み合わせたものが、Hybridである。

Client Authentication

5つのクライアント認証がある。

  • client_secret_basic
  • client_secret_post
  • client_secret_jwt
  • private_key_jwt
  • none

それぞれに特徴があるため、
ユースケースに合わせて、クライアント認証を選択することになる。

トークンエンドポイントを呼び出すときなどに利用する。

FAPI 2.0

OAuth 2.0をベースにした、セキュリティプロファイルである。

金融など、高いセキュリティが求められるAPIに適している。

セキュリティプロファイルには、
つぎのチェックリストや技術仕様が含まれており、
適用することで、OAuth 2.0とOpenID Connectの安全性を向上できる。

Specification Description
FAPI 2.0 Security Profile Attacker Modelの目標を達成するためのチェックリスト。

BaselineからSecurity Profileに名称が変更された。
つまり、Baselineに相当の仕様である。
FAPI 2.0 Attacker Model
FAPI 2.0: Message Signing 認可サーバーへのリクエストとレスポンスに署名する。

AdvancedからMessage Signingに名称が変更された。
つまり、Advancedに相当の仕様である。
FAPI 2.0 Http Signatures リソースサーバーへのリクエストとレスポンスに署名する。

RFC 9421をベースにしている。

FAPI 2.0 Security Profile

チェックリストの項目は100に近い。

HTTPでユーザーエージェントをリダイレクトするとき、
307ではなく、303のステータスコードを利用するなど、
単純なチェックリストもあるが、

RFC 9126に従い、Pushed Authorization Requestsをサポートするなど、
複雑なチェックリストもある。

ここでは代表例を紹介する。

Client Type

Confidential Clientに制限されている。

Sender-Constrained Access Token

つぎのいずれかの方法で、
送信者制約アクセストークンを発行することが求められる。

  • MTLS(RFC 8705)
  • DPoP(RFC 9449)

Client Authentication

つぎのいずれかの方法で、
クライアント認証を実施することが求められる。

  • MTLS(RFC 8705 - Section 2)
  • private_key_jwt(OIDC - Section 9)

Pushed Authorization Request

RFC 9126に従い、
Pushed Authorization Request(PAR)を実施することが求められる。

FAPI 2.0 Security Profileの処理の流れ

Sender-Constrained Access TokenとClient Authenticationに、
MTLSを採用と仮定すると、つぎの処理の流れになる。

Access Tokenの発行

Access Tokenの利用

Accenture Japan (有志)

Discussion