KeycloakでCondition - User Roleを使った認証+認可フロー構築
はじめに
Keycloak の Condition - User Role を使って、ブラウザアクセスするアプリにロールベースの認可を追加する方法を紹介します。
Keycloak 側で認証・認可を完結させるため、アプリ側の実装が不要になり、アクセス制御が一元管理できます。
今回のゴール
- keycloakで認証認可を完結させられる仕組みを構築する
- 認証後に必ずロール検査を行い、該当ロールがないユーザーはログイン拒否
- SSOクッキー経由でもロールチェックがバイパスされない
前提
- Keycloak 23.0.7
フロー全体像
DefaultのBrowserを真似してAuthenticationでまとめ、追加でAuthorizationを入れていきます。
Authentication(Required)
├─ Cookie(Alternative)
├─ Kerberos(Disabled)
├─ Identity Provider Redirector(Alternative)
└─ login forms(Alternative)
└─ Username Password Form(Required)
└─ custom OTP(Conditional)
├─ Condition - user configured(Required)
└─ OTP Form(Required)
Authorization(Conditional)
├─ Condition - user role(Required, Negate=ON)
└─ Deny Access(Required)
-
Authentication サブフロー
認証の入り口。defaultのBrowserフローをサブフローにしています。Cookie(SSO)やIDプロバイダリダイレクトもここに含めます。 -
Authorizationサブフロー(Conditional)
指定ロールを持たない場合だけ true(Negate=ON)として Deny Access を実行。
実装手順
今回はstreamlit-usersというロールを持っているユーザーにだけ、streamlit1のclientにアクセス可能に設計します。
1. フローを作成
- 管理コンソール → Authentication → Flowsで「Create Flowを選択」
2. 認証系サブフローを作成
- 先頭に Authentication サブフロー(Requirement = Required)を作成
- 中に以下を追加(Browserフローを参考にしながらだとやりやすい)
- Cookie(Alternative)
- Kerberos(Disabled)
- Identity Provider Redirector(Alternative)
- login forms(Alternative)
- Username Password Form(Required)
3. OTPサブフローを追加(任意)
- custom OTP サブフローを追加(Requirement = Conditional)
- 中に以下を追加
- Condition - user configured(Required)
- OTP Form(Required)
これにより「OTP設定済みのユーザーのみOTP入力を要求」できます。
4. 認可サブフローを追加
- Authorization サブフローを追加(Requirement = Conditional)
- 中に以下を追加
- Condition - user role(Required)
- Role:
streamlit-user-role
(事前作成したRealm Role) - Negate output: ON(ロールを持たない時に true)
- Role:
- Deny Access(Required)
- Error message: 任意(例:
You do not have the required role.
)
- Error message: 任意(例:
- Condition - user role(Required)
参考:全体設定
5. フローを適用
- Clients → 設定したいclient → AdvancedタブのAuthentication Flow Overrides で作成したflowを指定
動作確認
roleを持つyu-minはアクセスできて、roleを持たないyu-min2はアクセスできません
なお、Cookieで許可するように設定されてあるので、テストの際はシークレットブラウザを起動するなど、cookieがない状態で実行しましょう。
yu-minのケース
yu-min2のケース
注意点
- Negate output の意味は以下の通りです。
- Negate=OFF → ロールを持つときに true
- Negate=ON → ロールを持たないときに true(今回はこちらを使用) - Conditional サブフローは、中の Condition 実行が true の場合だけ有効化され、内部のステップ(例:Deny Access)が実行されます。false の場合はサブフロー全体がスキップされます。
- この仕様を組み合わせて、Negate=ON にすると「ロールを持たない場合に true → Deny Access 実行」という流れが作れます。
- Authentificationステップを先頭に置くことで、SSOログインでも必ず後続の認可に到達できます。他のアプリケーションで認証されている場合でも効果を発揮できます。
まとめ
- 認証(Authentication)と認可(Authorization)を分離することで、SSOバイパスを防ぎつつ柔軟なアクセス制御が可能
- Conditional サブフロー + Condition 実行 + Deny Access の組み合わせがポイント
- フローチャートは以下の通り
Discussion