Mô hình RBAC và Fine-grained Admin Permissions V2 trong Keycloak
1. Tổng quan về Roles trong Keycloak
Roles trong Keycloak là cơ chế chính để phân quyền truy cập. Ứng dụng kiểm tra roles của user (thông qua claims trong token) để quyết định user được phép làm gì. Keycloak hỗ trợ hai loại roles: Realm Roles và Client Roles.
Realm Roles vs Client Roles
| Đặc điểm | Realm Roles | Client Roles |
|---|---|---|
| Phạm vi | Toàn bộ realm | Chỉ trong client cụ thể |
| Use case | Vai trò chung (Admin, User, Manager) | Vai trò riêng cho ứng dụng (editor, viewer) |
| Namespace | Unique trong realm | Unique trong client |
| Token claim | realm_access.roles | resource_access.{client}.roles |
2. Realm Roles
2.1 Realm Roles mặc định
Keycloak tạo sẵn một số realm roles:
default-roles-{realm} — composite role chứa các roles mặc định cho users mới
offline_access — cho phép lấy offline token (refresh token dài hạn)
uma_authorization — cho phép sử dụng UMA (User-Managed Access)
2.2 Tạo Realm Role
Qua Admin Console:
Click Realm roles trong sidebar
Click Create role
Nhập:
- Role name:
admin - Description:
Full administrator access
- Role name:
Click Save
Qua Admin CLI:
# Tạo realm roles bin/kcadm.sh create roles -r my-company -s name=admin -s description="Full administrator access" bin/kcadm.sh create roles -r my-company -s name=manager -s description="Manager with limited admin access" bin/kcadm.sh create roles -r my-company -s name=user -s description="Regular user" bin/kcadm.sh create roles -r my-company -s name=viewer -s description="Read-only access"Xem danh sách realm roles
bin/kcadm.sh get roles -r my-company --fields name,description
Qua REST API:
# Tạo realm role curl -s -X POST \ "http://localhost:8080/admin/realms/my-company/roles" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "admin", "description": "Full administrator access", "composite": false }'Lấy danh sách realm roles
curl -s -X GET
"http://localhost:8080/admin/realms/my-company/roles"
-H "Authorization: Bearer $ACCESS_TOKEN" | jq '.[].name'
3. Client Roles
Client roles được sử dụng khi ứng dụng cần roles riêng — ví dụ ứng dụng CMS có roles editor, author, reviewer khác với roles của ứng dụng HR.
3.1 Tạo Client Role
Qua Admin Console:
Vào Clients → chọn client (ví dụ:
my-web-app)Tab Roles
Click Create role
Nhập name và description
Qua CLI:
# Lấy client ID CLIENT_UUID=$(bin/kcadm.sh get clients -r my-company -q clientId=my-web-app --fields id --format csv --noquotes)Tạo client roles
bin/kcadm.sh create clients/$CLIENT_UUID/roles -r my-company
-s name=editor -s description="Can create and edit content"bin/kcadm.sh create clients/$CLIENT_UUID/roles -r my-company
-s name=author -s description="Can create content"bin/kcadm.sh create clients/$CLIENT_UUID/roles -r my-company
-s name=reviewer -s description="Can review and approve content"bin/kcadm.sh create clients/$CLIENT_UUID/roles -r my-company
-s name=content-admin -s description="Full content management"Xem client roles
bin/kcadm.sh get clients/$CLIENT_UUID/roles -r my-company --fields name,description
Qua REST API:
curl -s -X POST \
"http://localhost:8080/admin/realms/my-company/clients/$CLIENT_UUID/roles" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "editor",
"description": "Can create and edit content"
}'
3.2 Client Roles trong Token
Client roles xuất hiện trong access token dưới claim resource_access:
{
"realm_access": {
"roles": ["user", "offline_access"]
},
"resource_access": {
"my-web-app": {
"roles": ["editor", "author"]
},
"my-api": {
"roles": ["read", "write"]
},
"account": {
"roles": ["manage-account", "view-profile"]
}
}
}
4. Composite Roles
Composite roles là roles chứa một hoặc nhiều roles con (realm roles và/hoặc client roles). Khi user được gán composite role, user tự động có tất cả roles con.
4.1 Tạo Composite Role
Qua Admin Console:
Vào Realm roles → chọn role (ví dụ:
admin)Tab Action → Add associated roles
Chọn các roles cần thêm (realm roles và/hoặc client roles)
Click Assign
Qua CLI:
# Tạo composite role: "manager" chứa "user" và "viewer" bin/kcadm.sh add-roles \ -r my-company \ --rname manager \ --rolename user \ --rolename viewerThêm client roles vào composite role
bin/kcadm.sh add-roles
-r my-company
--rname manager
--cclientid my-web-app
--rolename editor
--rolename reviewer
Ví dụ hierarchy:
admin (composite)
├── manager (composite)
│ ├── user (realm role)
│ ├── viewer (realm role)
│ ├── my-web-app/editor (client role)
│ └── my-web-app/reviewer (client role)
├── my-web-app/content-admin (client role)
└── account/manage-account (client role)
Lưu ý: Khi user được gán role admin, user sẽ có tất cả roles trong cây hierarchy: admin, manager, user, viewer, editor, reviewer, content-admin, manage-account.
4.2 Xem Composite Roles
# Xem roles con của composite role bin/kcadm.sh get-roles -r my-company --rname admin --effectiveREST API
curl -s -X GET
"http://localhost:8080/admin/realms/my-company/roles/admin/composites"
-H "Authorization: Bearer $ACCESS_TOKEN" | jq '.[].name'
5. Role Mappings
5.1 Gán Role cho User
Qua Admin Console:
Vào Users → chọn user
Tab Role mapping
Click Assign role
Chọn realm roles hoặc filter by client để chọn client roles
Click Assign
Qua CLI:
# Gán realm roles cho user bin/kcadm.sh add-roles \ -r my-company \ --uusername john.doe \ --rolename adminGán client roles cho user
bin/kcadm.sh add-roles
-r my-company
--uusername john.doe
--cclientid my-web-app
--rolename editorXem roles của user (bao gồm effective roles từ composite và groups)
bin/kcadm.sh get-roles
-r my-company
--uusername john.doe
--effective
Qua REST API:
# Lấy role representation ROLE_ID=$(curl -s -X GET \ "http://localhost:8080/admin/realms/my-company/roles/admin" \ -H "Authorization: Bearer $ACCESS_TOKEN" | jq -r '.id')ROLE_NAME=$(curl -s -X GET
"http://localhost:8080/admin/realms/my-company/roles/admin"
-H "Authorization: Bearer $ACCESS_TOKEN" | jq -r '.name')Gán realm role cho user
curl -s -X POST
"http://localhost:8080/admin/realms/my-company/users/$USER_ID/role-mappings/realm"
-H "Authorization: Bearer $ACCESS_TOKEN"
-H "Content-Type: application/json"
-d "[$(curl -s -X GET
"http://localhost:8080/admin/realms/my-company/roles/admin"
-H "Authorization: Bearer $ACCESS_TOKEN")]"
5.2 Gán Role cho Group
Khi gán role cho group, tất cả members của group (và sub-groups) sẽ kế thừa role đó:
# Qua CLI
bin/kcadm.sh add-roles \
-r my-company \
--gname Engineering \
--rolename user
bin/kcadm.sh add-roles \
-r my-company \
--gname Engineering \
--cclientid my-web-app \
--rolename viewer
# Qua REST API
curl -s -X POST \
"http://localhost:8080/admin/realms/my-company/groups/$GROUP_ID/role-mappings/realm" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "[$(curl -s -X GET \
"http://localhost:8080/admin/realms/my-company/roles/user" \
-H "Authorization: Bearer $ACCESS_TOKEN")]"
5.3 Effective Roles
Effective roles của user = roles được gán trực tiếp + roles kế thừa từ groups + roles từ composite roles:
# Xem effective realm roles curl -s -X GET \ "http://localhost:8080/admin/realms/my-company/users/$USER_ID/role-mappings/realm/composite" \ -H "Authorization: Bearer $ACCESS_TOKEN" | jq '.[].name'Xem effective client roles
curl -s -X GET
"http://localhost:8080/admin/realms/my-company/users/$USER_ID/role-mappings/clients/$CLIENT_UUID/composite"
-H "Authorization: Bearer $ACCESS_TOKEN" | jq '.[].name'
6. Default Roles
Default roles tự động được gán cho mọi user mới khi tạo tài khoản hoặc đăng ký.
6.1 Cấu hình Default Roles
Qua Admin Console:
Vào Realm roles
Tìm role default-roles-{realm} (ví dụ:
default-roles-my-company)Click vào role → tab Action → Add associated roles
Chọn roles muốn set làm default
Qua CLI:
# Thêm role vào default roles bin/kcadm.sh add-roles \ -r my-company \ --rname default-roles-my-company \ --rolename user \ --rolename offline_accessThêm client role vào default roles
bin/kcadm.sh add-roles
-r my-company
--rname default-roles-my-company
--cclientid my-web-app
--rolename viewer
Sau đó, mọi user mới tạo sẽ tự động có roles: user, offline_access, my-web-app/viewer.
7. Service Account Roles
Service accounts được sử dụng cho communication giữa services (machine-to-machine) — không cần user interaction.
7.1 Bật Service Account cho Client
Vào Clients → chọn hoặc tạo client
Tab Settings:
- Client authentication: ON
- Service accounts roles: ON
- Authorization: OFF (trừ khi cần authorization services)
Click Save
7.2 Gán Role cho Service Account
# Qua Admin Console: # Clients → chọn client → tab "Service account roles" → Assign roleQua CLI - lấy service account user
SA_USER_ID=$(bin/kcadm.sh get clients/$CLIENT_UUID/service-account-user -r my-company --fields id --format csv --noquotes)
Gán realm roles
bin/kcadm.sh add-roles
-r my-company
--uid $SA_USER_ID
--rolename adminGán client roles (realm-management) cho API access
bin/kcadm.sh add-roles
-r my-company
--uid $SA_USER_ID
--cclientid realm-management
--rolename manage-users
--rolename view-users
--rolename manage-clients
7.3 Sử dụng Service Account
# Lấy access token cho service account (client credentials grant) ACCESS_TOKEN=$(curl -s -X POST \ "http://localhost:8080/realms/my-company/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials" \ -d "client_id=my-backend-service" \ -d "client_secret=YOUR_CLIENT_SECRET" | jq -r '.access_token')Sử dụng token để gọi API
curl -s -X GET
"http://localhost:8080/admin/realms/my-company/users"
-H "Authorization: Bearer $ACCESS_TOKEN" | jq '.[].username'
8. Fine-grained Admin Permissions V2
Fine-grained admin permissions V2 (từ Keycloak 26+) cho phép kiểm soát chi tiết ai có thể quản lý resources nào trong Admin Console — thay vì chỉ dùng realm-management client roles thô.
8.1 Bật Fine-grained Admin Permissions
Vào Realm settings → General
Tìm Admin Permissions → bật Fine-grained admin permissions (V2)
Keycloak sẽ tạo permission management resources trong realm
Lưu ý: Đây là tính năng preview trong Keycloak 26.x. Trong production, cần đánh giá kỹ trước khi bật.
8.2 Resource Permissions
Sau khi bật, bạn có thể tạo permissions cho các resources:
Users permissions:
| Permission | Mô tả |
|---|---|
| view | Xem danh sách và chi tiết users |
| manage | Tạo, sửa, xóa users |
| map-roles | Gán/gỡ roles cho users |
| manage-group-membership | Thêm/xóa users khỏi groups |
| impersonate | Impersonate users |
Groups permissions:
| Permission | Mô tả |
|---|---|
| view | Xem groups |
| manage | Tạo, sửa, xóa groups |
| view-members | Xem members của group |
| manage-members | Thêm/xóa members |
| manage-membership | Quản lý group membership |
Clients permissions:
| Permission | Mô tả |
|---|---|
| view | Xem clients |
| manage | Tạo, sửa, xóa clients |
| configure | Thay đổi client settings |
| map-roles | Tạo/gán client roles |
Roles permissions:
| Permission | Mô tả |
|---|---|
| view | Xem roles |
| manage | Tạo, sửa, xóa roles |
| map-role | Gán roles cho users/groups |
8.3 Tạo Permission
Vào Realm settings → Admin permissions
Chọn resource type (Users, Groups, Clients, Roles)
Click vào permission cần cấu hình (ví dụ: manage cho Users)
Thêm policies để xác định ai có permission này
8.4 Policies
Policies xác định điều kiện để cấp permission. Keycloak V2 hỗ trợ các loại policies:
Role-based Policy:
// Cho phép users có role "hr-admin" quản lý users
{
"type": "role",
"name": "HR Admin Policy",
"description": "Users with hr-admin role",
"roles": [
{
"id": "{role-id-of-hr-admin}",
"required": true
}
]
}
User-based Policy:
// Cho phép specific users
{
"type": "user",
"name": "Specific Admin Policy",
"users": [
"{user-id-of-admin-1}",
"{user-id-of-admin-2}"
]
}
Group-based Policy:
// Cho phép members của group
{
"type": "group",
"name": "Admin Group Policy",
"groups": [
{
"id": "{group-id-of-admins}",
"extendChildren": true
}
]
}
Client-based Policy:
// Cho phép specific clients (service accounts)
{
"type": "client",
"name": "Backend Service Policy",
"clients": [
"{client-id-of-backend-service}"
]
}
8.5 Ví dụ thực tế: HR Admin chỉ quản lý Users
Yêu cầu: User có role hr-admin chỉ được phép xem và quản lý users, không được quản lý clients hay realm settings.
Tạo realm role
hr-admin:bin/kcadm.sh create roles -r my-company \ -s name=hr-admin \ -s description="HR Administrator - can manage users only"Bật Fine-grained admin permissions V2
Tạo Role-based Policy cho
hr-admin:- Vào Admin permissions → Policies tab
- Create policy → Role-based
- Name: "HR Admin Policy"
- Chọn role:
hr-admin
Gán policy vào Users permissions:
- Users → permission view → Add policy "HR Admin Policy"
- Users → permission manage → Add policy "HR Admin Policy"
Gán role cho user:
bin/kcadm.sh add-roles -r my-company \ --uusername hr-manager \ --rolename hr-admin
Giờ user hr-manager có thể đăng nhập Admin Console và chỉ thấy menu Users.
8.6 Permission Evaluation
Bạn có thể test permissions bằng cách sử dụng Evaluation tab:
Vào Admin permissions → Evaluate
Chọn user hoặc client cần test
Chọn resource type và permission
Click Evaluate để xem kết quả (PERMIT hoặc DENY)
9. Dedicated Realm Admin Consoles
Keycloak cho phép tạo admin accounts riêng cho mỗi realm — không cần truy cập master realm:
9.1 Tạo Realm Admin
# Tạo user trong realm bin/kcadm.sh create users -r my-company \ -s username=realm-admin \ -s [email protected] \ -s enabled=true \ -s emailVerified=truebin/kcadm.sh set-password -r my-company
--username realm-admin
--new-password "RealmAdmin@123"Gán realm-management client roles
bin/kcadm.sh add-roles -r my-company
--uusername realm-admin
--cclientid realm-management
--rolename realm-admin
9.2 Realm Management Client Roles
Client realm-management có sẵn các roles để kiểm soát quyền admin:
| Role | Mô tả |
|---|---|
| realm-admin | Full admin access cho realm |
| manage-users | Quản lý users |
| view-users | Xem users |
| manage-clients | Quản lý clients |
| view-clients | Xem clients |
| manage-realm | Quản lý realm settings |
| view-realm | Xem realm settings |
| manage-identity-providers | Quản lý identity providers |
| manage-events | Quản lý events |
| manage-authorization | Quản lý authorization |
| impersonation | Impersonate users |
| query-users | Tìm kiếm users |
| query-groups | Tìm kiếm groups |
| query-clients | Tìm kiếm clients |
| query-realms | Tìm kiếm realms |
Ví dụ: Tạo limited admin chỉ quản lý users và groups:
bin/kcadm.sh add-roles -r my-company \
--uusername limited-admin \
--cclientid realm-management \
--rolename manage-users \
--rolename view-users \
--rolename query-users \
--rolename query-groups
10. Sử dụng Roles trong ứng dụng
10.1 Kiểm tra Roles từ Access Token
Decoded access token chứa roles:
{
"sub": "user-uuid",
"realm_access": {
"roles": [
"admin",
"manager",
"user",
"default-roles-my-company",
"offline_access",
"uma_authorization"
]
},
"resource_access": {
"my-web-app": {
"roles": [
"editor",
"content-admin"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
}
}
10.2 Ví dụ trong Spring Boot
// SecurityConfig.java @Configuration @EnableWebSecurity public class SecurityConfig {@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/api/admin/**").hasRole("admin") .requestMatchers("/api/content/**").hasRole("editor") .requestMatchers("/api/public/**").permitAll() .anyRequest().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt .jwtAuthenticationConverter(jwtAuthenticationConverter()) ) ); return http.build(); } @Bean public JwtAuthenticationConverter jwtAuthenticationConverter() { JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter(); converter.setAuthoritiesClaimName("realm_access.roles"); converter.setAuthorityPrefix("ROLE_"); JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter(); jwtConverter.setJwtGrantedAuthoritiesConverter(converter); return jwtConverter; }
}
10.3 Ví dụ trong Node.js (Express)
// middleware/auth.js const jwt = require('jsonwebtoken');function hasRealmRole(role) { return (req, res, next) => { const token = req.headers.authorization?.split(' ')[1]; if (!token) return res.status(401).json({ error: 'No token provided' });
try { const decoded = jwt.decode(token); const roles = decoded.realm_access?.roles || []; if (roles.includes(role)) { req.user = decoded; next(); } else { res.status(403).json({ error: 'Insufficient permissions' }); } } catch (err) { res.status(401).json({ error: 'Invalid token' }); }}; }
function hasClientRole(clientId, role) { return (req, res, next) => { const token = req.headers.authorization?.split(' ')[1]; if (!token) return res.status(401).json({ error: 'No token provided' });
try { const decoded = jwt.decode(token); const roles = decoded.resource_access?.[clientId]?.roles || []; if (roles.includes(role)) { req.user = decoded; next(); } else { res.status(403).json({ error: 'Insufficient permissions' }); } } catch (err) { res.status(401).json({ error: 'Invalid token' }); }}; }
// Sử dụng app.get('/api/admin/users', hasRealmRole('admin'), (req, res) => { // Only admin can access });
app.post('/api/content', hasClientRole('my-web-app', 'editor'), (req, res) => { // Only editors can create content });
11. Bài tập thực hành
Tạo Realm Roles:
super-admin,manager,staff,viewerTạo Client Roles cho client
my-web-app:content-editor,content-reviewer,content-publisherTạo Composite Roles:
super-adminchứa:manager+ tất cả client rolesmanagerchứa:staff+content-reviewerstaffchứa:viewer+content-editor
Gán roles cho groups:
- Group
Engineering: realm rolestaff - Group
Engineering/Backend: client rolecontent-editor
- Group
Bật Fine-grained admin permissions V2 và tạo:
- Role-based policy cho
hr-admin - Gán policy vào Users view/manage permissions
- Test với user có role
hr-admin
- Role-based policy cho
Tạo Service Account cho client
my-backend-servicevới rolesmanage-users,view-usersvà test bằng client credentials grant
12. Tổng kết
Trong bài này, bạn đã học:
Phân biệt Realm Roles và Client Roles
Tạo Composite Roles với hierarchy phân quyền
Role Mappings cho users và groups (trực tiếp và kế thừa)
Cấu hình Default Roles cho users mới
Sử dụng Service Account Roles cho machine-to-machine communication
Fine-grained Admin Permissions V2 với policies (role-based, user-based, group-based, client-based)
Tạo dedicated realm admin với limited permissions
Kiểm tra roles trong ứng dụng (Spring Boot, Node.js)
Bài tiếp theo sẽ hướng dẫn về Clients, Client Scopes và OpenID Connect trong Keycloak.