KEYCLOAK-80 - Spike: Investigate Keycloak's Fine Grained Admin Permissions (FGAP) v2
Spike Overview
In order to implement https://folio-org.atlassian.net/browse/KEYCLOAK-61 and https://folio-org.atlassian.net/browse/KEYCLOAK-62 it is needed first gain a better understanding for the work involved. The purpose of this spike is to investigate/research the details and come up with an implementation plan.
Jira ticket for the spike - https://folio-org.atlassian.net/browse/KEYCLOAK-80
Migrate fine-grained Keycloak admin permissions from FGAP:V1 to FGAP:V2
Feature overview
Since Keycloak 26.2.0 fine-grained admin permissions v2 is available. V2 is a stable feature. To enable this feature the admin-fine-grained-authz:v1 should be removed from the https://github.com/folio-org/folio-keycloak/blob/master/Dockerfile#L21, https://github.com/folio-org/folio-keycloak/blob/master/Dockerfile-fips#L30.
Steps to enable
FGAP:V2 can be enabled for a realm using the new Admin Permissions switch in Realm Settings:
For realm creation it is needed to add additional attribute - https://github.com/folio-org/mgr-tenants/blob/master/src/main/java/org/folio/tm/integration/keycloak/KeycloakRealmService.java#L138:
// Enable Fine-Grained Admin Permissions v2
attributes.put("adminPermissionsEnabled", "true");In case of usage Fine-Grained Admin Permissions v2 the logic related creation impersanation policy(https://github.com/folio-org/mgr-tenants/blob/master/src/main/java/org/folio/tm/integration/keycloak/service/clients/ImpersonationClientService.java#L48 ) and impersanation permission can be removed(https://github.com/folio-org/mgr-tenants/blob/master/src/main/java/org/folio/tm/integration/keycloak/service/clients/ImpersonationClientService.java#L49).
Limitations
Legacy token exchange(v1) requires fine-grained admin permissions v1 (FGAP:v1) enabled, so it is not possible to migrate to fine-grained admin permissions v2(FGAP:v2) without migration token exchange functionality (https://www.keycloak.org/docs/latest/upgrading/index.html#migrating-to-26-2-0 ):
If you still need legacy token exchange, you also need Fine-grained admin permissions version 1 enabled (FGAP:v1) because version 2 (FGAP:v2) does not have support for token exchange permissions.
Project impact
Through code investigation do not find the place where that functionality could be used in case of usage token exchange v2. Assume that FGAP:V1 was enabled because it requires for token exchange(v1).
Token Exchange v2 does not need fine-grained admin permissions v2
Migrate from token-exchange to token-exchange-standard-v2
Feature overview
Token exchange is the process that allows a client application to exchange one token for another token. Standard token exchange: version 2 (V2) - is the fully supported token exchange implementation that is enabled by default once the Keycloak server is started. To enable this feature token-exchange:v1 should be removed from https://github.com/folio-org/folio-keycloak/blob/master/Dockerfile#L21C28-L21C45 , https://github.com/folio-org/folio-keycloak/blob/master/Dockerfile-fips#L30 .
Token Exchange v2 does not need fine-grained admin permissions (neither v1 nor v2).
Steps to enable
To enable token exchange for the client Standard Token Exchange clients flag should be switched on:
The new token exchange request should be used - https://www.keycloak.org/securing-apps/token-exchange#_example_token_exchange_request:
POST /realms/test/protocol/openid-connect/token
Authorization: Basic cmVxdWVzdGVyLWNsaWVudDpwYXNzd29yZA==
Content-Type: application/x-www-form-urlencoded
Accept: application/json
grant_type=urn:ietf:params:oauth:grant-type:token-exchange&
subject_token=$SUBJECT_TOKEN&
subject_token_type=urn:ietf:params:oauth:token-type:access_token&
requested_token_type=urn:ietf:params:oauth:token-type:access_tokenThe $SUBJECT_TOKEN is a token that should be exchanged.
Limitations
According documentation - https://www.keycloak.org/securing-apps/token-exchange#_example_token_exchange_request :
The capabilities of Keycloak for token exchange are as follows:
A client can exchange an existing Keycloak token created for a specific client for a new token targeted to a different client in the same realm.
A client can exchange an existing Keycloak token for an external token, such as a linked Facebook account.
A client can exchange an external token for a Keycloak token.
A client can impersonate a user.
The same time in documentation is mentioned that :
The standard token exchange supports only use-case (1). The legacy token exchange supports the four use-cases, but it is a preview feature.
Also documentation (https://www.keycloak.org/securing-apps/token-exchange#_standard-token-exchange) mentions that:
Standard token exchange in Keycloak implements the Token exchange specification. It allows client application to exchange an existing Keycloak token created for a specific client for a new token issued to the client that triggered the token exchange request. Both clients must be in the same realm.
So impersonation logic and cross-realms requests are not supported.
Project impact
The token-exchange (v1) functionality is used for folio-module-sidecar project - https://github.com/folio-org/folio-module-sidecar/blob/master/src/main/java/org/folio/sidecar/integration/keycloak/KeycloakImpersonationService.java#L52.
This logic performs user impersonation in Keycloak to obtain an access token for cross-tenant requests. Here's what it does:
Retrieves impersonation credentials - get the client credentials of target tenant needed for impersonation:
credentialService.getImpersonationClientCredentials(targetTenant)Performs token impersonation - uses the Keycloak client to impersonate the user by calling:
keycloakClient.impersonateUserToken(targetTenant, credentials, user.getUserName())
Because of limitations (https://folio-org.atlassian.net/wiki/spaces/FOLIJET/pages/edit-v2/1373962243#Limitations ) this logic will be affected as standard token exchange(v2) does not support impersonation of a user and cross-realms exchanges.