fix: read admin role from a configurable access-token claim path - #77
Merged
Merged
Conversation
getRolesFromAccessToken only read realm_access.roles from the Keycloak access token, but the admin role is assigned as a client role (resource_access.<client_id>.roles), so it never matched and every user was demoted to "user" in production. Now roles are merged from both realm_access.roles and resource_access[AUTH_KEYCLOAK_ID].roles before checking for "admin". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
admin is exclusively a client role, so checking realm_access.roles was unnecessary and could theoretically false-positive on an unrelated realm role of the same name. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ut, add federated logout support Aligns auth.ts with the sibling project's approach (role types kept binary: admin/user only): - Role is read from profile.roles at sign-in again, instead of being recomputed from the access token's client roles on every jwt() call. Admin revocation now takes effect on next login rather than near-instantly, which is an accepted trade-off here. - Any refresh token failure now forces logout (no longer special-cased for invalid_grant vs transient errors). - Added a redirect callback that allows passthrough to Keycloak's end_session_endpoint, and store id_token on the JWT so a federated Keycloak logout can be wired up later. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…urable Reverts a8489f6's move back to profile.roles (which reintroduces the "admin revoked but session stays admin until relogin" gap) in favor of the access-token approach, but generalizes it: instead of hardcoding resource_access[AUTH_KEYCLOAK_ID].roles, the claim path is now read from AUTH_KEYCLOAK_ROLES_CLAIM (dot-separated, e.g. "resource_access.<client-id>.roles" or "realm_access.roles"), defaulting to "realm_access.roles" if unset. This makes the realm-role-vs-client-role choice a deployment config instead of a code change, so switching it in Keycloak doesn't require another PR. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Production could not correctly identify admin users — everyone was treated as a regular
user, even accounts that should have admin access. The previous release worked fine.Root cause
getRolesFromAccessTokeninsrc/auth.tsonly readrealm_access.rolesfrom the Keycloak access token, butadminis assigned as a client role, which lives underresource_access.<client_id>.roles, notrealm_access. Since the code never looked there, no user could ever be recognized as admin.Fix
jwt()callback (so Keycloak-side revocation takes effect promptly, without waiting for a full re-login).AUTH_KEYCLOAK_ROLES_CLAIM(dot-separated path into the decoded access token payload, e.g.resource_access.<client-id>.rolesorrealm_access.roles), defaulting torealm_access.roleswhen unset.This turns the realm-role-vs-client-role question into a deployment config choice instead of a code change.
Deployment note
Production needs
AUTH_KEYCLOAK_ROLES_CLAIMset toresource_access.<client-id>.roles(with the actual Keycloak client id) for theadminclient role to be picked up correctly.Verification
tsc --noEmitpasses.adminis configured as a Keycloak client role.🤖 Generated with Claude Code