1
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?

はじめに

送信者限定アクセストークンを DPoP (ディーポップ) (RFC 9449) で実現する場合、クライアントはサーバへ送信するリクエストに DPoP proof JWT (Section 4) を含めます。

dpop_bound_access_token.png

その DPoP proof JWT のペイロードには次のクレーム群を含めなければなりません。

クレーム 説明
jti DPoP proof JWT の一意識別子
htm リクエストの HTTP メソッド
htu リクエストのターゲット URI
iat DPoP proof JWT 生成時刻

これらに加え、DPoP proof JWT をアクセストークンと一緒に用いる場合、すなわち、クライアントが保護リソースにアクセスする際は、ath クレームも含めなければなりません。

クレーム 説明
ath アクセストークンの SHA-256 ハッシュの base64url 表現

また、サーバが nonce を要求する場合、nonce クレームも必須となります。

クレーム 説明
nonce サーバから提供された最新の nonce

本記事ではこの nonce について詳細に見ていきます。

nonce を含む DPoP proof JWT のペイロードの例
{
  "jti": "XdPQLwZIH9pmlMhD",
  "htm": "GET",
  "htu": "https://rs.example.com/resource/1",
  "iat": 1755096729,
  "ath": "-7JjHPHFqtqwNHk7dPoU4nL7SgIgLn8vdCiDq-LfovY",
  "nonce": "ZgmFr7UWLrJX0fHB"
} 

nonce の意義

DPoP 仕様の Section 2. Objectives は、XSS コードが未来のタイムスタンプを持つ DPoP proof JWT を生成し、時間経過後に別所でそれを悪用する攻撃について言及しています。この攻撃に対し、もしもサーバが、サーバの提供する時間制限のあるデータを DPoP proof JWT に含めることを要求すれば、作り置きされた DPoP proof JWT を用いた不正アクセスの影響をいくらか抑えることができます。

DPoP proof JWT を生成するのはクライアントなので、そのペイロードに含む時刻関連クレームの値はクライアントが自由に選べます。そのため、DPoP proof JWT の有効期間をサーバ側で制御したい場合、サーバが提供する時間制限のあるデータを DPoP proof JWT に含めることを要求する必要があります。この目的のために nonce クレームが使われます。

nonce の提供方法

DPoP proof JWT に nonce が入っていることを要求するサーバは、DPoP proof JWT に nonce が含まれていない場合、DPoP-Nonce HTTP ヘッダを含むエラー応答を返します。

HTTP/1.1 401 Unauthorized
WWW-Authenticate: DPoP error="use_dpop_nonce"
DPoP-Nonce: ZgmFr7UWLrJX0fHB

RFC 6750 仕様に従うリソースサーバであれば、エラー情報は WWW-Authenticate HTTP ヘッダに書かれており、エラーコードは use_dpop_nonce となっているはずです。

use_dpop_nonce_0.png

このエラーを受け取ったクライアントは、DPoP-Nonce ヘッダの値を取り出し、その値を nonce クレームの値として含む DPoP proof JWT を作成します。

use_dpop_nonce_1.png

そして、リソースリクエストの再送時にその新しい DPoP proof JWT をリクエストに含めます。

use_dpop_nonce_2.png

nonce 有効期限切れの判定

クライアントは、提供された nonce を以降のリソースリクエストでも使い続けます。しかし、その nonce もいつかは有効期限切れとなり、それが原因でサーバはエラー応答を返します。

エラー応答を受け取った際、クライアントはそのエラーの原因が「nonce の有効期限切れ」だと分かれば、そのエラー応答に含まれる最新の nonce を用いて DPoP proof JWT を作り直し、リクエストを再送するでしょう。

しかし、その判定方法はそれほど自明ではありません。というのは、それ専用のエラーコード (例えば dpop_nonce_expired というようなエラーコード) を DPoP 仕様で定め忘れたからです。

ですので、クライアント側としては、次の条件が成り立つときに「nonce 有効期限切れがエラーの原因」と判定することになります。

  1. レスポンスのステータスコードが 401 Unauthorized である
  2. 自分が現在保持している nonce の値とエラー応答に含まれる DPoP-Nonce ヘッダの値が異なる
  3. エラーコードが invalid_dpop_proof である
HTTP/1.1 401 Unauthorized
WWW-Authenticate: DPoP error="invalid_dpop_proof"
DPoP-Nonce: knvXdyXM3FK3QGEK

リクエスト再送ロジック

DPoP nonce を使う場合、定期的にサーバがエラー応答を返すのが期待動作となるので、クライアント側ではそれに対応するリクエスト再送処理を実装しなければなりません。結果としてエラー処理が煩雑になります。

参考までにリクエスト再送の擬似コードを掲載します。

// 現在クライアントが保持している nonce 値を得る。この nonce 値は DPoP proof
// JWT に埋め込まれる。もしもこのクライアントがこれまでにサーバから nonce の
// 提供を一度も受けていない場合、getDpopNonce() メソッドは null を返す。
String dpopNonce = getDpopNonce();

// リソースリクエストを行う。(DPoP proof JWT の生成は invoke メソッド内で行われる)
ResponseInfo rinfo = invoke(request, httpMethod, path, body, mediaType, dpopNonce);

// レスポンスの中に DPoP-Nonce HTTP ヘッダが含まれていれば、そのヘッダの値で
// このクライアントが保持する nonce 値を更新する。レスポンスが DPoP-Nonce
// ヘッダを含んでいなければ、updateDpopNonceIfSupplied() メソッドは
// nonce 値の更新を行わず、null を返す。
String updatedDpopNonce = updateDpopNonceIfSupplied(rinfo.getResponse());

// レスポンスが DPoP nonce エラーを示している場合
if (isDpopNonceError(rinfo.getResponse(), dpopNonce, updatedDpopNonce))
{
    // 最新の nonce 値を用いて DPoP proof JWT を作り、リクエストを再送する。
    rinfo = invoke(request, httpMethod, path, body, mediaType, updatedDpopNonce);
}

// レスポンスのステータスコード
int status = rinfo.getResponse().getStatus();

// リクエストが成功した場合
if (200 <= status && status < 300)
{
    return rinfo;
}

// リクエストが失敗した場合
throw callError(httpMethod, path, rinfo);

DPoP nonce 関連の設定項目 (Authlete 固有)

Authlete には次の DPoP nonce 関連の設定項目があります。

設定項目 説明
Service.dpopNonceDuration DPoP nonce の有効秒数
Service.dpopNonceRequired サーバが DPoP nonce を要求するかどうか
Client.dpopNonceRequired 当クライアントに対して DPoP nonce を要求するかどうか

おわりに

DPoP については過去に動画や文書で説明させていただいております。是非ご覧ください。

【動画】 OAuth・OpenID 標準仕様による徹底的な API 保護 (17:22〜)
【文書】 標準仕様による徹底的な API 保護

1
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
1
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?