KeycloakのAuthentication Flowは、Required/Alternative/Conditional/Disabledという実行要件の組み合わせで挙動が決まります。この評価規則を正確に押さえれば、条件付きMFAもブラウザフローのカスタマイズも怖くありません。現場で頻発する誤設定と併せて、一次情報をたどりながら整理します。
Keycloakを本番投入すると、多くのチームが最初につまずくのがAuthentication Flow(認証フロー)です。「MFAを管理者だけに強制したい」「特定のクライアントだけ多要素にしたい」といった要件を、GUIのRequirementラジオボタンだけで実現しようとして、意図しない挙動に悩む——という場面を私たちも何度も見てきました。本記事では、フローの評価規則を一次情報に沿って正確に押さえ、条件付きMFAとブラウザフローのカスタマイズ、そして頻発する誤設定を実務目線で整理します。バージョンは現行のQuarkus版(新しめのリリース)を前提としますが、細部は公式ドキュメントで必ずご確認ください。
01フローとサブフロー、実行(Execution)という3階層
Keycloakの認証フローは、上から順に評価される実行(Execution)の並びです。1つの実行は「Cookie検証」「ユーザー名+パスワードのForm」「OTP Form」といった認証処理(Authenticator)か、もしくはサブフロー(Sub-flow)を指します。サブフローはフローの入れ子であり、それ自体が1つの実行として親フローの中で評価されます。
ここで最初に理解すべきは、評価が上から下へ順次(top-to-bottom)進むという点です。各実行にはRequirement(実行の要件)が設定され、この要件の組み合わせで「どこまで実行するか」「成功と見なすか」が決まります。標準のブラウザフローは、トップレベルにCookie、Identity Provider Redirector、Kerberos、そしてFormsサブフローが並ぶ構造になっており、この設計を読み解くことが理解の近道です。
02Required / Alternative / Conditional / Disabled の意味
実行の要件は4種類です。それぞれの評価規則を正確に押さえます。
- Required(必須):同じフロー階層にあるすべてのRequired実行が成功しなければ、そのフローは失敗します。Required同士はANDの関係です。パスワードとOTPを両方ともRequiredにすれば、両方通らないとログインできません。
- Alternative(代替):同じ階層のAlternative実行のうちいずれか1つが成功すれば、そのフローは成功と見なされ、以降のAlternative実行は評価されません。標準ブラウザフローでCookie・Identity Provider Redirector・FormsサブフローがAlternativeなのはこのためで、Cookieが有効なら以降は走りません。なおKerberosは既定ではDisabledで、利用する場合に手動でAlternativeまたはRequiredへ変更します。
- Conditional(条件付き):サブフローにのみ設定できる特殊な要件です。サブフロー内に置いた「Condition系Authenticator(条件)」がすべてtrueならそのサブフローは実質Requiredとして振る舞い、条件がfalseなら実質Disabledとしてスキップされます。条件付きMFAの土台はこれです。
- Disabled(無効):その実行は評価されません。削除せず一時的に無効化したいときに使います。
混同しやすいのが「同じ階層にRequiredとAlternativeが混在するとどうなるか」です。公式の評価規則では、ある階層にRequiredが1つでも存在すると、その階層のAlternativeは事実上無視されます。Requiredが階層の成否を支配するためです。だからこそ、代替経路(パスワード or パスキー など)を作りたいときは、必ずAlternativeなサブフローで包む——という設計が定石になります。詳細はServer Administration Guideの認証フローの章に整理されています。
03条件付きMFA — Conditionalサブフローの組み立て方
「管理者ロールを持つユーザーだけOTPを必須にする」——エンタープライズで最も多い要件です。これは次の構造で実現します。
- Formsサブフローの中に、新しいサブフロー(例:「Conditional Admin OTP」)を追加し、要件をConditionalに設定する。
- そのサブフロー内に、Condition - User Roleを追加し、要件をRequired、対象ロールに
admin(realmロール)やclient.admin(clientロール)を指定する。 - 同じサブフロー内にOTP Formを追加し、要件をRequiredにする。
これで、adminロールを持つユーザーだけOTPが実質Requiredとなり、それ以外のユーザーはサブフロー全体がDisabled扱いでスキップされます。条件を複数入れると、Required条件はすべて満たす必要があります(AND)。この「複数条件AND」は、たとえば「adminロールを持ち、かつOTPを設定済み」という組み合わせに有効です。
04ステップアップ認証 — LoAとACRで強度を制御する
もう一段マニアックな要件がステップアップ認証です。通常はパスワードのみ、機密操作のときだけMFAを追加要求する——というものです。KeycloakはこれをLoA(Level of Authentication)という数値で扱います。
レルムの設定でACR(Authentication Context Class Reference)をLoAにマッピングします。ACRは任意の文字列、LoAは数値です(例:silver→1、gold→2)。Conditionalサブフローの中にCondition - Level of Authenticationを置き、目標LoAを指定すると、そのLoAにまだ達していないときだけ追加認証を走らせられます。クライアントはOIDCリクエストのacr_valuesやclaimsパラメータで必要なACRを要求し、発行されるトークンのacrクレームで達成レベルを確認できます。
新しめのバージョンでは、クライアント単位でMinimum ACR valueを強制する設定や、Condition - sub-flow executed(直前のサブフローが実行されたか)、Condition - client scopeといった条件も加わっています。利用可能な条件はバージョンで差があるため、実装前に稼働バージョンの管理画面と公式ドキュメントで必ず突き合わせてください。ステップアップ設計の全体像は姉妹記事ステップアップ認証でも掘り下げています。
05Authenticator SPIとmatchCondition — 標準条件で足りないとき
標準の条件で表現できないロジック(例:社内APIの返す属性で分岐、時間帯で分岐)が必要になったら、Authenticator SPIで独自のConditional Authenticatorを実装します。ポイントは2つのメソッドです。
- matchCondition():Conditionalサブフローは内包するすべての条件系実行の
matchConditionを呼び、すべてtrueなら「Requiredサブフロー」として振る舞います。独自条件はここに判定ロジックを書きます。 - configuredFor():そのユーザーがこのAuthenticatorを利用できる設定状態か(例:OTPを登録済みか)を判定します。Requiredな認証器でこれがfalseなら、必要に応じて設定用のRequired Actionへ誘導します。
実装の詳細と、SecretQuestionを題材にしたウォークスルーはServer Developer Guideに載っています。カスタム認証器の設計・運用の勘所は姉妹記事カスタムAuthenticator SPIにまとめています。SPIに手を出す前に、標準条件の組み合わせで要件を満たせないかを一度立ち止まって検討するのが、保守性の観点では堅実です。
06ブラウザフローのカスタマイズと本番反映(Bind)
カスタムフローは作っただけでは使われません。Binding(バインド)が必要です。手順の骨子は次の通りです。
- Authenticationメニューで標準「browser」フローをDuplicateし、名前を付ける(例:「browser-mfa」)。
- Formsサブフロー内に前述のConditionalサブフローを追加し、User Role条件やOTP Formを配置する。
- フロー一覧右上のアクションからBind flowを選び、Browser flowとして割り当てる。
フローには「Browser」「Direct grant」「Reset credentials」「Registration」など複数のバインディングポイントがあります。ブラウザログインだけ直して満足していると、パスワードグラント(Direct grant)経由やパスワードリセット経路にMFAが掛からず、ポリシーの穴になりがちです。加えて、クライアント単位でAuthentication flow overridesを設定して特定クライアントだけ別フローを使う運用もできます。フローの管理をコード化したい場合は、Admin REST APIやTerraformでの自動化を検討してください(姉妹記事Admin REST APIとIaC参照)。
07よくある誤設定と、その回避
私たちが現場で実際に踏んだ・見かけた落とし穴を挙げます。
- OTP FormをトップレベルでRequiredにしてしまう:全ユーザーにOTP登録が強制され、未登録者は初回ログインでOTP設定に飛ばされます。「一部ユーザーだけ」ならConditionalサブフローで包むのが正解です。
- 代替経路をAlternativeにせず、同階層にRequiredを混ぜる:同じ階層にRequiredがあるとAlternativeは無視され、意図した「or」になりません。or分岐は必ずAlternativeなサブフローで表現します。
- Bindを忘れる:フローを編集しても、バインドしていなければ実際のログインには反映されません。反映されない不具合の多くはこれです。
- Direct grant / Reset credentials を放置:ブラウザフローだけMFA化しても、他のバインディングポイントが素通りだと実効的な多要素になりません。
- Conditionalサブフローの中身がConditionしか無い:条件だけでは何も認証しません。条件が真のときに走るRequiredな認証器を必ず1つ以上入れます。
- User Role条件でclientロールとrealmロールを取り違える:記法が異なります。対象ロールの種別を確認してください。
acrクレームまで確認すると、後の障害切り分けが楽になります。監査面ではEvent Listener SPIでの認証イベント記録も併せて設計すると盤石です。—まとめ
Authentication Flowは、Required(AND)・Alternative(or、1つ成功で確定)・Conditional(条件で実質Required/Disabledを切替)・Disabledという4要件の組み合わせで挙動が決まります。条件付きMFAはConditionalサブフロー+Condition認証器、ステップアップはLoA/ACRマッピング——という定石を押さえ、Bindとバインディングポイントの取りこぼしに注意すれば、エンタープライズの要件はGUIの範囲でかなり表現できます。標準で足りなければAuthenticator SPIへ、という順序が保守性の面でも堅実です。Keycloakの実構築事例は導入事例もご覧ください。