v0.11.0 影響確認 — verified_claims の OIDC4IDA 準拠化・配信・移行
本ドキュメントは v0.11.0 に含まれる verified_claims(身元確認済みクレーム)関連の変更と、その利用者側(RP / テナント運用者)への影響をまとめる。
Issue #1435 / PR #1514 対応: 身元確認済みクレーム(verified_claims)の Access Token 出力構造を OIDC4IDA 準拠のネスト構造に修正し、UserInfo エンドポイントでの返却に対応した。
Issue #1628 追加対応: UserInfo を claims パラメータ(OIDC4IDA 標準の要求方式)経由でも返せるようにし、verified_claims の §5.7「要求より少なく返す」挙動を仕様精査に基づいて見直した(claims が空でも verification は返す)。あわせて「何のクレームに同意したか」の記録を grant に自己完結保存する内部変更を行った。
影響まとめ
| 変更 | 種別 | 対象 |
|---|---|---|
Access Token の verified_claims がフラット → ネスト構造(verification + claims)になる | 🔴 破壊的 | access_token_selective_verified_claims を有効にしているテナントと、その Access Token を消費する RP / リソースサーバー |
UserInfo が verified_claims を返すようになる(スコープ経由) | 🟢 追加 | access_token_selective_verified_claims + verified_claims:* スコープを使うテナント |
UserInfo が claims パラメータ(OIDC4IDA 標準)経由でも verified_claims を返す(フラグ不要) | 🟢 追加 | claims パラメータで userinfo.verified_claims を要求する RP(#1628) |
要求クレームが全て利用不可/不一致でも verification + 空 claims を返す(従来の「全体省略」を見直し) | 🟡 挙動変更 | verified_claims を消費する RP(§5.7 / #1512 の挙動見直し) |
claims パラメータの value / values 制約が verified_claims 要求でも適用される(従来は無視) | 🟡 挙動変更 | claims で value/values 制約付き verified_claims を要求する RP(#1624) |
verified_claims:* スコープ・access_token_selective_verified_claims フラグの設定追従 | 🟡 設定 | eKYC / 身元確認を提供するテナント |
Discovery に OIDC4IDA §8 メタデータ(verified_claims_supported 等)を広告+ evidence/trust_frameworks の supported 値を 1.0 正規値へ | 🟢 追加 / 🟡 挙動変更 | テナントの Discovery を読む RP(#1513 / #1651) |
verified_claims 要求(同意内容)を grant に sentinel 形式で自己完結保存(ID Token 側も対象) | ⚙️ 内部/運用 | テナント運用者(ローリングデプロイ / 同意レコード) |
| 身元確認申込みのステータス遷移を状態機械化(前進のみ・終端吸収・hard error 非遷移) | 🟡 挙動変更 | eKYC / 身元確認を提供するテナント(承認 → verified_claims 付与の前提となるライフサイクル, #1617) |
承認時に標準クレーム・custom_properties・ユーザーステータスも更新可能に(user_claims_mapping_rules / custom_properties_mapping_rules / user_status) | 🟢 追加 | eKYC / 身元確認を提供するテナント(承認時のユーザー属性更新, #1582) |
verified_claims / custom_properties の更新ポリシー(*_update_policy)を追加 | 🟢 追加 / 🟡 設定 | 段階的KYC・属性同期を行うテナント(#1584) |
承認時に実際適用した user_claims / custom_properties / user_status を結果レコードに記録(applied_user_claims カラム追加) | 🟢 追加 | eKYC / 身元確認を提供するテナント(承認時のユーザー属性変更の監査・トレーサビリティ, #1607) |
1. Access Token の構造変更(破壊的)
Before(フラット展開)
{
"verified_claims": {
"given_name": "Taro",
"family_name": "Yamada"
}
}
After(OIDC4IDA 準拠のネスト構造)
{
"verified_claims": {
"verification": {
"trust_framework": "eidas"
},
"claims": {
"given_name": "Taro",
"family_name": "Yamada"
}
}
}
verification(検証プロセスのメタデータ)と claims(検証済みクレーム値)が分離される。これは OpenID Connect for Identity Assurance 1.0 の verified_claims 構造に準拠する。
Access Token でも正規構造を使う根拠: OIDC4IDA §4.7 は Access Token での
verified_claims利用を「可能」と述べるのみで構造を規定しない。この穴を RFC 9068 §2.2.2(IANA 登録済みクレームは登録名・定義に従って encode すべき(SHOULD))が補完する。verified_claimsは IANA JWT Claims Registry 登録済みで、参照先が OpenID Identity Assurance Schema Definition 1.0 §5。その §5.2 / §5.4.2 がverification(必須)+claims(必須)のネスト構造とverification.trust_framework必須を定める。したがって Access Token・ID Token・UserInfo の全配信先で同一の正規構造を用い、AT だけフラット/独自形にはしない。
RP / リソースサーバー側の対応
クレーム値の参照パスを変更する。
| Before | After |
|---|---|
verified_claims.given_name | verified_claims.claims.given_name |
(verification は存在しなかった) | verified_claims.verification.trust_framework 等が参照可能に |
Access Token の
verified_claims出力は選択モード(access_token_selective_verified_claims)に一本化されている(旧・全量モードaccess_token_verified_claimsは #1603 で廃止)。
移行手順(破壊的変更の安全なロールアウト)
サーバーは新旧構造を同時には出力しない(ネスト構造へ一括切替)。RP(クライアント / リソースサーバー)が旧構造前提のままサーバーを更新すると壊れるため、RP を先に両対応させてから切り替える。
-
RP を新旧両対応にする(先行リリース) RP のパースをフラット(旧)・ネスト(新)の両方を受理するよう更新してデプロイする。
- 新(優先):
verified_claims.claims.<claim> - 旧(フォールバック):
verified_claims.<claim>
この時点ではサーバーは旧構造のまま。両対応にしてあるので RP は壊れない。
- 新(優先):
-
新バージョンをリリース サーバーを更新し、
verified_claimsをネスト構造で出力する。RP は既に両対応済みのため無停止で切り替わる。 -
RP のフラット(旧構造)フォールバックを削除 全サーバーが新バージョンに切り替わったことを確認後、手順1で RP に追加したフラット構造のフォールバック処理を削除する。これで RP はネスト構造のみを扱う実装に整理される。
「RP 両対応 → サーバー新バージョンリリース → フォールバック削除」の順を守ること。サーバー先行で切り替えると、未対応の RP で
verified_claims参照が壊れる。
2. UserInfo での verified_claims 返却(追加)
これまで UserInfo は verified_claims を返さなかったが、本変更で返却するようになった。Access Token / ID Token と同じネスト構造(verification + claims)で返る。
// GET /v1/userinfo の応答(抜粋)
{
"sub": "...",
"verified_claims": {
"verification": { "trust_framework": "eidas" },
"claims": { "given_name": "Taro", "family_name": "Yamada" }
}
}
2.1 2つの要求方式
| 方式 | 要求方法 | フラグ | 位置づけ |
|---|---|---|---|
verified_claims:* スコープ | Access Token のスコープ | access_token_selective_verified_claims: true が必要 | idp-server 独自拡張。要素単位の選択は 3.1 |
claims パラメータ(#1628) | 認可リクエストの claims の userinfo.verified_claims メンバ | 不要 | OIDC4IDA 標準。value / values 制約や §5.7 の選択的省略が適用される |
スコープ経由は
access_token_selective_verified_claimsフラグに依存するが、claimsパラメータ経由はフラグ非依存で動作する(標準の要求メカニズムのため)。スコープ経由で返るclaimsは Access Token が持つverified_claims:<claim>スコープに対応するものに限られ、verificationの任意要素はverified_claims:verification:<element>スコープで選択する(3.1)。
2.2 競合時の優先順位
両経路はどちらもトップレベルの verified_claims キーを生成するため、1リクエストで両方が指定された場合は claims パラメータ(標準)を優先し、verified_claims:* スコープ(独自拡張)側は出力しない(両方を同時指定する RP は実運用では想定していない)。
2.3 返却ルール(§5.7「要求より少なく返す」)
要求したクレームのうち、ユーザーが保持しない/value・values 制約に一致しないものは個別に省かれる。その結果 claims が空になっても、verification が有効なら verified_claims は verification + 空 claims(claims: {})で返す。IDA スキーマが「claims は空でよい」と定める(IDA-verified-claims §5.3)ため、§5.7.5 の親要素省略は空 claims では発火しない、という仕様精査の結論による(#1512 の「全体省略」を見直し)。
verified_claims を丸ごと省略するのは verification 要件が満たせない場合のみ(verification 要素の value/values 不一致、または必須の trust_framework をユーザーが持たない=§5.7.4)。この挙動は ID Token / UserInfo で共通(OIDC4IDA は配信先を区別しない §5.2)。
RP への影響: 「
verified_claimsが無い=ユーザーは検証済み属性を持たない」と決め打ちしないこと。要求クレームが揃わなくても{"verification": {...}, "claims": {}}が返り得る。
v0.11.0 修正(#1624):
claimsパラメータのvalue/values制約が verified_claims 要求で無視されていた問題を修正した(OIDC4IDA 5.5.1 / 5.7.4 )。指定したvalue/valuesに一致しない検証済みクレームは返らない(制約マッチが効く)ようになったため、value/valuesで絞り込む RP は返却が変わり得る。
3. 設定の追従
3.1 スコープの列挙
verified_claims の出力は 2種類のスコープで要素単位に制御する。いずれも クライアントの scope に列挙する(必須・スコープ付与の制御点)。テナントの scopes_supported にも列挙することを推奨するが、これは OpenID Connect Discovery / RFC 8414 上の広告用メタデータであり、付与可否の制御には影響しない(実際のスコープ付与は client.scope で決まる)。
| スコープ | 選択対象 | 例 |
|---|---|---|
verified_claims:<claim> | claims 内の検証済みクレーム | verified_claims:given_name |
verified_claims:verification:<element> | verification 内の検証メタデータ | verified_claims:verification:trust_framework / verified_claims:verification:evidence |
本来
claims内の要素はverified_claims:claims:<claim>だが、冗長なためclaims:を省略しverified_claims:<claim>とする。verification:セグメントは検証済みクレームとの区別のため残す(verified_claims:verification:名前空間は常にverification要素として扱われる)。
// client.scope(クライアント登録)★ スコープ付与の制御点(必須)
"openid profile email transfers verified_claims:given_name verified_claims:family_name verified_claims:birthdate verified_claims:address verified_claims:verification:trust_framework"
// authorization_server.scopes_supported(テナント)★ Discovery 広告用(推奨・enforce されない)
[
"openid", "profile", "email", "transfers",
"verified_claims:given_name",
"verified_claims:family_name",
"verified_claims:birthdate",
"verified_claims:address",
"verified_claims:verification:trust_framework",
"verified_claims:verification:evidence"
]
データ最小化:
claimsとverificationの任意要素は、スコープで明示的に要求した要素だけが返る(OIDC4IDA §5.4 / §7)。
- ただし
verification.trust_frameworkは IDA スキーマ上verificationの必須要素なので、スコープ要求の有無に関わらず常に含まれる(verification: {}は非準拠のため出さない)。verified_claims:verification:trust_frameworkスコープは Discovery 広告・明示要求用で、付与しなくてもtrust_frameworkは返る。- 特に
verification.evidenceは書類番号・確認トランザクションID 等の生PIIを含むため、verified_claims:verification:evidenceを明示要求しない限り返さない(オプトイン)。- ユーザーが
trust_frameworkを持たない場合(マッピング設定不備等)は、verification要件を満たせないため §5.7.4 に従いverified_claims全体を返さない。- 選択できる要素名はテナントの verified_claims マッピング設定に追従する(コード側で固定リストを持たない)。
3.2 フラグの有効化
authorization_server.extension に出力モードのフラグを設定する。
{
"extension": {
"access_token_selective_verified_claims": true
}
}
3.3 出力モード
| フラグ | 出力先 | クレーム選択 | 構造 |
|---|---|---|---|
access_token_selective_verified_claims: true | Access Token および UserInfo | verified_claims:* スコープに対応するクレームのみ | verification + claims |
access_token_selective_verified_claimsは Access Token と UserInfo の両方の選択的返却を制御する。UserInfo にverified_claimsを返したい場合はこのフラグを有効にする(スコープ経由のみ。claimsパラメータ経由はフラグ不要 = 2.1)。 旧access_token_verified_claims(スコープ不問で全量を Access Token に焼き込むモード)は #1603 で廃止し、選択モードに一本化した。データ最小化(§3.1)の観点でも全量配信は非推奨だったため。
3.4 同意記録の永続化(運用者向け)
claims パラメータで要求された verified_claims(=ユーザーが何に同意したか)は、grant の userinfo_claims(#1628)に sentinel トークン vc:<base64url(JSON)> として永続化される(DB スキーマ変更なし)。grant を「同意内容の権威ある記録」とし、トークン発行時に元の認可リクエストが無くても verified_claims を組み立てられるようにするため。同じ方 式を ID Token 側(id_token_claims)にも展開中(#1628 フォローアップ)。
- ローリングデプロイ / ロールバック安全: 旧バージョンは未知の
vc:トークンを単に無視する(クレーム出力はvalues.contains("name")等の既知名チェックで、トークン集合を列挙しない)。新旧混在・巻き戻しでもクラッシュや誤クレーム混入は起きない。 - 同意内容の確認: 現状この sentinel は Grant 管理 API のレスポンスには出していない(
scopesのみ)。同意したverified_claimsを API から観測可能にする対応は #1644 で追跡。
3.5 Discovery メタデータ(OIDC4IDA §8 / #1513・#1651)
Discovery エンドポイント(/.well-known/openid-configuration)が OIDC4IDA §8 の身元確認メタデータを広告するようになった。RP はこれを読んで、テナントが対応する trust framework・evidence 種別・検証済みクレームを判別できる。
| フィールド | 内容 |
|---|---|
verified_claims_supported | 身元確認済みクレームに対応するか(boolean) |
trust_frameworks_supported | 対応する信頼フレームワーク(例: eidas) |
evidence_supported | 対応する証拠タイプ(例: document / electronic_record) |
documents_supported / documents_methods_supported | 対応する本人確認書類・確認方式 |
electronic_records_supported | 対応する電子記録 |
claims_in_verified_claims_supported | claims に入れられる検証済みクレーム名 |
あわせて #1651 で
evidence/trust_frameworksの supported 値を OIDC4IDA 1.0 の正規値へ正規化した。RP 側で supported 値を固定列挙している場合は追従が必要。広告される値はテナントの verified_claims 設定に追従する(コード側の固定リストではない)。
4. 身元確認申込みステータスのライフサイクル整理(#1617)
verified_claims はテナント設定の result.verified_claims_mapping_rules に基づき、身元確認申込みが 承認(APPROVED)に遷移したときにユーザーへ書き込まれる(実装: IdentityVerificationUserUpdater)。したがって申込みステータスの遷移が正しいことが、verified_claims を「いつ・正しく付与するか」の前提になる。
v0.11.0 ではステータス遷移評価をステートレス評価から状態機械へ整理した(Phase 1)。従来は「現在のステータス」を入力に取らず、条件にマッチ しないと経路(process / callback)ごとに異なる固定値へ fallbackしていたため、後退遷移や hard error による意図しない遷移が起きていた。
ステータス遷移図
Phase 1 で保証されること
- 前進のみ(後退禁止): running 4相(
REQUESTED → APPLYING → APPLIED → EXAMINATION_PROCESSING)は前進のみ。callback で進んだ後に process が no-match でも、固定 fallback(APPLYING)へ巻き戻らない。 - 終端は吸収:
APPROVED/REJECTED/EXPIRED/CANCELLEDに入ったら、以降の process / callback 評価では遷移しない。 - 失敗試行は遷移しない: その試行が success でない場合(pre-hook 検証エラー・追加パラメータ解決エラー・外部 API 実行エラー: HTTP 4xx/5xx・timeout・接続失敗)は
failure_countのみ記録し、ステータスは据え置く。失敗試行でロック・リトライ条件(#1608)は従来どおり機能する。 - 終端イベントの冪等性: 終端(
APPROVED/REJECTED/CANCELLED)への遷移に伴う副作用(ライフサイクルイベント発火・検証結果 register・user の verified_claims 更新)は、「今ステップで新規に終端へ遷移した」ときのみ 1 回発火する。終端済み申込みへ成功する process / callback を再投入しても二重に発火しない(handleTerminalTransition/ callback が遷移前ステータスで判定)。
設計(一箇所への集約)
ステータス決定ロジックは IdentityVerificationApplicationStatusEvaluator に集約した。evaluateInitial(初回申込み)/ evaluateOnProcess(hard error スキップ込み)/ evaluateOnCallback が「候補算出 → 現ステータスとの reconcile(終端吸収・後退禁止)」までを担い、申込み集約(IdentityVerificationApplication)は試行回数の記録に専念する。ユニットテスト: IdentityVerificationApplicationStatusReconcileTest。
ライフサイクルイベント(*_approved / *_rejected / *_cancelled)と検証結果 register・user 更新は、handleTerminalTransition(process)/ callback 経路の終端ブロックで行うが、遷移前ステータスを見て「新規の終端遷移」のときだけ実行するようガードした。
申込みデータとセキュリティイベントの関係(変更前後)
ステータス遷移の整理(前進のみ・終端吸収・失敗試行は非遷移)と終端イベントの遷移ガードにより、申込みデータの状態とライフサイクルイベントの発火が 1 対 1 で対応するようになった。
| シナリオ | 変更前(申込みデータ / イベント) | 変更後(申込みデータ / イベント) |
|---|---|---|
| 失敗試行(検証 / pre-hook / 実行エラー) | status → APPLYING へ移動(fallback)/ failure_count++ / {type}_{process}_failure | status 据え置き / failure_count++ / {type}_{process}_failure |
進行済み申込みへの no-match 成功(例: APPLIED 後に条件不一致の process) | status → APPLYING へ後退 / {type}_{process}_success | status 据え置き(APPLIED) / {type}_{process}_success |
正当な終端遷移(例: APPLIED → APPROVED) | status → APPROVED / *_approved 1 回 + 検証結果 register + user 更新 | (同じ)status → APPROVED / *_approved 1 回 + result register + user 更新 |
| 終端済み申込みへの成功再投入(process / callback) | no-match なら status が APPROVED → APPLYING へ巻き戻り(承認消失)、再承認なら *_approved 二重発火 + 検証結果 二重 register + user 冗長更新 | status は APPROVED 維持(吸収) / 遷移ガードで終端イベント・result・user 更新は再発火しない |
変更後のイベント発火ルール:
*_failure:失敗試行ごと(ステータスは動かさない)*_success:成功した process / callback ごと(ステータスが進む / 据え置きに関わらず)- 終端イベントは 到達した終端 1 種のみ(
*_approved/*_rejected/*_cancelledは排他)で、「今ステップで新規に終端へ遷移した」ときのみ 1 回発火する。- 検証結果 register・user の verified_claims 更新は
*_approved固有の副作用。*_rejected/*_cancelledはイベント発火のみで、結果登録・user 更新は伴わない。 - 例: cancel パターン(
... → APPLIED → cancel)では*_cancelledのみ発火し、*_approvedは発火しない(verified_claims 付与・結果 register も起きない)。rejectも同様に*_rejectedのみ。
- 検証結果 register・user の verified_claims 更新は
スコープ外(Phase 2 / #1617): no-match 時の fallback 廃止(=完全な「現状維持」)、transition config への running 系ターゲット(
applying/examination_processing)開放、evaluator から fallback を取り除く構造変更は本リリースでは未対応。既存テナント設定の移行を伴うため別途対応する。