🔐

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. フローを作成

  1. 管理コンソール → Authentication → Flowsで「Create Flowを選択」

2. 認証系サブフローを作成

  1. 先頭に Authentication サブフロー(Requirement = Required)を作成
  2. 中に以下を追加(Browserフローを参考にしながらだとやりやすい)
    • Cookie(Alternative)
    • Kerberos(Disabled)
    • Identity Provider Redirector(Alternative)
    • login forms(Alternative)
      • Username Password Form(Required)

3. OTPサブフローを追加(任意)

  1. custom OTP サブフローを追加(Requirement = Conditional)
  2. 中に以下を追加
    • Condition - user configured(Required)
    • OTP Form(Required)

これにより「OTP設定済みのユーザーのみOTP入力を要求」できます。

4. 認可サブフローを追加

  1. Authorization サブフローを追加(Requirement = Conditional)
  2. 中に以下を追加
    • Condition - user role(Required)
      • Role: streamlit-user-role(事前作成したRealm Role)
      • Negate output: ON(ロールを持たない時に true)
    • Deny Access(Required)
      • Error message: 任意(例: You do not have the required role.

参考:全体設定

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