0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OAuth/OIDCの「クライアント認証」方式を整理する

0
Posted at

システムとしてAPIを構築・提供する際、APIを呼び出すクライアントをどのように認証するか「クライアント認証方式」を考える必要があります。

クライアント認証とはOAuth 2.0 / OpenID Connect(OIDC)でアクセストークンを取得するときに、クライアント自身を認証する方式 のことです。

クライアント認証方式にはさまざまな方式があり、APIの公開範囲や相手先との信頼関係、セキュリティなどさまざまな観点からどの方式で認証すべきか検討する必要があります。

  • client_secret_basic
  • private_key_jwt
  • tls_client_auth
  • self_signed_tls_client_auth

本記事では、各クライアント認証方式の概要について整理し、提供するAPIについて適切な認証方式を選択できるようまとめます。


1. 「クライアント認証」と「API認可」の概要

まずは前提となる「クライアント認証」と「API認可」の違いを説明します。

OAuth 2.0 のクライアントがAPIを呼び出す典型的な流れは、次のようになります。

ここで役割を分けると、次の通りです。

処理 確認すること 代表例
クライアント認証 トークンを要求しているクライアントは正規のクライアントか client_secret_basic, private_key_jwt, mTLS
API認可 このアクセストークンでAPI操作を許可してよいか scope、audience、roleなどの検証

今回考えるのはAPIの呼び出し元であるクライアントをどのように認証するかであるクライアント認証方式についてそれぞれの違いや向いている用途を整理したいと思います。


2. クライアント認証方式の種類

OAuthにおけるトークンエンドポイントのクライアント認証方式には下記のような種類があります。

方式名 意味 主な定義元
none クライアント認証なし RFC 7591 / OAuth Public Client
client_secret_post POST bodyでクライアントシークレットを送信 RFC 6749、RFC 7591
client_secret_basic HTTP Basic認証でクライアントシークレットを送信 RFC 6749、RFC 7591
client_secret_jwt 共有シークレットを鍵にした署名JWTで認証 OpenID Connect Core 1.0
private_key_jwt 秘密鍵で署名したJWTで認証 OpenID Connect Core 1.0、RFC 7523
tls_client_auth PKIベースのmTLSで認証 RFC 8705
self_signed_tls_client_auth 自己署名証明書ベースのmTLSで認証 RFC 8705

またそれぞれの方式ごとの特徴は下記となります。

方式 クライアントが保持するもの 特徴 想定ケース
none 認証用の秘密情報なし Public Client向け。通常はPKCEと併用 SPA、モバイルアプリ
client_secret_basic 共有シークレット シンプルで広く利用される 通常のサーバーサイドアプリ
client_secret_post 共有シークレット シークレットをリクエストbodyに含める Basicを利用できない制約がある場合
client_secret_jwt 共有シークレット シークレットをHMAC署名鍵として使う JWT assertionを利用したい場合
private_key_jwt 秘密鍵 秘密鍵を送らず、公開鍵で検証可能 BFF、M2M、高セキュリティAPI連携
tls_client_auth CA発行のクライアント証明書と秘密鍵 PKI/CAによる証明書信頼モデル 企業間・金融API
self_signed_tls_client_auth 自己署名証明書と秘密鍵 登録済み公開鍵・証明書を直接信頼 限定されたM2M連携

3. none:クライアント認証なし

none は、SPAやモバイルアプリなど、クライアントシークレットを安全に保持できない Public Client が使う方式です。

クライアント認証は行いませんが、認可コードフローでは通常 PKCE(RFC 7636) を利用して、認可コードの横取り対策を行います。

PKCEはクライアント認証そのものではなく、認可コード横取り対策の仕組みです。


4. client_secret_basic:Basic認証でシークレットを送る

client_secret_basic は、client_idclient_secret を HTTP Basic 認証で送る方式です。

POST /oauth2/token HTTP/1.1
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials

シンプルで広くサポートされている一方、クライアントと認可サーバーが同じシークレットを保持するため、シークレットの保管・ローテーションが重要です。


5. client_secret_post:POST bodyでシークレットを送る

client_secret_post は、client_idclient_secret をリクエストbodyに含める方式です。

POST /oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&
client_id=batch-client&
client_secret=secret-value

Authorizationヘッダーを設定できない、または、プロキシやゲートウェイでAuthorizationヘッダーが削除されてしまうようなHTTP Basic認証を扱えない環境では候補になりますが、シークレット値そのものを送る点はclient_secret_basic と共通です。


6. client_secret_jwt:共有シークレットでJWTに署名する

client_secret_jwt は、クライアントシークレットを直接送る代わりに、共有シークレットを使ってJWTへHMAC署名し、そのJWTをクライアント認証に使う方式です。

HMAC署名とは、共有している秘密鍵(secret)とハッシュ関数を使って、データが改ざんされていないこと・正しい相手が作成したことを確認する仕組みのこと

JWT assertionの送信例は次のようになります。

POST /oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&
client_id=batch-client&
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&
client_assertion=eyJ...

client_secret 自体を通信で送らない点は特徴ですが、クライアントと認可サーバーが共有シークレットを持つ信頼モデルは変わりません。


7. private_key_jwt:秘密鍵でJWTに署名する

private_key_jwt は、クライアントが自身の秘密鍵で署名したJWTを client_assertion として送る方式です。

認可サーバーは、事前に登録された公開鍵やJWKSを使って署名を検証します。

JWKS は JSON Web Key Set の略で、JWTなどの署名を検証するための公開鍵を、JSON形式で複数まとめて公開する仕組み

client_secret のような共有秘密を認可サーバーに保持させず、検証用の公開鍵のみを登録できる点が特徴です。

JWT assertionの送信例は次のようになります。

{
  "iss": "batch-client",
  "sub": "batch-client",
  "aud": "https://auth.example.com/oauth2/token",
  "iat": 1770000000,
  "exp": 1770000300,
  "jti": "b72865d5-68b6-4c62-a99a-6dde7108ee62"
}

代表的なクレームの意味は以下です。

クレーム 意味
iss JWTの発行者。通常は client_id
sub 認証対象。通常は client_id
aud JWTの宛先。通常はトークンエンドポイント
iat 発行時刻
exp 有効期限
jti JWTの一意識別子。リプレイ対策で利用可能

8. tls_client_auth:PKIベースのmTLS

tls_client_auth は、認可サーバーが信頼するCAから発行されたクライアント証明書を利用する方式です。

認可サーバーは、主に以下を確認します。

  • 証明書チェーンが信頼できるCAにつながること
  • クライアントに登録された Subject DN や SAN 等の値と、提示された証明書が対応すること

この方式は、外部企業とのAPI連携や金融系APIなど証明書管理・失効管理を求められる環境、多数クライアントをPKI運用で統制したい場合に向いています。

mTLSとは何か

mTLS の mmutual(相互) です。

通常のTLSでは、クライアントが主にサーバー証明書を検証します。一方、mTLSでは、サーバーもクライアント証明書を検証します。

OAuth 2.0 で mTLS を使う場合、RFC 8705 は次の2種類のクライアント認証方式を定義しています。

  • tls_client_auth
  • self_signed_tls_client_auth

9. self_signed_tls_client_auth:自己署名証明書ベースのmTLS

self_signed_tls_client_auth は、自己署名クライアント証明書を利用する方式です。

認可サーバーは、CAの証明書チェーンを信頼の根拠にするのではなく、クライアントに紐づけて事前登録された証明書または公開鍵と、接続時に提示された証明書を照合します。

この方式は、管理対象クライアントが少ないM2M連携や特定パートナーとの限定されたAPI連携、PKI運用を設けず、公開鍵の事前登録で管理できる構成に向いています。

tls_client_authself_signed_tls_client_auth の違い

self_signed_tls_client_auth は「自己署名だから即座に危険」という意味ではありません。
何を信頼の根拠にするかが違う方式です。ただしクライアント数が増えると、証明書の登録・更新・失効の個別管理が重くなりやすい点には注意が必要です。

観点 tls_client_auth self_signed_tls_client_auth
証明書 CA発行証明書 自己署名証明書
信頼の根拠 信頼済みCA・PKI 事前登録した証明書または公開鍵
照合方法 証明書チェーン検証 + Subject DN / SAN 等 登録済み証明書・公開鍵との一致
失効・更新管理 CA/PKI運用に寄せられる クライアント単位で登録情報を更新
適した規模 多社・大規模・統制重視 小規模・限定連携

まとめ

client-authenticate.png

API連携を設計する際は、「アクセストークンをどう使ってAPIを認可するか」だけでなく、そのアクセストークンを取得するクライアントをどう認証するか まで分けて考えると、方式選定が整理しやすくなります。

参考になりましたら、ぜひ「いいね」をお願いします。


参考仕様・ドキュメント

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?