Chuyển đến nội dung chính

レッスン 10: 認証フロー - 認証フローのカスタマイズ

Keycloakの認証フロー、ブラウザフロー、直接付与フロー、登録フロー、認証情報のリセットフロー、最初のブローカーログインフローを理解します。カスタム フローの作成、実行とサブフロー、条件付きオーセンティケーター (条件 - 実行されるサブフロー、条件 - クライアント スコープ)、ステップアップ認証、ACR から認証レベル (LoA) へのマッピング、およびセッション制限を追加します。

🔒 DevSecOps — レッスン 10 レッスン 10: 認証フロー - カスタマイズ 認証フロー

基本から上級までの Keycloak

パート 3: 認証、MFA、および ID ブローカリング

xdev.asia

1. 認証フロー — 概要

Keycloakでの認証フローは次のとおりです。一連の認証ステップこれは、ユーザーがログイン、登録、またはその他のセキュリティ アクションを実行するときに実行する必要があります。各フローには次のものが含まれます処刑(認証者) は順序付けされており、入れ子にすることができますサブフロー.

フローを表示および管理するには、次のサイトにアクセスしてください。管理コンソール → 認証 → フロー.

1.1 組み込みの認証フロー

Keycloak はデフォルトのフローを提供します。

流れ説明するそれはいつトリガーされますか?
ブラウザの流れブラウザからのログインの流れユーザーが初めてアプリケーションにアクセスするか、セッションが期限切れになる
直接助成金の流れユーザー名/パスワード (リソース所有者パスワード) を使用した直接認証Grant_type=password を使用した API 呼び出し
登録の流れ新規アカウント登録の流れユーザーがログインページで「登録」をクリックします
認証情報のリセットフローパスワードリセットの流れユーザーが「パスワードを忘れた場合」をクリックします
最初のブローカーのログインフローフローは、アイデンティティ プロバイダーを介した最初のログインを処理します。ユーザーが初めてソーシャル ログイン経由でログインする
Docker認証フローDockerレジストリの認証Docker クライアントのイメージのプル/プッシュ
HTTPチャレンジの流れHTTPヘッダーによる認証非ブラウザクライアント (Kerberos、X.509)

1.2 フローの種類

各フローには、次のタイプの要素を含めることができます。

タイプ説明する
認証者特定の認証ステップ (例: ユーザー名、パスワード フォーム)
サブフロー子フローには複数の認証子が含まれており、複雑なロジックが可能です
形状ユーザーが情報 (ユーザー名、パスワード、OTP など) を入力するためのフォームを表示します。

2. ブラウザ フロー — 詳細

デフォルトのブラウザ フローは次の構造になっています。

Browser Flow
├── Cookie (Alternative)              → Kiểm tra SSO session cookie
├── Kerberos (Disabled)               → Xác thực Kerberos (tắt mặc định)
├── Identity Provider Redirector (Alternative) → Redirect đến IdP nếu có
└── Forms (Alternative)               → Sub-flow xử lý form login
    ├── Username Password Form (Required) → Nhập username + password
    └── Browser - Conditional OTP (Conditional) → Sub-flow OTP
        ├── Condition - User Configured (Required) → Kiểm tra user đã setup OTP
        └── OTP Form (Required)           → Nhập mã OTP

仕組み:

  1. クッキー: ユーザーがすでに有効なセッション Cookie を持っている場合 → すべてスキップし、ログインに成功します
  2. ケルベロス: デフォルトでは無効です — 有効にすると、Kerberos チケットが試行されます
  3. アイデンティティプロバイダリダイレクタ: あればkc_idp_hint→ その IdP にリダイレクトします
  4. フォーム:ログインフォームを表示
    • ユーザー名とパスワードが必要です
    • ユーザーが OTP を設定している場合 → OTP コードの入力が必要

2.1 実行要件

フロー内の各実行には 1 つの要件。要件動作を定義します。

要件説明するいつ使用するか
必須実行して成功することが不可欠ですユーザー名/パスワード、OTP の設定後
代替成功した代替案の 1 つで十分ですCookie またはフォーム — たった 1 パス
条件付きサブフローは条件が true の場合にのみ実行されます条件付き OTP — ユーザーが設定した場合にのみ OTP が必要です
無効完全に無視してくださいステップを削除せずに一時的に無効にする

重要なルール:

  • フロー内のすべての実行が代替→ただパスワード1個
  • 少なくとも 1 つあれば必須→ Required はすべて合格する必要があり、Alternative は無視されます
  • 条件付きサブフローでよく使用されます。最初のステップは条件チェッカーであり、次のステップは認証子です。

3. カスタム認証フローの作成

組み込みフローは直接編集できません。必要です重複。重複それからカスタマイズします。

3.1 複製と編集

  1. 入力認証 → フロー
  2. コピーするフローを選択します。たとえば、ブラウザ
  3. クリックアクション → 複製
  4. 新しい名前:私のカスタムブラウザフロー
  5. 新しいフローは、元のフローとすべて同じ実行で表示されます。

3.2 実行の追加

複製したら、実行を追加/削除/並べ替えることができます。

  1. カスタム フローで、「ステップを追加」
  2. リストから認証システムを選択します。
    • ユーザー名 パスワード フォーム— ユーザー名+パスワード入力フォーム
    • OTPフォーム— OTPコードを入力するフォーム
    • クッキー— セッション Cookie を確認する
    • アイデンティティプロバイダリダイレクタ— 外部 IdP へのリダイレクト
    • アクセスを拒否する— アクセスを拒否する
    • アクセスを許可する— アクセスを許可する
    • ユーザー名フォーム— ユーザー名のみを入力します (別のパスワード)
    • パスワードフォーム— パスワードのみを入力します
    • WebAuthn オーセンティケーター— セキュリティキーによる認証
    • WebAuthn パスワードレス認証システム— パスワードレス認証
  3. 適切な要件を設定します (必須、代替、条件付き、無効)

3.3 サブフローの追加

サブフローを使用すると、複数の実行をグループ化して、より複雑なロジックを作成できます。

My Custom Browser Flow
├── Cookie (Alternative)
├── Identity Provider Redirector (Alternative)
└── My Login Forms (Alternative)              ← Sub-flow
    ├── Username Password Form (Required)
    └── MFA Sub-flow (Conditional)            ← Sub-flow lồng nhau
        ├── Condition - User Configured (Required)
        ├── OTP Form (Alternative)            ← Cho chọn OTP...
        └── WebAuthn Authenticator (Alternative) ← ...hoặc Security Key

サブフローを追加する方法:

  1. クリック「サブフローを追加」
  2. たとえば、次のように名前を付けます。MFA サブフロー
  3. 要件を設定します。条件付き
  4. サブフローに実行を追加する

4. 条件付き認証子

条件付き認証子が許可される条件を確認するサブフローを実行する前に。条件が満たされない場合 → サブフロー全体がスキップされます。

4.1 利用可能な条件

状態説明する
条件 - ユーザー設定ユーザーは対応する認証情報 (OTP、WebAuthn...) を構成しました。
条件 - ユーザーの役割ユーザーには特定の役割があります
条件 - ユーザー属性ユーザーは必要な値を持つ特定の属性を持っています
条件 - クライアントの範囲リクエストには特定のスコープが含まれています (例:acr_values)
条件 - サブフローの実行前のサブフローは正常に実行されました

4.2 例: ロール別の条件付き OTP

ロールを持つユーザーのみの OTP リクエスト管理者。管理者:

My Custom Browser Flow
├── Cookie (Alternative)
└── Forms (Alternative)
    ├── Username Password Form (Required)
    └── Admin OTP Sub-flow (Conditional)
        ├── Condition - User Role (Required)    → Config: role = "admin"
        └── OTP Form (Required)

条件の構成 - ユーザーの役割:

  1. もっと条件 - ユーザーの役割サブフローへ
  2. 条件の横にある ⚙️ (設定) アイコンをクリックします。
  3. 入力:
    • エイリアス: 管理者の役割を確認する
    • ユーザーの役割: 管理者。管理者(またはレルム管理.管理ユーザークライアントの役割の場合)
    • 出力を否定します: オフ(ロールを持たないユーザーに適用する場合はオン)

4.3 条件 - クライアントの範囲

クライアントが特別なスコープを要求する場合は MFA を要求します。

# Authorization request yêu cầu MFA
GET /realms/myrealm/protocol/openid-connect/auth?
  client_id=my-app&
  scope=openid profile mfa-required&
  response_type=code&
  redirect_uri=https://myapp.example.com/callback
My Custom Browser Flow
├── Cookie (Alternative)
└── Forms (Alternative)
    ├── Username Password Form (Required)
    └── MFA When Requested (Conditional)
        ├── Condition - Client Scope (Required)  → Config: scope = "mfa-required"
        └── OTP Form (Required)

5. ステップアップ認証と認証レベル (LoA)

ステップアップ認証によりリクエストが許可されますより高いレベルの認証ユーザーに完全な再認証を強制することなく、機密性の高いアクションを実行できます。

5.1 ACR とスピーカーのマッピング

ACR (認証コンテキスト クラス リファレンス)ID トークン内のクレームは次のとおりです信憑性のレベルが行われました。 KeycloakはACR値をマップします認証レベル (LoA)— 整数。

ACR から LoA へのマッピングを構成します。

  1. 入力認証 → フロー
  2. 使用中のフローを開きます (例: ブラウザ フロー)
  3. 各サブフローには 1 つを割り当てることができますLoAレベル
My Step-up Browser Flow
├── Cookie (Alternative)                          → LoA: không set
└── Login Forms (Alternative)
    ├── Username Password Form (Required)         → LoA Level 1
    └── Step-up MFA (Conditional)
        ├── Condition - Level of Authentication (Required)
        └── OTP Sub-flow (Conditional)            → LoA Level 2
            ├── Condition - User Configured (Required)
            └── OTP Form (Required)

デフォルトの LoA マッピング (認証 → フロー → 歯車アイコン):

# Trong Realm Settings → General → ACR to LoA Mapping:
# Hoặc cấu hình trong flow
{
  "acr_to_loa_mapping": {
    "urn:keycloak:loa:1": 1,    // Password only
    "urn:keycloak:loa:2": 2,    // Password + OTP
    "urn:keycloak:loa:3": 3,    // Password + Security Key
    "gold": 2,                   // Custom ACR value
    "platinum": 3                // Custom ACR value
  }
}

5.2 ステップアップ認証の要求

クライアントは、次の方法で特定の LoA を要求します。acr_valuesまたは主張パラメータ:

# Sử dụng acr_values (voluntary — không bắt buộc)
GET /realms/myrealm/protocol/openid-connect/auth?
  client_id=my-app&
  scope=openid&
  acr_values=gold&
  response_type=code&
  redirect_uri=https://myapp.example.com/callback

# Sử dụng claims parameter (essential — bắt buộc LoA)
GET /realms/myrealm/protocol/openid-connect/auth?
  client_id=my-app&
  scope=openid&
  claims={"id_token":{"acr":{"essential":true,"values":["gold"]}}}&
  response_type=code&
  redirect_uri=https://myapp.example.com/callback

ID トークンの結果:

{
  "acr": "gold",
  "sub": "user-123",
  "iss": "https://keycloak.example.com/realms/myrealm",
  ...
}

5.3 アプリケーションで LoA を確認する

// Spring Security — kiểm tra ACR level
@GetMapping("/sensitive-action")
public ResponseEntity<?> sensitiveAction(
        @AuthenticationPrincipal OidcUser user) {
    
    String acr = user.getIdToken().getClaimAsString("acr");
    
    if (!"gold".equals(acr)) {
        // Redirect user để step-up authentication
        String stepUpUrl = keycloakBaseUrl + 
            "/realms/myrealm/protocol/openid-connect/auth" +
            "?client_id=my-app" +
            "&scope=openid" +
            "&acr_values=gold" + 
            "&prompt=login" +
            "&response_type=code" +
            "&redirect_uri=" + redirectUri;
        
        return ResponseEntity.status(302)
            .header("Location", stepUpUrl)
            .build();
    }
    
    return ResponseEntity.ok("Sensitive data here");
}

6. 直接的な助成金の流れ

ダイレクトグラントフロー処理許可タイプ=パスワード— ブラウザを経由しない直接認証:

Direct Grant Flow (mặc định)
├── Username Validation (Required)    → Kiểm tra username tồn tại
├── Password (Required)               → Verify password
└── Direct Grant - Conditional OTP (Conditional)
    ├── Condition - User Configured (Required)
    └── OTP (Required)
# Ví dụ: Direct Grant request
curl -X POST \
  https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=password' \
  -d 'client_id=my-backend' \
  -d 'client_secret=my-secret' \
  -d '[email protected]' \
  -d 'password=user-password' \
  -d 'totp=123456'    # Nếu user đã setup OTP

⚠️ 注記: 直接付与 (リソース所有者のパスワード認証情報) は実稼働環境では推奨されません。代わりに認証コード フロー + PKCE を使用する必要があります。

7. 登録の流れ

登録フローは、新しいアカウントの登録プロセスを制御します。

Registration Flow (mặc định)
└── Registration Form (Required)
    ├── Registration User Profile (Required)  → Nhập thông tin profile
    ├── Password Validation (Required)        → Nhập + confirm password
    └── Recaptcha (Disabled)                  → reCAPTCHA (tắt mặc định)

7.1 登録を有効にする

  1. 入力レルム設定 → ログイン
  2. オンにするユーザー登録:の上
  3. オプション: オンユーザー名としての電子メールユーザーがユーザー名として電子メールを使用できるようにする

7.2 カスタム登録の流れ

My Registration Flow
└── Registration Form (Required)
    ├── Registration User Profile (Required)
    ├── Password Validation (Required)
    ├── Recaptcha (Required)                → Bật reCAPTCHA
    └── Terms and Conditions (Required)     → Yêu cầu đồng ý điều khoản

reCAPTCHA を構成します。

  1. Google reCAPTCHA v3 にサインアップするには、https://www.google.com/recaptcha/admin
  2. フロー内で、その横にある ⚙️ をクリックします再キャプチャ
  3. 入力:
    • 再キャプチャサイトキー: あなたのサイトキー
    • 再キャプチャシークレット: あなたの秘密鍵
    • Recaptcha.net を使用する: オン (中国で必要な場合)

8. 認証情報のリセットフロー

フローはパスワード リセット プロセスを処理します。

Reset Credentials Flow (mặc định)
├── Choose User (Required)                → User nhập username/email
├── Send Reset Email (Required)           → Gửi email reset link
├── Reset Password (Required)             → Form nhập mật khẩu mới
└── Reset - Conditional OTP (Conditional) → OTP nếu đã cấu hình
    ├── Condition - User Configured (Required)
    └── Reset OTP (Required)

9. セッション制限

Keycloakを使用すると、ユーザーごとの同時セッション数を制限できます。

9.1 認証フローでのセッション制限の構成

もっとユーザーセッションの制限フローへの認証子:

My Custom Browser Flow
├── Cookie (Alternative)
└── Forms (Alternative)
    ├── Username Password Form (Required)
    ├── Browser - Conditional OTP (Conditional)
    │   ├── Condition - User Configured (Required)
    │   └── OTP Form (Required)
    └── User Session Limits (Required)

ユーザーセッション制限を構成します。

  1. 横にある⚙️をクリックしてくださいユーザーセッションの制限
  2. 構成:
    • 最大レルムセッション数: レルム内のセッションの最大合計数 (例:3)
    • 最大クライアントセッション数: 1 クライアントの最大セッション数 (例:1)
    • 制限に達したときの動作:
      • 新しいセッションを拒否する— 新規ログインを拒否する
      • 最も古いセッションを終了する— 最古のセッションロック
    • エラーメッセージ: 拒否された場合のカスタム メッセージ (例:「ログインセッションの制限に達しました」)

10. レルムとクライアントへのバインド フロー

10.1 レルムのバインドフロー

カスタム フローを作成したら、それをレルムのデフォルト フローとしてバインドします。

  1. 入力認証 → フロー
  2. タブをクリックします「バインディング」(または必要なアクション)
  3. 各バインディングのフローを選択します。
    • ブラウザの流れ: 私のカスタムブラウザフロー
    • 直接助成金の流れ: 直接助成
    • 登録の流れ: 私の登録の流れ
    • 認証情報のリセットフロー: 認証情報のリセット

10.2 特定のクライアントのバインド フロー

各クライアントのレルム フローをオーバーライドできます。

  1. 入力クライアント → クライアントを選択
  2. タブ"高度な"
  3. アイテム「認証フローのオーバーライド」:
    • ブラウザの流れ: レルムのデフォルト以外のフローを選択します
    • 直接助成金の流れ: 別のフローを選択します

11. クライアントポリシーによる動的なフロー選択

Keycloak 25+ からは次のことができますクライアントポリシークライアントのプロパティに基づいて認証フローを自動的に選択します。

11.1 フロー選択のためのクライアントポリシーの作成

  1. 入力レルム設定 → クライアントポリシー → ポリシー
  2. 新しいポリシーを作成します。安全なクライアント MFA ポリシー
  3. もっと状態:
    • タイプ:クライアントスコープ
    • 範囲:["MFA が必要"]
  4. もっとプロフィール(クライアントプロフィールより):
    • プロファイル エグゼキュータ: ブラウザ フローをオーバーライドします
// Client Policy — ví dụ export JSON
{
  "policies": [
    {
      "name": "Secure Clients MFA Policy",
      "description": "Enforce MFA for clients with mfa-required scope",
      "enabled": true,
      "conditions": [
        {
          "condition": "client-scopes",
          "configuration": {
            "scopes": ["mfa-required"],
            "type": "DEFAULT"
          }
        }
      ],
      "profiles": ["mfa-enforced-profile"]
    }
  ]
}

12. 認証フローのエクスポート/インポート

認証フローはレルムのエクスポートに含まれます。

# Export realm bao gồm flows
/opt/keycloak/bin/kc.sh export \
  --dir /opt/keycloak/data/export \
  --realm myrealm

# Trong file realm-export.json, flows nằm ở:
# "authenticationFlows": [...]
# "authenticationExecutions": [...]

Admin REST API を介した部分的なインポート:

# Lấy danh sách flows
curl -s -X GET \
  "https://keycloak.example.com/admin/realms/myrealm/authentication/flows" \
  -H "Authorization: Bearer $ADMIN_TOKEN" | jq '.[].alias'

# Export 1 flow cụ thể
FLOW_ID=$(curl -s -X GET \
  "https://keycloak.example.com/admin/realms/myrealm/authentication/flows" \
  -H "Authorization: Bearer $ADMIN_TOKEN" | \
  jq -r '.[] | select(.alias=="My Custom Browser Flow") | .id')

curl -s -X GET \
  "https://keycloak.example.com/admin/realms/myrealm/authentication/flows/$FLOW_ID/executions" \
  -H "Authorization: Bearer $ADMIN_TOKEN" | jq .

13. まとめ

コンセプト説明する
認証の流れ認証ステップのチェーン - サブフローを介してネスト可能
実行要件必須、代替、条件付き、無効
条件付き認証子サブフロー実行前に条件を確認する
ステップアップ認証機密性の高いアクションにはより高い LoA が必要
ACR から LoA へのマッピングACR値を数値レベルにマッピングする
セッション制限ユーザーごとの同時セッションを制限する
フローバインディングレルムレベルまたはクライアントごとのオーバーライドでのバインドフロー