メインコンテンツまでスキップ

RFC 8705: OAuth 2.0 Mutual TLS

RFC 8705 は、TLS クライアント証明書を使ったクライアント認証とトークンバインディングの仕様です。このドキュメントでは、mTLS の仕組みと実装方法を解説します。


第1部: 概要編

mTLS とは何か?

mTLS(Mutual TLS)は、TLS ハンドシェイク時にクライアントもサーバーに対して証明書を提示する仕組みです。

通常の TLS(サーバー認証のみ):
クライアント ─── TLS ───► サーバー
証明書提示
「私は example.com です」

Mutual TLS(相互認証):
クライアント ─── TLS ───► サーバー
証明書提示 ◄───────────── 証明書提示
「私は client-A です」 「私は example.com です」

RFC 8705 の 2 つの機能

機能説明
クライアント認証クライアント証明書でクライアントを認証
証明書バインドトークンアクセストークンをクライアント証明書にバインド

なぜ mTLS が必要なのか?

従来の方式の問題

方式問題
client_secret_basicシークレットがネットワークを流れる
client_secret_postシークレットがネットワークを流れる
private_key_jwtJWT のリプレイ攻撃リスク
Bearer Token盗まれたら誰でも使える

mTLS の解決策

mTLS クライアント認証:
- クライアント証明書は TLS 層で検証
- 秘密鍵は一切ネットワークを流れない
- PKI インフラで信頼性を担保

証明書バインドトークン:
- トークンが特定の証明書にバインド
- 証明書を持たない攻撃者はトークンを使用不可

第2部: 詳細編

クライアント認証方式

RFC 8705 では 2 つのクライアント認証方式を定義。

1. PKI Mutual TLS(tls_client_auth)

CA が発行した証明書を使用。認可サーバーは証明書の Subject を検証。

クライアント登録時:
{
"client_id": "s6BhdRkqt3",
"token_endpoint_auth_method": "tls_client_auth",
"tls_client_auth_subject_dn": "CN=client-app,O=Example Inc,C=US"
}

トークンリクエスト:

POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
# TLS クライアント証明書が提示されている

grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcallback
&client_id=s6BhdRkqt3

注意: client_secret は不要。TLS 層でクライアント認証が完了している。

2. Self-Signed Certificate(self_signed_tls_client_auth)

自己署名証明書を使用。認可サーバーは事前登録された証明書と照合。

クライアント登録時:
{
"client_id": "s6BhdRkqt3",
"token_endpoint_auth_method": "self_signed_tls_client_auth",
"jwks": {
"keys": [{
"kty": "RSA",
"use": "sig",
"x5c": ["MIIDQjCCAiqgAwIBAgIGATz..."]
}]
}
}

Subject DN の照合

PKI mTLS では、証明書の Subject DN を照合。

属性パラメータ
Subject DNtls_client_auth_subject_dnCN=client,O=Example,C=US
SAN DNStls_client_auth_san_dnsclient.example.com
SAN URItls_client_auth_san_urihttps://client.example.com
SAN IPtls_client_auth_san_ip192.168.1.1
SAN Emailtls_client_auth_san_emailclient@example.com

証明書バインドアクセストークン

アクセストークンをクライアント証明書にバインドする機能。

仕組み

1. トークンリクエスト時
クライアント ──TLS証明書提示──► 認可サーバー

認可サーバーは証明書のハッシュ(cnf.x5t#S256)を
トークンに紐づけて発行

2. リソースアクセス時
クライアント ──TLS証明書提示──► リソースサーバー
──アクセストークン──►

リソースサーバーは:
a) トークンから cnf.x5t#S256 を取得
b) TLS 証明書のハッシュを計算
c) 両者が一致することを確認

JWT アクセストークンの場合

{
"iss": "https://auth.example.com",
"sub": "user-123",
"client_id": "s6BhdRkqt3",
"exp": 1704070800,
"cnf": {
"x5t#S256": "bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2"
}
}

cnf.x5t#S256 は、クライアント証明書の SHA-256 サムプリント(Base64URL エンコード)。

Introspection の場合

{
"active": true,
"client_id": "s6BhdRkqt3",
"cnf": {
"x5t#S256": "bwcK0esc3ACC3DB2Y5_lESsXE8o9ltc05O89jdN-dg2"
}
}

証明書ハッシュの計算

リソースサーバーでの検証

TLS 終端の考慮事項

多くの本番環境では、TLS がロードバランサーやリバースプロキシで終端される。

クライアント ──TLS──► ロードバランサー ──HTTP──► アプリケーション
証明書提示 │
証明書情報をヘッダーで転送
X-Client-Cert: ...

証明書の転送方法

方式ヘッダー形式
AWS ALBX-Amzn-Mtls-ClientcertURL エンコード PEM
NginxX-SSL-Client-CertURL エンコード PEM
EnvoyX-Forwarded-Client-Cert独自形式

FAPI における mTLS

プロファイルmTLS 要件
FAPI 1.0 Baselineクライアント認証として使用可能
FAPI 1.0 Advancedクライアント認証または DPoP が必須
FAPI 2.0クライアント認証または DPoP が必須

mTLS vs DPoP

観点mTLSDPoP
レイヤーTLS(L4/L5)アプリケーション(L7)
証明書管理PKI インフラが必要不要(自己生成鍵ペア)
TLS 終端プロキシでの転送が複雑ヘッダーで完結
ブラウザサポート限定的JavaScript で実装可能
既存インフラ企業環境で普及新しい環境向け

セキュリティ考慮事項

項目推奨事項
証明書の検証失効確認(CRL/OCSP)を行う
証明書の有効期限適切な期間を設定(1〜2年)
秘密鍵の保護HSM や TPM での保管を推奨
TLS バージョンTLS 1.2 以上必須、TLS 1.3 推奨
暗号スイート強力な暗号スイートのみ許可

Discovery メタデータ

{
"token_endpoint_auth_methods_supported": [
"tls_client_auth",
"self_signed_tls_client_auth",
"private_key_jwt"
],
"tls_client_certificate_bound_access_tokens": true,
"mtls_endpoint_aliases": {
"token_endpoint": "https://mtls.auth.example.com/token",
"introspection_endpoint": "https://mtls.auth.example.com/introspect"
}
}

mtls_endpoint_aliases を使うことで、mTLS 用の専用エンドポイントを提供できる。


参考リンク