chore: super admin personal access tokens#2686
Conversation
Signed-off-by: Philip Miglinci <pmig@glasskube.com>
PR SummaryHigh Risk Overview Authentication changes load PATs without requiring org membership ( The nav Personal Access Tokens link is shown for super admins; token create failures surface via Reviewed by Cursor Bugbot for commit c03e9ba. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6bb31eb. Configure here.
There was a problem hiding this comment.
Pull request overview
Enables super admins to create/manage personal access tokens (PATs) while ensuring any PAT used by a super admin is effectively read-only across requests, and updates UI navigation to expose PAT management to super admins.
Changes:
- Clamp super-admin token effective role to
read_onlyand add coverage inEffectiveUserRole()tests. - Allow super admins to create/delete their own PATs (removing
BlockSuperAdminfrom those routes) with additional membership enforcement during creation. - Propagate
isSuperAdmininto auth info from PATs and update UI to show PAT nav + improved create error toast handling.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/types/access_token.go | Makes super-admin PATs always act as read-only via EffectiveUserRole(). |
| internal/types/access_token_test.go | Adds a super-admin case to role-capping tests. |
| internal/handlers/settings.go | Removes BlockSuperAdmin for PAT create/delete endpoints and documents the exception. |
| internal/handlers/settings_access_token.go | Enforces org membership for super-admin PAT creation and forces read-only role. |
| internal/authn/authinfo/token.go | Ensures PAT-derived auth info carries isSuperAdmin and documents expected behavior. |
| frontend/ui/src/app/components/nav-bar/nav-bar.component.html | Shows “Personal Access Tokens” menu item for super admins. |
| frontend/ui/src/app/access-tokens/access-tokens.component.ts | Treats super admins as read-only in role selection and shows backend error messages on create failures. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| http.Error(w, err.Error(), http.StatusInternalServerError) | ||
| return | ||
| } | ||
| request.UserRole = new(types.UserRoleReadOnly) |
| superAdmin := AccessTokenWithUserAccount{ | ||
| AccessToken: AccessToken{UserRole: new(UserRoleAdmin)}, | ||
| UserAccount: UserAccount{IsSuperAdmin: true}, | ||
| } | ||
| g.Expect(superAdmin.EffectiveUserRole()).To(Equal(UserRoleReadOnly)) |
| // A token issued by a super admin carries the super admin identity, so it | ||
| // has the same read access as an interactive super admin session (it can | ||
| // read all organizations). Write access is still blocked for super admins | ||
| // (BlockSuperAdmin), and EffectiveUserRole caps the role to read-only. | ||
| // Such tokens can only be created in an organization the super admin is a | ||
| // member of (enforced at creation). |
| // Super admins are not organization members and may only create read-only tokens. | ||
| this.auth.isSuperAdmin() ? 'read_only' : this.auth.getClaims()?.role |
| // Super admins may only create tokens in an organization they are a | ||
| // member of, and those tokens are always read-only. |
There was a problem hiding this comment.
If I understand correctly, this is in conflict with the premise that super-admins are not supposed to be a member of any organizations
There was a problem hiding this comment.
But they are created in an organization
Signed-off-by: Philip Miglinci <pmig@glasskube.com>
| // When the user has no membership in the token's organization (e.g. a | ||
| // super-admin-owned token), there is no role to cap against and the token's own | ||
| // role is authoritative. |
| if auth.IsSuperAdmin() { | ||
| // Super admins are not organization members, so they may only ever | ||
| // create read-only tokens regardless of what was requested. | ||
| request.UserRole = new(types.UserRoleReadOnly) | ||
| } else if request.UserRole != nil { |
| mk := func(tokenRole *UserRole, orgRole UserRole) AccessTokenWithUserAccount { | ||
| return AccessTokenWithUserAccount{ | ||
| AccessToken: AccessToken{UserRole: tokenRole}, | ||
| UserRole: orgRole, | ||
| UserRole: &orgRole, | ||
| } |
| g.Expect(AccessTokenWithUserAccount{ | ||
| AccessToken: AccessToken{UserRole: new(UserRoleAdmin)}, | ||
| UserRole: nil, | ||
| }.EffectiveUserRole()).To(Equal(UserRoleReadOnly)) |
| g.Expect(AccessTokenWithUserAccount{ | ||
| AccessToken: AccessToken{UserRole: new(UserRoleAdmin)}, | ||
| UserAccount: UserAccount{IsSuperAdmin: true}, | ||
| }.EffectiveUserRole()).To(Equal(UserRoleReadOnly)) |
| // and a capped role, so it must not be exchangeable for a different or more privileged session | ||
| // (e.g. a super admin's read-only PAT minting a super-admin JWT via switch-context). It must run | ||
| // after the authentication middleware. | ||
| func RejectAccessToken(handler http.Handler) http.Handler { |
There was a problem hiding this comment.
Similar middlewares are called Block... I think this should be called BlockAccessToken
| emailVerified: a.CurrentUserEmailVerified(), | ||
| tokenScope: a.TokenScope(), | ||
| userRole: nil, // Interactive super admins don't have a role | ||
| isSuperAdmin: true, |
There was a problem hiding this comment.
Setting this to true by default seems really scary. since we already have the user account, I think we could set it to user.isSuperAdmin right away

No description provided.