Keycloakのロールについて学ぶ
はじめに
Keycloakは、オープンソースのアイデンティティおよびアクセス管理ソリューションであり、OpenID Connect や SAML を利用した認証ができるツールです。Keycloakの機能の1つに、ロールベースのアクセス制御があります。ロールは、特定の権限やアクセスレベルを持つユーザーグループに割り当てられ、アプリケーションやサービスへのアクセスを制御します。
しかし、Keycloak の管理画面を見ると、ロールの設定方法が複雑で理解しにくいです。そこで、この記事では、Keycloakのロールについて理解を深めるために、ロールの概念や設定方法について学習した内容をアウトプットします。
CHANGELOG
Date | Changes |
---|---|
2025-01-12 | Added - レルムロールとクライアントロールの比較表を追加 Changed - “ロールについて” の文章を更新 - 参考リンクを一部修正 |
成果物
https://github.com/kntks/blog-code/tree/main/2024/05/keycloak-role
環境
バージョン | |
---|---|
Mac | Ventura 13.2.1 |
Keycloak | 23.0.6 |
Docker | 26.0.0 |
Docker Compose | v2.24.5 |
Terraform | 1.8.2 |
環境構築
起動する
http://localhost:8080/auth にアクセスして、Keycloakの管理画面にログインします。デフォルトのユーザー名とパスワードは、admin
です。
Terraform を使用するために Keycloak側のセットアップ が必要です。
terraform apply で Keycloak の設定を行います。
ロールについて
Keycloakでは、ユーザーやグループにアクセス権限を付与するために「ロール」を利用します。ロールには大きく分けて「レルムロール」と「クライアントロール」の2種類があります。
レルムロール (Realm Roles)
- 定義の範囲
レルム全体に適用されるロールで、同じレルム内のすべてのクライアントで利用可能です。 - 用途
グローバルな権限や役割を定義する際に使用されます。たとえば、すべてのアプリケーションに共通する「admin」や「user」などのロールを作成できます。 - 例
admin
: 全アプリケーションに対する管理者権限user
: 一般ユーザー権限manager
: チーム管理者権限
クライアントロール (Client Roles)
- 定義の範囲
特定のクライアント(アプリケーション)に限定されたロールで、それぞれのクライアントには専用の名前空間があります。 - 用途
クライアント固有の権限や役割を定義する際に使用されます。各クライアントごとに個別のロールセットを持ち、アクセス制御を細かく設定できます。 - 例
ソーシャルメディアアプリケーションにおけるロール:post
: 投稿権限comment
: コメント権限like
: いいね権限
レルムロールとクライアントロールの比較
特徴 | レルムロール | クライアントロール |
---|---|---|
適用範囲 | レルム全体 | 特定のクライアント |
権限の共有 | 複数のクライアント間で共有可能 | クライアントごとに個別 |
用途 | グローバル権限(例: 管理者、一般ユーザー) | クライアント固有の権限(例: 投稿、コメント) |
名前空間 | レルムレベルで一意の名前空間 | クライアントごとに専用の名前空間 |
割り当て対象
また、ロールを割り当てる対象は以下の3つがあります。
-
Group(以下:グループ)
グループにつけるロールです。グループは、ユーザーの集合であり、ユーザーにロールを割り当てるための便利な方法です。グループにロールを割り当てることで、グループ内のすべてのユーザーにそのロールが自動的に割り当てられます。 -
User(以下:ユーザー)
ユーザーとロールを定義します。マッピングを作成することでユーザーにレルムロールまたはクライアントロールを割り当てることでき、そのユーザーに特定のアクセス許可を付与できます。 -
Service account(以下:サービスアカウント)
各クライアントには、アクセストークンを取得するためのサービスアカウントが組み込まれています。Client Credentials Grants を利用してアクセストークンを取得する際に使用します。
参考:
- Core concepts and terms - Keycloak Documentation
- Assigning permissions using roles and groups - Keycloak Documentation
- Client roles - Keycloak Documentation
デフォルトで設定されているロール
Terraform でレルム(myrealm)、クライアント(myapp)、ユーザー(myuser)を作成しました。それぞれについているロールを確認してみましょう。
このセクションでは、アクセストークンと Keycloak の管理画面からロールを確認します。
管理画面からロールを確認する
レルムロール
レルムにデフォルトで設定されているロールを確認します。Realm settings
-> User registration
-> Default roles
に表示されているロールが、レルムにデフォルトで設定されているロールです。
クライアントロール
クライアントにデフォルトで設定されているロールを確認します。myapp
のクライアントの詳細画面に移動し、Roles
タブをクリックします。デフォルトでは、何も作成されていません。
グループ
デフォルトでグループは作成されていないので、ロールは割り当てられていません。
ユーザー
myuser
をクリックして、ユーザーの詳細画面に移動します。
Role Mappings
タブを開くと、ロールを確認できます。ユーザーに直接割り当てられているロール(default-role-myrealm)が表示されます。
Hide inherited roles
のチェックを外すと、他に割り当てられている5つのロールが表示されます。
manage-account、manage-account-links、view-profile のロール名に account
が付いていることから、account
クライアントのロールであることがわかります。
default-role-myrealm 以外のロールは、Realm settings
-> User registration
-> Default roles
にある設定によって自動的に割り当てられています。
Use default roles to automatically assign user role mappings when a user is created
(訳)デフォルトのロールを使用して、ユーザー作成時にユーザーのロールマッピングを自動的に割り当てます。
サービスアカウント
クライアント詳細画面から Service accounts roles
タブをクリックし、Hide inherited roles
のチェックを外すと、サービスアカウントに割り当てられているロールが表示されます。
アクセストークンのロールを確認する
先ほどは管理画面からロールの確認をしました。今度は、アクセストークンのロールを確認します。アクセストークンは、Resource Owner Password Credentials Grants (Direct Access Grants)とClient Credentials Grants を使用して取得します。それぞれの方法で access_token を取得します。
ユーザー
Resource Owner Password Credentials Grant でアクセストークンを取得する例
その後、取得した access_token を jwt.io に貼り付け、Payload を確認します。
※ロールに関する情報のみ表示しています。
サービスアカウント
Client Credentials Grants でアクセストークンを取得する例
その後、取得した access_token を jwt.io に貼り付け、Payload を確認します。
※ロールに関する情報のみ表示しています。
クライアントスコープとロールスコープマッピング
クライアントスコープとは、Keycloak においてレルムレベルで設定され、クライアントにリンクできるエンティティです。
Keycloak には、Client scopes
という名前がついているものが2つあり、画像左のナビゲーションペインにある Client scopes
と Clients の詳細画面の Client scopes
タブです。
紛らわしいのでこの記事では、左のナビゲーションペインにある Client scopes
を、“クライアントスコープメニュー”、Clients 詳細画面の Client scopes
タブは”クライアントスコープタブ”と呼ぶことにします。
クライアントスコープメニューから作成できるクライアントスコープは、レルム内にあるすべてのクライアントと共有でき、クライアントスコープタブから個別のクライアントにクライアントスコープをリンクできます。クライアントスコープは、クライアントにリンクされると、そのクライアントに対してアクセストークンのスコープとして使用できるようになります。
アクセストークンの”scope”を追加する
ここではクライアントスコープを作成し、クライアントにリンクすることで、アクセストークンの “scope” に追加してみます。
クライアントスコープを作成する
クライアントスコープでは、クライアント共有のクライアントスコープを作成できます。
my-client-scope
というクライアントスコープを作成します。
クライアントとクライアントスコープを関連付ける
次にクライアントスコープタブに移動し、my-client-scope
を myapp
クライアントにリンクします。
今回は Optional
で追加します。
アクセストークンの”scope”を確認する
以下のコードを実行し、アクセストークンを取得します。
その後、取得した access_token を jwt.io に貼り付け、Payload から “scope” を確認します。
次は scope に my-client-scope
を追加してアクセストークンを取得します。
こちらも同様に取得した access_token を jwt.io に貼り付け、Payload から “scope” を確認します。
先ほど作成した my-client-scope
が追加されていることが確認できます。
クライアントスコープをクライアントに関連付ける際に、Assigned type
を Optional
にしました。これを Default
に変更した場合は、トークンエンドポイントへのリクエストに scope
パラメータが “openid” のみでも、my-client-scope
が自動的に追加されます。
アクセストークンに付与されるロール
このセクションでは、ロールスコープマッピングについて学習します。
ロールスコープマッピングは以下の引用からアクセストークンに付与されるロールに関係していることがわかります。
Role Scope Mappings limit the roles declared inside an access token. When a client requests a user authentication, the access token they receive contains only the role mappings that are explicitly specified for the client’s scope.
(訳)ロールスコープマッピングは、アクセストークン内で宣言されるロールを制限します。クライアントがユーザ認証を要求したとき、彼らが受け取るアクセストークンには、クライアントのスコープに対して明示的に指定されたロールマッピングのみが含まれます。
続いての引用から、デフォルトではユーザーに割り当てられているすべてのロールがアクセストークンに含まれることがわかります。
By default, each client gets all the role mappings of the user.
(訳)デフォルトでは、各クライアントはユーザーのすべてのロールマッピングを取得します。
アクセストークンからデフォルトのロールを削除する
先ほどの”アクセストークンのロールを確認する”のセクションではアクセストークンのロールを確認しました。
しかし、デフォルトではユーザーに割り当てられているすべてのロールがアクセストークンに含まれるため、アクセストークンのサイズが大きくなる可能性があります。実際、以下の Realm settings
-> User registration
-> Default roles
にロールを追加すると自動的にアクセストークンに含まれます。
デフォルトのロールを削除しても良いのですが、クライアントスコープタブから Full Scope Allowed
を Off にすることで、アクセストークンについていたデフォルトのロールを削除できます。
Clients
-> myapp
-> Client scopes
-> myapp-dedicated
-> Scope
の順にページ移動します。
Full scope allowed
をクリックして “Off” にします。
再度アクセストークンを取得します。
Payload を確認すると、aud
や resource_access
、realm_access
が削除されていることが確認できます。
myapp ユーザーの Role mapping
を確認すると、デフォルトのロールがついていますが、アクセストークンには含まれていません。
カスタムロールをアクセストークンに追加する
先ほど Off にした Full Scope Allowed
はそのままにしておきます。
ここでは、レルムロール、myapp のクライアントロール、account のクライアントロールをユーザーに割り当て、アクセストークンに含まれるロールを確認します。
myapp
クライアントの詳細画面から Role タブに移動し my-client-role
ロール(クライアントロール)を作成します。
その後 Users
-> myuser
-> Role mapping
に移動し、Assign role
ボタンを押します。
myuser のロールに my-client-role
と、manage-account
を追加します。myapp クライアントのロールと account クライアントのロールを割り当てることで、アクセストークンに含まれるロールを確認してみます。
現在ユーザーに割り当てられているロールは以下の通りです。
いつものようにアクセストークンを発行してみます。
access_token の Payload を確認してみると、resource_access に myapp
のクライアントロールである my-client-role
のみ表示され、アクセストークンには、aud
が存在しませんでした。
Full Scope Allowed
が Off の場合、(デフォルトで作成されている)roles
クライアントスコープは、ユーザーのロールをアクセストークンに追加するために使用されます。(実際に Assign type を Default から Optional に変更すると my-client-role
もアクセストークンから無くなります。)
roles
クライアントスコープの Mappers
以下は、roles
クライアントスコープの説明です。
This scope has mappers, which are used to add the roles of the user to the access token and add audiences for clients that have at least one client role.
(訳)このスコープにはマッパーがあり、アクセストークンにユーザーのロールを追加し、少なくとも1つのクライアントロールを持つクライアントのオーディエンスを追加するために使用されます。
roles
クライアントスコープのスコープには何も設定していませんが、どうやら、myuser
が持っているロールの中から、client_id が myapp
であるクライアントにリンクされているクライアントロールのみがアクセストークンに含まれるようです。(メモ:この挙動はドキュメントを探しても見つかりませんでした。)
参考:
まとめ
この記事では、Keycloak のロールについて学習しました。Keycloak には、レルムロール、クライアントロール、グループロールの3つのロールがあります。また、ロールを割り当てる対象は、ユーザー、グループ、サービスアカウントの3つがあります。ロールを割り当てる対象にロールを割り当てることで、アプリケーションやサービスへのアクセスを制御できます。さらにクライアントスコープを使用することで、アクセストークンのスコープを制御できます。
さいごに
Keyclokaのクライアントスコープやマッパー周りは複雑で難しいです。さらに Usability improvements for Client Scope configuration #19869 のディスカッションにもあるように将来的にUIが改善されたり、Dedicated scopes
が廃止されるかもしれません。そのため、もし Keycloak 24 以上を使用している場合は最新のドキュメントを参照することをオススメします。