The Keycloak Upgrade Ledger

Every upgrade we have rehearsed, with the environment stated and the clock running.

2026-09-01 · run 2026-09-01-fgap-v2-activation

FGAP-v2 activation path pinned (26.7.3)

Condition
FGAP-v2 RBAC advisory batch (CVE-2026-14613/16105/16108/…) — unblock the reproductions by pinning how 26.7.3 turns FGAP v2 on

Question

2026-08-31-fgap-v2-token-exchange left this open: the pre-26.7 procedure (adminFineGrainedAuthz realm field + GET /admin/realms/{realm}/fine-grained-permissions) is dead in 26.7.3 — the field is unrecognized and the endpoint 404s — while the ADMIN_FINE_GRAINED_AUTHZ_V2 feature flag reports type=DEFAULT, enabled=true. How does 26.7.3 actually turn FGAP v2 on, and where is the permission catalog?

Answer (pinned from bytecode + verified live)

FGAP v2 is a DEFAULT feature and activates per-realm with the classic adminPermissionsEnabled flag. No --features gate, no adminFineGrainedAuthz field.

Bytecode path (jars extracted from quay.io/keycloak/keycloak:26.7.3):

  1. org.keycloak.services.resources.admin.fgap.AdminPermissions.evaluator(...) branches on Profile.isFeatureEnabled(ADMIN_FINE_GRAINED_AUTHZ_V2) — v2 selects MgmtPermissionsV2, v1 selects MgmtPermissions. The flag is type=DEFAULT in 26.7.3, so v2 is the only line in play.
  2. org.keycloak.authorization.fgap.AdminPermissionsSchema.init(session, realm) (spi-private) runs when the realm has admin permissions enabled. It creates a client with clientId admin-permissions (openid-connect), sets it as the realm's adminPermissionsClient, creates its authorization resource server, and seeds the schema:
    • resources = resource types: Users, Groups, Roles, Clients, Organizations (Realms is handled cross-realm);
    • scopes = the permission catalogue.

Live verification (26.7.3, Postgres, Compose lab)

POST /admin/realms {"realm":"fgap","adminPermissionsEnabled":true} → then:

GET /admin/realms/fgap            adminPermissionsEnabled: true
                                  adminPermissionsClient: {clientId: "admin-permissions"}
                                  "adminFineGrainedAuthz" NOT in representation

GET /admin/realms/fgap/clients    -> includes "admin-permissions" (authzServicesEnabled)
GET .../authz/resource-server/resource -> Clients, Groups, Organizations, Roles, Users
GET .../authz/resource-server/scope    -> 16 permission scopes (below)
GET /admin/realms/fgap/fine-grained-permissions        -> 404
GET /admin/realms/fgap/admin-fine-grained-permissions  -> 404

The v2 permission catalogue (scopes on the admin-permissions client)

view, manage, manage-members, view-members, manage-membership, manage-membership-of-members, manage-group-membership, map-roles, map-roles-client-scope, map-roles-composite, map-role, map-role-client-scope, map-role-composite, impersonate, impersonate-members, reset-password.

What changed vs pre-26.7 (migration-surfacing)

Thingpre-26.7 (v1)26.7.3 (v2)
Feature gate--features=admin-fine-grained-authz (preview)ADMIN_FINE_GRAINED_AUTHZ_V2, type=DEFAULT
Realm activationadminFineGrainedAuthz fieldadminPermissionsEnabled flag
Permissions clientrealm-management (managed)admin-permissions (new, schema-seeded)
Permission catalogueGET .../fine-grained-permissionsresources+scopes on admin-permissions's resource server
Grant a permissionv1 policy APIstandard authz scope-permission API on admin-permissions

How to audit / drive FGAP v2 in 26.7.3 (the new procedure)

  1. PUT/POST /admin/realms/{realm} with {"adminPermissionsEnabled": true}.
  2. Read adminPermissionsClient from the realm representation to get the admin-permissions client id.
  3. Catalogue: GET /admin/realms/{realm}/clients/{id}/authz/resource-server/resource (resource types) and .../scope (permissions).
  4. Grant a permission to a role/group: create a scope-based permission policy on the admin-permissions client (.../authz/resource-server/permission/scope), assigning the role/group policy — the standard authorization-services API.

What this unblocks

The FGAP-v2 RBAC CVE reproductions no longer need the dead v1 activation:

Each can now be set up by (a) enabling adminPermissionsEnabled, (b) building the role/group + scope-permission on admin-permissions, (c) exercising the admin endpoint under test. Still deferred: token-exchange CVEs (CVE-2026-18215/18214, external IdP) and CVE-2026-79652 (jwt-bearer consentRequired).

Verification

ClaimEvidence
v2 is the active line, DEFAULT featureAdminPermissions bytecode + serverinfo flag enabled=true
Activation is adminPermissionsEnabledlive realm rep + admin-permissions client created ☑
Catalogue = resources+scopes on admin-permissionslive resource (5 types) + scope (16) responses ☑
v1 surface removedadminFineGrainedAuthz absent; both catalog endpoints 404 ☑

← Back to the Ledger