コンテンツにスキップ

PAR

PAR (Pushed Authorization Requests)

PAR(RFC 9126)は、クライアントがユーザーをリダイレクトする前に、認可リクエストパラメータを直接認可サーバーにプッシュできるOAuth 2.0セキュリティ拡張です。

概要

なぜPARを使用するのか?

セキュリティ上の利点

  1. パラメータ改ざん防止

    • 認可パラメータはセキュアなバックチャネル経由で送信
    • ユーザーや中間者によるパラメータ変更不可
    • リクエストの整合性を保証
  2. プライバシー保護

    • 機密パラメータがブラウザ履歴に露出しない
    • リファラーヘッダーからの漏洩なし
    • 認可リクエストの監視を防止
  3. URL長制限の回避

    • ブラウザ/サーバーのURL長制限を回避
    • 多数のパラメータを持つ複雑なリクエストが可能
    • 大きなリクエストオブジェクト(JAR)をサポート
  4. クライアント認証

    • PARエンドポイントでクライアント認証を要求可能
    • 不正な認可リクエストを防止
    • フィッシングリスクを軽減

ユースケース

  • 金融サービス(FAPI準拠)
  • ヘルスケア(HIPAA準拠OAuthフロー)
  • エンタープライズ(多数のパラメータを持つ複雑な認可)
  • モバイルアプリ(ネイティブアプリからのセキュアな認可)

PARの仕組み

フロー概要

  1. クライアントがパラメータをプッシュ: クライアントが認可パラメータをPARエンドポイントに送信
  2. サーバーがパラメータを保存: サーバーが検証して保存(10分TTL)
  3. サーバーがrequest_uriを返却: サーバーが一意のrequest_uriで応答
  4. クライアントがユーザーをリダイレクト: クライアントがrequest_uri付きで認可エンドポイントにリダイレクト
  5. サーバーがパラメータを取得: 認可エンドポイントが保存されたパラメータを取得
  6. 通常のフローを継続: 認可が通常通り進行

APIリファレンス

PARエンドポイント

POST /as/par

リクエスト形式

POST /as/par HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <base64(client_id:client_secret)>
client_id=my_client_id
&response_type=code
&redirect_uri=https://myapp.example.com/callback
&scope=openid+profile+email
&state=abc123
&nonce=xyz789
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256

成功レスポンス

ステータス: 201 Created

{
"request_uri": "urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c",
"expires_in": 600
}
フィールド説明
request_uristring保存されたリクエストを識別する一意のURN
expires_innumber有効期間(秒)(デフォルト: 600 = 10分)

PARを使用した認可エンドポイント

GET /authorize

GET /authorize
?request_uri=urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c
&client_id=my_client_id
Host: auth.example.com
パラメータ必須説明
request_uriYesPARレスポンスからのrequest URI
client_idYesPARリクエストのclient_idと一致する必要がある

使用例

基本的なPARフロー

Step 1: 認可リクエストをプッシュ

Terminal window
curl -X POST https://auth.example.com/as/par \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=my_client_id" \
-d "response_type=code" \
-d "redirect_uri=https://myapp.example.com/callback" \
-d "scope=openid profile email" \
-d "state=abc123" \
-d "nonce=xyz789"

レスポンス:

{
"request_uri": "urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c",
"expires_in": 600
}

Step 2: ユーザーを認可エンドポイントにリダイレクト

const authUrl = new URL('https://auth.example.com/authorize');
authUrl.searchParams.set('request_uri', 'urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c');
authUrl.searchParams.set('client_id', 'my_client_id');
window.location.href = authUrl.toString();

従来方式とPARの比較

従来の認可リクエスト

GET /authorize
?response_type=code
&client_id=my_client_id
&redirect_uri=https://myapp.example.com/callback
&scope=openid+profile+email
&state=abc123

問題点:

  • パラメータがURLに露出
  • ブラウザ履歴に残る
  • URL長に制限
  • 改ざん可能

PAR認可リクエスト

POST /as/par → {request_uri}
GET /authorize?request_uri=urn:ietf:...&client_id=my_client_id

利点:

  • パラメータはPOSTでセキュアに送信
  • ブラウザ履歴に残らない
  • URL長制限なし
  • 改ざん不可

セキュリティ機能

  1. 単一使用: request_uriは取得後すぐに削除
  2. 短い有効期間: デフォルト10分(600秒)
  3. client_IDマッチング: 認可リクエストのclient_idはPARリクエストと一致する必要がある
  4. セキュアストレージ: パラメータは自動有効期限付きでKVに保存

準拠

  • FAPI 2.0: FAPI 2.0準拠にPAR必須
  • OAuth 2.1: PARはOAuth 2.1ドラフトの一部
  • OpenID Connect: すべてのOIDCフローと互換

参考資料