-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[DRAFT] Allow shortening of access tokens and introspection of full token content #8914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DRAFT] Allow shortening of access tokens and introspection of full token content #8914
Conversation
… the access token, which can be retrieved by token introspection
|
Hi! There is also some discussion about allowing to get access_token with additional Client Scopes applied using the /token-endpoint and refresh_token. |
|
Hi @thomasmicro, as I understand, the purpose of the userinfo endpoint is to provide profile information on the current user such as email, birthday etc. In Keycloak, per default, it does not contain role information. It's used in OIDC to retrieve more information about the user. I found this anwer on Stackoverflow quite helpful: https://stackoverflow.com/a/59015391/1078445 |
|
I'm not sure I quite follow this proposal. Is the AccessTokenShortenerMapper a special mapper that is used instead of other mappers, or in combination with other mappers? Another option could be to add more options to mappers on what they are added to. Currently, there's support for "Add to ID token" and "Add to userinfo". What about if we also add "Add to Access Token" and "Add to Introspection"? That should solve the admin client use-case as the roles mapper can just be set to only "Add to Introspection", which is then also useful to other roles, as well as any other claims. This also would have the benefit of providing support for small tokens, which can remove the need to add support for things like reference tokens. |
It is a special mapper which is used in combination with the other mappers - it's applied after all the other mappers. It removes configurable claims from the token which has been build by the other mappers.
There is already an option "Add to Access Token" for some mappers (e.g. "realm roles"). But not for all mappers - some mappers just add the corresponding claim to the access token, without configuration option (e.g. "audience resolve"). The "Add to Introspection" option would have to be added and supported by all access-token related mappers. |
|
I also like the idea of an Add to Introspection flag. I try to line out which configuration would be delivered with Keycloak with this approach.
Could this be a valid approach @stianst? |
|
We're trying to wrap this up as "lightweight access tokens", see #9713 for more details. |
|
Some thoughts on this. I am more familiar with the implementation of Reference Tokens in IdentityServer4. Correct me if I am wrong, but with a lightweight token approach, the resource server would need to do both frequent refresh and introspect requests, where only the latter can be cached, right? Also, it does not seem that this implementation utilizes token_type_hint for optimizing introspection, which could be worth considering. It is useful for revocation as well, in case Keycloak stores anything that needs to be cleared. |
|
Digging deeper into what Keycloak can do in regards to tokens and claims, I also discovered the concept of Requesting Party Tokens. It seems that this actually solves some of my issues that could not be resolved with an ordinary access token. |
|
I'm going to close this one for now as I don't like the custom/bespoke nature of it for admin endpoints. I'd say we should first prioritise getting lightweight access tokens included, then add support for that to the admin endpoints. |
This is an implementation DRAFT based on discussion #8599. I would like to get feedback from the community, whether the implemented approach makes sense, how it can be improved, or if someone suggests a better alternative.
Current Implementation
This DRAFT PR implements a mapper named AccessTokenShortenerMapper, which can be configured with a list of "Introspectable claims", which will be excluded from the resulting access token - the default value for those claims is "aud,realm_access.roles,resource_access". Instead of those claims, the token contains a special claim "isc" (short for introspectable claims), which contains the claims which have been excluded.
The "Introspectable claims" are configurable, in order to make it possible to also exclude groups or custom claims, which may become large.
The token introspection endpoint has been extended to evaluate the "isc" claim and extending the existing token with the missing claims. The missing claims are created based on a newly created access token. This access token is created based on user info, client info and scope from the existing token, skipping AccessTokenShortenerMapper.
The KeycloakIdentity class, which is used in the Admin API and several other places, has been adjusted to support reloading the missing claims (with "internal token introspection"), when an access token contains the "isc" claim.
This way, the Admin API can be used with any full-scope client with configured AccessTokenShortenerMapper - even when the full token is quite large - for example, when authorizing as an admin of many realms.
Implications of the current implementation
The current implementation of the token introspection (both the "actual" and the "internal" token introspection) extends the token with the missing claims based on the current state, not the state when the token was created. This should be fine, because the current state should be the relevant one for most use cases.
On the other hand, for performance reasons, it COULD make sense to cache a full token - then the token introspection would not necessarily reflect the current state.
Considered alternatives
Special admin-client flag on the client
This should be quite easy to implement. When this flag would be set, the Admin API would just load the roles from the persistence (see UserModelIdentity), as it is already done for the special clients admin-cli and security-admin-console.
But this approach has the drawback that it is only usable when accessing Keycloak internal API. It does not help to integrate external clients which require a large amount of authorization data.
Add a flag to mappers
Add a flag to the mappers, which defines whether this mapper's result should be excluded from a access token and only be available via token introspection. For users, it would be more intuitive to have this configuration directly at the affected mapper, but it also would be more implementation effort - not only once, but also for new mappers.
Furthermore, the client configuration would be much more complicated, because the aud, realm_access and resource_access claims are created by mappers configured for the "roles" client scope, which is a default client scope. In order to have different mappers configured for the admin clients, another "introspectable-roles" scope would have to be created and added as default scope to the client, instead of the "roles" scope. Additionally, the three mappers would have to be added to the client with appropriate configuration. And users might be confused that there are now two OIDC scopes "roles" and "introspectable-roles", for essentially the same data.
Open issues
Denylist for certain claims
It should be made sure that certain claims such as alg, typ, iss cannot be excluded from the token, in a similar way as it is already done in OIDCAttributeMapperHelper.
Support "Internal token introspection" for complete Keycloak API
For a final implementation, it has to be considered that there are several other places using bearer authentication. They probably should also be extended to support the "internal token introspection" functionality:
Maybe there are even more places?
Migration of existing clients admin-cli and security-admin-console?
Currently, in case of the special admin clients, all (role-based) authorization is done based on the roles currently assigned to the user, regardless of whether they are contained in the token or even in the scope of the client (see UserModelIdentity).
To get rid of the UserModelIdentity and similar classes, the clients admin-cli and security-admin-console would need to be re-configured in the following way: