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

Client Instance 登録API (1.0.0)

Download OpenAPI specification:Download

ネイティブアプリのインスタンスが、端末内で生成した鍵(Client Instance Key)を認可サーバーに登録するためのエンドポイント仕様。 Attestation-Based Client Authentication(attest_jwt_client_auth)で client_attestation_trust_source: registered_instance_key を使う構成で必要になります。

Client Instance

アプリのインスタンスごとに端末内で生成した鍵を、認可サーバーに登録するAPI群。

登録が済むと、そのインスタンスは自分の鍵で Client Attestation JWT を自己署名し、 トークンエンドポイント等で attest_jwt_client_auth として認証できるようになります。 認証フェーズの仕様は RP用API を参照してください。

インスタンスは利用者に束縛されます

登録されたインスタンスは、登録時にログインした利用者に束縛されます (client_instance_registration_policy: user_bound)。

流れ

1. POST /v1/client-instances/challenges  → challenge / instance_id
2. 端末内で鍵を生成し、request_hash を計算
     request_hash = base64url_nopad( SHA-256( challenge_bytes || canonical_jwk_utf8 ) )
3. 認可リクエスト(nonce = request_hash)で利用者がログイン → ID トークン
4. challenge を埋め込んだプラットフォーム証明を取得
5. POST /v1/client-instances(ID トークン + 公開鍵 + 証明) → 登録完了

チャレンジを先に発行するのは、プラットフォーム証明と ID トークンを この登録のために作られたものに縛るためです。

認証

登録はクライアント認証より前に行う必要があるため、どちらのエンドポイントも クライアント認証を要求しません。

  • POST /v1/client-instances/challenges は無認証です
  • POST /v1/client-instances は ID トークン(誰か)と プラットフォーム証明(どの端末・鍵か)で 認証されます。ID トークンの nonce が request_hash なので、ID トークンはその鍵の登録にしか使えません

ID トークンは、クライアント認証なしで取得します。

経路 取得のしかた 使いどころ
同じクライアント ハイブリッドフロー(response_type=code id_token)。同じ応答のコードは、登録した鍵の attest_jwt_client_auth で交換する 基本
登録用クライアント 登録先クライアントの extension.client_instance_registration_clients に載せたパブリッククライアント PAR 必須のテナント

検証の中身は Attestation-Based Client Authentication を参照してください。

検証器(PlatformAttestationVerifier)が1つも登録されていない場合、すべての登録が拒否されます。 無認証エンドポイントに対する安全側の既定です。

登録チャレンジの発行

登録に使う一回限りのチャレンジと、予約された instance_id を発行します。

発行できるのは、token_endpoint_auth_method が attest_jwt_client_auth で、 extension.client_instance_registration_policy が user_bound のクライアントだけです。 未設定・未知の値のクライアントには発行しません。

レスポンスは Cache-Control: no-store を伴います。

path Parameters
tenant-id
required
string <uuid>

テナント識別子

Request Body schema: application/json
required
client_id
required
string

登録先のクライアント。token_endpoint_auth_method が attest_jwt_client_auth であること

Responses

Request samples

Content type
application/json
{
  • "client_id": "de2f6a1c-8f29-4a1f-9a2b-1c0d5f7e3b44"
}

Response samples

Content type
application/json
{
  • "challenge": "string",
  • "instance_id": "string",
  • "expires_in": 300
}

Client Instance の登録

発行済みのチャレンジ・ID トークン・登録したい公開鍵・プラットフォーム証明を提示して、 Client Instance を登録し、ID トークンの利用者に束縛します。

ID トークンについて、サーバーは次を確認します。

  1. この認可サーバーが署名した JWS であること(暗号化された ID トークンは受け付けません)
  2. iss がこの認可サーバーで、exp を過ぎていないこと
  3. aud が登録先のクライアント、またはその client_instance_registration_clients に載ったクライアントであること
  4. nonce が、チャレンジと client_instance_public_key から計算した request_hash と一致すること
  5. iat がチャレンジの発行より後であること(この登録のためのログインであること)
  6. sub の利用者が存在し、有効であること

プラットフォーム証明について、次の3つがすべて成立することを確認します(詳細は Attestation-Based Client Authentication)。

  1. チャレンジの束縛 — 証明がこの登録のために作られたこと
  2. インスタンス鍵の束縛 — 証明が client_instance_public_key を対象にしていること
  3. アプリ同一性の束縛 — 証明されたアプリがこのクライアントのアプリであること

加えて証明書チェーンをピン留めしたルートまで検証し、鍵がセキュアハードウェアで 生成された署名可能な鍵であることを確認します。

同じテナントの中で、すでにいずれかのインスタンス(失効したものを含む)に登録されている鍵は登録できません。

利用者 1 人につき、クライアントごとに有効なインスタンスは 1 つです。 登録が成功すると、 同じ利用者の同じクライアントの他の有効なインスタンスは失効します(revocation_reason: superseded)。 失効したインスタンスは次のクライアント認証(リフレッシュを含む)で拒否されます。トークンは削除しないため、 発行済みのアクセストークンは有効期限まで使えます。失効したインスタンスごとにセキュリティイベント client_instance_revoked を出します。同じ利用者の登録が同時に 2 件走った場合、後の方は失敗します。

登録が済むと、このインスタンスは自分の鍵で Client Attestation JWT を自己署名できます。

レスポンスは Cache-Control: no-store を伴います。

path Parameters
tenant-id
required
string <uuid>

テナント識別子

Request Body schema: application/json
required
challenge
required
string

POST /v1/client-instances/challenges で得た値

id_token
required
string

登録を認証する ID トークン。nonce に request_hash を指定した認可リクエストで取得したもの。 aud は登録先のクライアント、またはその client_instance_registration_clients に載ったクライアント

client_instance_public_key
required
object

登録する公開鍵(JWK)。プラットフォーム証明が対象にしている鍵と一致すること。 以降の Client Attestation JWT はこの鍵の秘密鍵で署名します

required
Android Key Attestation (object) or Apple App Attest (object) (PlatformEvidence)

プラットフォームが発行した、鍵とアプリに関する証明。platform の値で構造が決まります。

対応プラットフォームは PlatformAttestationVerifier の実装として登録されたものだけです。 未知の platform は拒否されます。

Responses

Request samples

Content type
application/json
Example
{
  • "challenge": "Zm9vYmFyLWNoYWxsZW5nZS0wMQ",
  • "id_token": "<nonce に request_hash を指定して取得した ID トークン>",
  • "client_instance_public_key": {
    },
  • "platform_evidence": {
    }
}

Response samples

Content type
application/json
{
  • "instance_id": "string"
}