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

Authentication Policy設定ガイド

このドキュメントの目的​

認証ポリシー(Authentication Policy)の設定方法を理解します。

所要時間​

⏱️ 約25分


Authentication Policyとは​

認証ポリシーはフロー別の認証要件を定義します。

設定内容:

  • 利用可能な認証方式
  • ACR(Authentication Context Class Reference)マッピング
  • 成功条件・失敗条件・ロック条件

設定ファイル構造​

authentication-policy/oauth.json​

{
"id": "f0864ea0-c4a0-470f-af92-22f995c80b3a",
"flow": "oauth",
"enabled": true,
"policies": [
{
"description": "default",
"priority": 1,
"conditions": {},
"available_methods": [
"password",
"email",
"fido-uaf"
],
"acr_mapping_rules": {
"urn:mace:incommon:iap:gold": ["fido-uaf", "fido2"],
"urn:mace:incommon:iap:silver": ["email", "sms"],
"urn:mace:incommon:iap:bronze": ["password"]
},
"success_conditions": {
"any_of": [
[
{
"path": "$.password-authentication.success_count",
"type": "integer",
"operation": "gte",
"value": 1
}
]
]
},
"failure_conditions": {
"any_of": []
},
"lock_conditions": {
"any_of": []
}
}
]
}

主要なフィールド​

ポリシー基本情報​

フィールド必須説明例
id✅ポリシーID(UUID)f0864ea0-...
flow✅対象フローoauth / ciba
enabled✅有効/無効true / false
policies✅ポリシーリスト配列

Policyオブジェクト​

フィールド必須説明
description❌ポリシー説明
priority✅優先度(高い値が優先)
conditions❌適用条件
available_methods✅UIに表示する認証方式(UIヒント)
acr_mapping_rules❌ACRマッピング
step_definitions❌多段階認証のステップ定義
success_conditions✅成功条件
failure_conditions❌失敗条件
lock_conditions❌ロック条件
auth_session_binding_required❌セッションバインディング(デフォルト: true)
custom_params_trusted_sources❌条件式から読めるカスタムパラメータの出どころ(デフォルト: ["pushed", "request_object"])。$.request.* を参照

Available Methods​

UIに表示する認証方式を指定します。この設定はUIヒントとして機能し、フロントエンドが認証画面で表示する認証方式を決定するために使用されます。

{
"available_methods": [
"password",
"email",
"fido-uaf",
"fido2"
]
}

重要:

  • この設定はバックエンドでの認証方式の制限には使用されません
  • 認証の成功条件は success_conditions で制御してください
  • Authentication Configuration で登録済みの認証方式のみ指定可能

ACR Mapping Rules​

ACR値と認証方式のマッピング:

{
"acr_mapping_rules": {
"urn:mace:incommon:iap:gold": ["fido-uaf", "fido2"],
"urn:mace:incommon:iap:silver": ["email", "sms"],
"urn:mace:incommon:iap:bronze": ["password"]
}
}

動作:

  • クライアントがacr_values=urn:mace:incommon:iap:goldを要求 → FIDO-UAFまたはWebAuthn認証が必要

Success Conditions​

認証成功の条件をJSONPathで定義:

{
"success_conditions": {
"any_of": [
[
{
"path": "$.password-authentication.success_count",
"type": "integer",
"operation": "gte",
"value": 1
}
],
[
{
"path": "$.email-authentication.success_count",
"type": "integer",
"operation": "gte",
"value": 1
},
{
"path": "$.fido-uaf-authentication.success_count",
"type": "integer",
"operation": "gte",
"value": 1
}
]
]
}
}

意味:

  • パスワード認証成功 OR(Email認証成功 AND FIDO-UAF認証成功)

サポートされる演算子​

演算子説明例
eq / ne等しい / 等しくないstatus == "REGISTERED"
gt / gteより大きい / 以上success_count >= 1
lt / lteより小さい / 以下failure_count <= 3
in / ninリストに含まれる / 含まれないstatus in ["REGISTERED","IDENTITY_VERIFIED"]
contains配列・文字列が値を含むroles contains "admin"
exists / missing値が存在する / しないemail_verified exists
regex正規表現マッチ—

value の代わりに value_path を書くと、右辺もコンテキストの path から読みます(eq / ne のみ)。 どちらかの値が無いとき、eq は false、ne は true になります(value の eq は両方 null で true になるのと違います)。 value と value_path の両方を書いた条件と、eq / ne 以外で value_path を使った条件は、管理 API が 400 を返します。

{ "path": "$.request.custom_params.member_no", "operation": "eq",
"value_path": "$.user.custom_properties.member_no" }

参照可能なコンテキスト​

条件の path は次の名前空間を参照できます(success_conditions / failure_conditions / lock_conditions / device_registration_conditions 共通)。

名前空間内容例
$.<interaction-type>.*各認証方式のインタラクション結果$.password-authentication.success_count
$.<interaction-type>.interactions.<interaction>.*interaction ごとの内訳(external-api-authentication と attribute-verification のみ)$.external-api-authentication.interactions.risk-check.success_count
$.user.*認証対象ユーザーの属性$.user.status, $.user.roles
$.request.custom_params.*認可リクエストのカスタムパラメータ(信頼する出どころのものだけ)$.request.custom_params.member_no

interactions.*(interaction ごとの内訳)​

external-api-authentication は1つの設定に複数の interaction を持てますが、それらはすべて同じエンドポイントパスに届くため、$.external-api-authentication.success_count は全 interaction の合計です。

そのため合計だけで条件を書くと、意図しない形で成立します。

// ❌ 3つの interaction を通したいが、1つを3回呼んでも成立する
{ "path": "$.external-api-authentication.success_count", "operation": "gte", "value": 3 }

interaction ごとの内訳を使えば、それぞれを名指しで要求できます。

// ✅ 3つの interaction がそれぞれ1回以上成功したことを要求する
"success_conditions": {
"any_of": [[
{ "path": "$.external-api-authentication.interactions.step-a.success_count",
"type": "integer", "operation": "gte", "value": 1 },
{ "path": "$.external-api-authentication.interactions.step-b.success_count",
"type": "integer", "operation": "gte", "value": 1 },
{ "path": "$.external-api-authentication.interactions.step-c.success_count",
"type": "integer", "operation": "gte", "value": 1 }
]]
}

failure_count / call_count も同じ形で参照でき、interaction ごとに試行回数の上限を変えられます。

path内容
$.external-api-authentication.success_count全 interaction の合計(従来どおり)
$.external-api-authentication.interactions.<interaction>.success_countその interaction だけの成功回数
$.external-api-authentication.interactions.<interaction>.failure_countその interaction だけの失敗回数
$.external-api-authentication.interactions.<interaction>.call_countその interaction の呼び出し回数
未実行の interaction は値がありません

一度も呼ばれていない interaction はキー自体が存在せず、path が解決しません。解決しない path は null として扱われ、gte などの数値比較は false になります(#1646)。「必須の interaction が実行されていない」は条件を満たさない側に倒れます。

この内訳を持つのは external-api-authentication だけです

他の認証方式は「1つの interactor = 1つの認証要素」で、type そのものが数えたい対象と一致するため、内訳は作られません(interactions キーが出力されません)。

$.user.*(ユーザー属性)​

認証トランザクションで識別済みのユーザー属性を参照できます(1st factor 完了後に有効)。

path型説明
$.user.substringユーザー識別子
$.user.statusstringステータス(REGISTERED / IDENTITY_VERIFIED / LOCKED 等。複数許可は in で列挙)
$.user.email_verifiedbooleanメール検証済みか
$.user.phone_number_verifiedboolean電話番号検証済みか
$.user.has_passwordbooleanパスワード設定済みか
$.user.provider_idstringプロバイダID
$.user.rolesstring[]ロール名の配列(contains で判定)
$.user.permissionsstring[]パーミッションの配列(contains で判定)
$.user.custom_properties.*anyテナント定義のカスタム属性

セキュリティ: $.user.* は allowリスト方式で上記のみ参照可能です。hashed_password / credentials / verified_claims などの機微情報は意図的に除外しています(条件評価は値の有無が成否として観測できるため、機微情報を参照可能にすると値抽出のオラクルになりうる)。この投影はポリシー評価専用で、外部APIリクエストには使用されません。

設定例: 登録済みユーザーのみ成功とみなす

{
"success_conditions": {
"any_of": [
[
{ "path": "$.user.status", "operation": "in", "value": ["REGISTERED", "IDENTITY_VERIFIED"] },
{ "path": "$.password-authentication.success_count", "type": "integer", "operation": "gte", "value": 1 }
]
]
}
}

未登録(INITIALIZED)ユーザーはパスワードが通っても成功になりません。複数ステータスを許可する場合は in で列挙します(eq を複数並べるとステータスは同時に1値しか取らないため AND が常に false になります)。ロール/パーミッションは AND グループ内の必須条件として参照できます(例: { "path": "$.user.roles", "operation": "contains", "value": "admin" })。

$.user.* の評価タイミング​

$.user.* はトランザクションにユーザーが bind された後でないと空になります。bind されるタイミングは認証フローの段階で決まります。

段階$.user.*補足
1st factor の challenge空(参照不可)ユーザー未確定。AuthenticationTransaction#updateWithUser が challenge 段での bind をスキップする
verify(認証成功)以降参照可能新規ユーザーは INITIALIZED、既存ユーザーは REGISTERED 等
  • 新規登録フローの同一トランザクションでは $.user.status は INITIALIZED です(REGISTERED への遷移は authorize 成立時で、success_conditions の評価はそれより前に走るため)。「新規 = INITIALIZED / 既存 = REGISTERED」で分岐できます。
  • challenge 段や user 未解決の段で $.user.* を参照する条件は**常に空 = 不成立(fail-closed)**になります。path の typo も同様に静かに不成立になるため、参照キーは上表の allowリストと突き合わせて確認してください(登録時の自動検証は #1664 で検討中)。

$.request.*(認可リクエスト)​

認可リクエストのカスタムパラメータ(OAuth / OIDC の既知パラメータ以外)を $.request.custom_params.<名前> で参照できます。RP が渡した値(例:会員番号)と、ログインした利用者の属性を value_path で突き合わせる用途です。

見えるのは、ポリシーの custom_params_trusted_sources に含まれる出どころの値だけです。それ以外は値が無いものとして扱います。

出どころ値既定で信頼
pushedクライアント認証をした PAR の本文(本文のリクエストオブジェクトを含む)✅
request_object署名されたリクエストオブジェクトのクレーム✅
queryクエリの値。署名の無いリクエストオブジェクトの値と、クライアント認証の無い(公開クライアントの)PAR の値もここに入る。公開クライアントの PAR は、本文のリクエストオブジェクトが署名されていてもここに入る❌

query の値は利用者が書き換えられます。照合に使うと、利用者が自分の値に書き換えるだけで通るため、既定では信頼しません。

照合の目的によって、必要な経路が変わります。

目的例経路
取り違えを防ぐ(利用者に悪意が無い前提)家族の共用端末で、別の人のセッションのまま進むのを止めるクエリでよい。custom_params_trusted_sources に query を足す
本人であることを保証する(利用者が攻撃者になりうる前提)名義人だけに許す再認証、なりすまし対策PAR か署名されたリクエストオブジェクト(既定のまま)

クエリを信頼するのは、それで足りるクライアントやスコープのポリシーだけにしてください(conditions で絞る)。どちらの場合も、RP は返ってきた ID Token の sub が想定した会員かを確かめます。

出どころは認可エンドポイントで決め、認証トランザクションに保存します。リクエストオブジェクトとクエリに同じキーがあるときはリクエストオブジェクトの値を使います(FAPI 1.0 Advanced ではリクエストオブジェクトの値だけ)。

設定例: RP が渡した会員番号がログインした利用者のものか確かめる

{
"custom_params_trusted_sources": ["pushed", "request_object"],
"success_conditions": {
"any_of": [[
{ "path": "$.password-authentication.success_count", "type": "integer", "operation": "gte", "value": 1 },
{ "path": "$.request.custom_params.member_no", "type": "string", "operation": "eq",
"value_path": "$.user.custom_properties.member_no" }
]]
}
}
このポリシーでは SSO しません

照合は「その認可リクエストでの確認」なので、セッションでは代わりになりません。次のどれかを含むポリシーに当てはまる認可リクエストは、SSO(セッションの再利用)をせず、毎回サインインからやり直します。

  • 属性照合のステップ(step_definitions の attribute-verification)
  • $.request.* を参照する条件(success_conditions / failure_conditions / lock_conditions)
  • 属性照合の結果($.attribute-verification.*)を参照する条件
経路動き
view-datasession_enabled が false。画面は最初からサインインを出す
authorize-with-session400(authentication policy verifies each request; sign in again)
prompt=nonelogin_required

SSO を効かせたいクライアントには、conditions(client_ids / scopes / acr_values)で照合の無いポリシーを当ててください。

型は値そのもので決まります。カスタムパラメータは文字列なので、数値で保存したカスタム属性とは一致しません。


Step Definitions(多段階認証)​

目的: 認証ステップの実行順序とユーザー識別制御を定義します。

step_definitionsとsuccess_conditionsの違い​

項目step_definitionssuccess_conditions
目的認証の実行順序とユーザー識別認証の成功判定
制御内容どの順番で認証を実行するかどの認証が成功すれば完了か
使用シーンEmail → SMS のような順序制御パスワード OR 生体認証 のような条件

フィールド一覧​

フィールド型必須説明例
methodstring✅認証方式"email", "sms", "password"
interactionstring❌method 内の特定の interaction に限定する(後述)"identify", "verify"
orderinteger✅実行順序(小さい値が先)1, 2, 3
requires_userboolean✅ユーザーが事前に識別されている必要があるかfalse(1st factor)/ true(2nd factor)
allow_registrationboolean❌このステップでユーザー登録を許可するかtrue / false
user_identity_sourcestring❌ユーザー識別に使用する属性"email", "phone_number", "username"

設定例: Email → SMS 多段階認証​

{
"step_definitions": [
{
"method": "email",
"order": 1,
"requires_user": false,
"allow_registration": true,
"user_identity_source": "email"
},
{
"method": "sms",
"order": 2,
"requires_user": true,
"allow_registration": false,
"user_identity_source": "phone_number"
}
]
}

動作:

  1. ステップ1(Email認証):

    • requires_user: false → ユーザー未特定でもOK
    • allow_registration: true → 新規ユーザー登録可能
    • メールアドレスでユーザーを識別
  2. ステップ2(SMS認証):

    • requires_user: true → ステップ1でユーザーが特定済みである必要
    • allow_registration: false → 登録不可(既存ユーザーのみ)
    • 電話番号で検証

1st Factor と 2nd Factor​

1st Factor (requires_user: false):

  • ユーザー識別フェーズ
  • ユーザーが未特定でも実行可能
  • 新規ユーザー登録が可能(allow_registration: true)

2nd Factor (requires_user: true):

  • 認証検証フェーズ
  • ユーザーが既に特定されている必要あり
  • ユーザーを変更できない
  • allow_registration: true のとき、メールアドレス・電話番号が未登録のユーザーには、リクエストの値を登録する。ユーザーに書き込むので、ユーザーが認証済みである必要がある。認証済みとは、同じトランザクションで認証が成功している、CIBA のリクエスト、または /me の API(アクセストークンのユーザー)のどれか。login_hint でユーザーを指定しただけでは登録せず、チャレンジが unauthorized で失敗する。外部 API 認証とナンバーマッチングの成功も認証として数える。device_registration_conditions はここには効かない

interaction 単位の定義​

external-api-authentication は複数の interaction を1つの設定に持ちますが、どれを実行しても method は "external-api" です。そのため method だけを書いた定義は、設定内の全 interaction に適用されます。

interaction ごとに requires_user を変えたい場合は interaction を指定します。

{
"step_definitions": [
{ "method": "external-api", "interaction": "identify", "order": 1, "requires_user": false },
{ "method": "external-api", "interaction": "verify", "order": 2, "requires_user": true }
]
}

interaction の値は、認証設定の interactions のキー(=リクエストボディの interaction に指定する値)です。

解決順:

優先条件
1method と interaction の両方が一致する定義
2method が一致し、interaction を持たない定義
3どちらも無い場合は定義なし(制約なし)

2 があるため、method 単位の定義を既定、interaction 単位の定義をその上書きとして書けます。宣言順には依存しません。

{
"step_definitions": [
{ "method": "external-api", "order": 2, "requires_user": true },
{ "method": "external-api", "interaction": "identify", "order": 1, "requires_user": false }
]
}

上記では identify だけが 1st factor になり、それ以外の interaction はすべて 2nd factor として扱われます。既定を先に書いても後に書いても結果は変わりません。

method 単位の既定を必ず1つ書いてください

interaction 単位の定義だけを並べると、そこに書かれていない interaction は「定義なし」になり、requires_user のチェックが行われません(step_definitions を設定していない場合と同じ挙動)。

interaction を1つ追加して step 定義に書き忘れると、2nd factor の同一性検証が静かに無効化されます。上の例のように method 単位の既定を1つ置き、例外だけを interaction で上書きしてください。

external-api-authentication 以外の認証方式は1 method に interaction が1つなので、interaction を書く必要はありません。

使用シーン​

  • 段階的なユーザー登録: Email認証 → SMS認証で段階的に情報を収集
  • ステップアップ認証: 通常ログイン後、重要な操作前にSMS認証を要求
  • 複合認証: 複数の認証方式を組み合わせてセキュリティを強化
  • 1設定内での 1st / 2nd factor 混在: external-api-authentication で本人特定と追加確認を分ける(interaction 単位の定義)

Auth Session Binding(セッションバインディング)​

目的: 認可フローハイジャック攻撃を防止するための設定です。

概要​

【認可フローハイジャック攻撃】

1. 攻撃者が認可リクエストを開始 → id=abc123, AUTH_SESSION=xyz789 を取得
2. 攻撃者がURL (id=abc123) を被害者に送信
3. 被害者がそのURLにアクセスして認証しようとする
4. 被害者のブラウザにはAUTH_SESSION Cookieがない
5. 【対策あり】認証時にvalidateAuthSession()が失敗 → 被害者が認証できない

設定​

フィールド型デフォルト説明
auth_session_binding_requiredbooleantrueAUTH_SESSION Cookie検証の有効/無効

設定例​

標準(推奨):

{
"policies": [{
"auth_session_binding_required": true,
"available_methods": ["password"],
"success_conditions": { ... }
}]
}

→ AUTH_SESSION Cookieの検証を実施。認可フローハイジャック攻撃を防止。

無効化(特殊なユースケース向け):

{
"policies": [{
"auth_session_binding_required": false,
"available_methods": ["password"],
"success_conditions": { ... }
}]
}

→ AUTH_SESSION Cookieの検証をスキップ。

検証タイミング​

AUTH_SESSION Cookieは以下のエンドポイントで検証されます:

エンドポイント説明
POST /password-authenticationパスワード認証
POST /totp-authenticationTOTP認証
POST /authorize認可(同意)
POST /authorize-with-sessionSSO認可

例外​

以下のフローでは、AUTH_SESSION検証が自動的にスキップされます:

  • CIBA(Client Initiated Backchannel Authentication): ブラウザを経由しない認証フロー
  • その他のnon-browserフロー

関連ドキュメント​


2要素認証(2FA)の設定例​

{
"available_methods": ["password", "email"],
"success_conditions": {
"any_of": [
[
{
"path": "$.password-authentication.success_count",
"type": "integer",
"operation": "gte",
"value": 1
},
{
"path": "$.email-authentication.success_count",
"type": "integer",
"operation": "gte",
"value": 1
}
]
]
}
}

動作: パスワードANDメールOTPの両方成功で認証完了


Management APIで登録​

API エンドポイント​

組織レベルAPI:

POST /v1/management/organizations/{organization-id}/tenants/{tenant-id}/authentication-policies

ポリシー登録​

POST /v1/management/organizations/{organization-id}/tenants/{tenant-id}/authentication-policies
Content-Type: application/json

{
"id": "uuid",
"flow": "oauth",
"enabled": true,
"policies": [
{
"priority": 1,
"available_methods": ["password"],
"success_conditions": {
"any_of": [
[
{"path": "$.password-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}
]
]
}
}
]
}

よくある設定ミス​

ミス1: 未登録の認証方式を指定​

エラー:

{
"error": "invalid_request",
"error_description": "authentication method 'fido-uaf' not found"
}

原因: available_methodsに指定した認証方式が未登録

解決策: Authentication Configurationで先に登録

ミス2: 成功条件の論理エラー​

問題: すべての認証方式が成功しないと認証完了にならない

原因:

{
"success_conditions": {
"any_of": [
[
{"path": "$.password-authentication.success_count", "type": "integer", "operation": "gte", "value": 1},
{"path": "$.email-authentication.success_count", "type": "integer", "operation": "gte", "value": 1},
{"path": "$.fido-uaf-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}
]
]
}
}

解決策: OR条件にする

{
"success_conditions": {
"any_of": [
[{"path": "$.password-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}],
[{"path": "$.email-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}]
]
}
}

次のステップ​

✅ Authentication Policy設定を理解した!

次に読むべきドキュメント​

  1. FIDO-UAF設定 - 生体認証設定
  2. Password設定 - パスワード認証設定

関連ドキュメント​


最終更新: 2025-12-06


📊 初学者向けドキュメント品質レビュー​

レビュー日: 2025-01-15 レビュー対象: 初学者(idp-server開発経験なし、Java/Spring Boot基礎知識あり)

✅ 良い点​

  1. 2FA設定例: 実用的な2要素認証の設定例が明確
  2. 演算子の説明: JSONPath演算子(gte/lte/eq/ne)を表で整理
  3. 論理条件の説明: AND/ORの組み合わせを具体例で説明
  4. エラー対処: よくある論理エラーと解決策が詳細
  5. ACRマッピング: ACR値と認証方式のマッピングが明確
  6. フィールド説明: 表形式で全フィールドを網羅

⚠️ 改善推奨事項​

  • Authentication Policyの概念説明(重要度: 高)

    • 「なぜAuthentication Policyが必要か」の説明不足
    • Tenant/Client/Authentication Policyの関係性
    • Policyがどのタイミングで評価されるか
  • JSONPath基礎の説明(重要度: 高)

    • JSONPath構文($.password-authentication.success_count)の読み方
    • どのようなデータ構造を参照しているか
    • 利用可能なパスの一覧
  • any_of論理構造の図解(重要度: 高)

    • ネストされた配列の意味が分かりにくい
    • any_of: [[A,B],[C]] = (A AND B) OR C の視覚化
  • 最小構成の例(重要度: 高)

    • 最もシンプルな単一認証方式の例
    • 段階的に複雑にする説明
  • 実践的なシナリオ(重要度: 中)

    • 「一般ユーザー: パスワードのみ」
    • 「管理者: パスワード + 2FA必須」
    • 「高セキュリティ: 生体認証必須」
  • priority の動作説明(重要度: 中)

    • 複数policyがある場合の選択ロジック
    • conditionsとの組み合わせ
  • デバッグ方法(重要度: 中)

    • 成功条件が満たされない場合の確認方法
    • 認証状態の確認方法

💡 追加推奨コンテンツ​

  1. 認証フロー全体図:

    認証開始 → Policy選択 → 認証方式提示 →
    認証実行 → 成功条件評価 → 認証完了/継続
  2. JSONPath参照データ構造:

    {
    "password-authentication": {
    "success_count": 1,
    "failure_count": 0
    },
    "email-authentication": {
    "success_count": 0,
    "failure_count": 0
    }
    }
  3. 条件組み合わせパターン集:

    • 単一認証
    • 2要素認証(2FA)
    • 多要素認証(MFA)
    • ステップアップ認証
  4. 失敗条件・ロック条件の例:

    • パスワード3回失敗でロック
    • 一定時間内の再試行制限
  5. トラブルシューティング拡充:

    • 認証が完了しない原因特定
    • 条件式のテスト方法

📈 総合評価​

  • 理解しやすさ: ⭐⭐⭐☆☆ (3/5) - JSONPath条件が初学者には難しい
  • 実用性: ⭐⭐⭐⭐☆ (4/5) - 2FA例など実用的
  • 完全性: ⭐⭐⭐⭐☆ (4/5) - 主要な設定を網羅
  • 初学者適合度: ⭐⭐⭐☆☆ (3/5) - 前提知識が多く、概念説明が不足

🎯 推奨される学習パス​

このドキュメントの位置づけ: 中級(認証方式設定後)

推奨順序:

  1. Tenant設定 - Tenant作成
  2. Client設定 - Client登録
  3. Password設定 - 認証方式登録
  4. このドキュメント - Authentication Policy設定
  5. Authentication Policy実装ガイド - 実装詳細

📝 具体的改善案(優先度順)​

1. Authentication Policyの概念説明(最優先)​

## Authentication Policyとは(詳細)

**Authentication Policy(認証ポリシー)**は、**どの認証方式を使って、どのような条件で認証を成功とするか**を定義する設定です。

### なぜ必要か

- 異なるセキュリティ要件への対応(一般ユーザー vs 管理者)
- 複数認証方式の組み合わせ(2FA, MFA)
- ACR(認証レベル)による動的な要件変更

### Policyが評価されるタイミング

\`\`\`
1. ユーザーが認証開始
2. → Tenant/Client情報取得
3. → Authentication Policy選択(flow, priority, conditions)
4. → 利用可能な認証方式を提示
5. → ユーザーが認証実行
6. → 成功条件評価
7. → ✅ 成功 or ❌ 継続/失敗
\`\`\`

### Tenant-Client-Policy-Authentication Methodの関係

\`\`\`
┌────────────────────────────────┐
│ Tenant │
│ │
│ ┌──────────────┐ │
│ │ Client │ │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────┐ │
│ │ Authentication Policy │ │
│ │ (OAuth Flow用) │ │
│ ├─────────────────────────┤ │
│ │ available_methods: │ │
│ │ - password │──┐│
│ │ - email │──┤│
│ │ - fido-uaf │──┤│
│ └─────────────────────────┘ │││
│ │││
│ ┌──────────────────────────┐ │││
│ │ Authentication Methods │ │││
│ ├──────────────────────────┤ │││
│ │ password config │◀┘││
│ │ email config │◀─┘│
│ │ fido-uaf config │◀──┘
│ └──────────────────────────┘ │
└────────────────────────────────┘
\`\`\`

2. JSONPath基礎の説明​

## JSONPath条件の仕組み

### 認証状態データ構造

認証実行時、以下のような状態データが内部で管理されます:

\`\`\`json
{
"password-authentication": {
"success_count": 1,
"failure_count": 0,
"last_attempt_at": "2025-01-15T10:00:00Z"
},
"email-authentication": {
"success_count": 0,
"failure_count": 0
},
"fido-uaf-authentication": {
"success_count": 0,
"failure_count": 0
}
}
\`\`\`

### JSONPath構文

\`\`\`
$.password-authentication.success_count
│ │ │
│ │ └─ フィールド名
│ └─ 認証インタラクション名
└─ ルート

結果: 1(パスワード認証の成功回数)
\`\`\`

### 利用可能なパス

| JSONPath | 説明 | 型 |
|----------|------|-----|
| \`$.{method}-authentication.success_count\` | 成功回数 | integer |
| \`$.{method}-authentication.failure_count\` | 失敗回数 | integer |

**{method}**: password, email, sms, webauthn, fido-uaf など

3. any_of論理構造の図解​

## any_of条件の論理構造

### 基本形式

\`\`\`json
{
"any_of": [
[条件A, 条件B], // ← グループ1(AND)
[条件C] // ← グループ2
]
}
\`\`\`

**意味**: (条件A AND 条件B) OR 条件C

### 視覚化

\`\`\`
┌─────────────────────────┐
│ any_of(いずれか満たす) │
├─────────────────────────┤
│ Group 1: │
│ ✓ 条件A AND │ ─┐
│ ✓ 条件B │ ─┤ OR
│ │ │
│ Group 2: │ │
│ ✓ 条件C │ ─┘
└─────────────────────────┘
\`\`\`

### 実例: 2FA設定

\`\`\`json
{
"success_conditions": {
"any_of": [
[
{"path": "$.password-authentication.success_count", "type": "integer", "operation": "gte", "value": 1},
{"path": "$.email-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}
]
]
}
}
\`\`\`

**読み方**:
- Group 1: パスワード成功 **AND** Email成功
- → 両方成功で認証完了(2FA)

### 実例: 複数認証方式の選択

\`\`\`json
{
"success_conditions": {
"any_of": [
[{"path": "$.password-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}],
[{"path": "$.fido-uaf-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}]
]
}
}
\`\`\`

**読み方**:
- Group 1: パスワード成功 **OR**
- Group 2: FIDO-UAF成功
- → どちらか一つ成功で認証完了

4. シナリオ別設定例​

## シナリオ別Authentication Policy設定

### シナリオ1: 単一認証(パスワードのみ)

**要件**: パスワード認証のみで完了

\`\`\`json
{
"flow": "oauth",
"policies": [{
"priority": 1,
"available_methods": ["password"],
"success_conditions": {
"any_of": [[
{"path": "$.password-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}
]]
}
}]
}
\`\`\`

### シナリオ2: 2要素認証(パスワード + OTP)

**要件**: パスワードとEmail OTP両方必須

\`\`\`json
{
"flow": "oauth",
"policies": [{
"priority": 1,
"available_methods": ["password", "email"],
"success_conditions": {
"any_of": [[
{"path": "$.password-authentication.success_count", "type": "integer", "operation": "gte", "value": 1},
{"path": "$.email-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}
]]
}
}]
}
\`\`\`

### シナリオ3: ステップアップ認証

**要件**: 通常はパスワード、ACR要求時は生体認証必須

\`\`\`json
{
"flow": "oauth",
"policies": [{
"priority": 1,
"available_methods": ["password", "fido-uaf"],
"acr_mapping_rules": {
"urn:mace:incommon:iap:gold": ["fido-uaf"],
"urn:mace:incommon:iap:bronze": ["password"]
},
"success_conditions": {
"any_of": [
[{"path": "$.password-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}],
[{"path": "$.fido-uaf-authentication.success_count", "type": "integer", "operation": "gte", "value": 1}]
]
}
}]
}
\`\`\`

**動作**:
- 通常リクエスト → パスワード認証
- \`acr_values=urn:mace:incommon:iap:gold\` → FIDO-UAF必須