fix(auth): workspace owner can generate token via read_write token (#958) - #1054
Merged
Conversation
) generate_token()'s owner-elevation fallback only ran when the resolved permission was falsy, so a workspace owner acting through a read_write token — e.g. a child token minted (and scoped) for their own workspace — fell through to "Only admin can generate token" and could not start their own server-apps (apps.start -> ws.generate_token). Two changes: - WorkspaceInfo.owned_by() now also recognises a user's personal workspace by construction ("ws-user-<uid>", or "ws-user-<parent>" for a child token). owned_by() previously matched only on id/email being present in the owners list, which a child token (random id, no email in owners) fails, even though it is the same user. The parent chain is assigned server-side in generate_token(), so it cannot be forged. - generate_token() runs the ownership fallback whenever the resolved permission is below admin (not only when it is None), elevating an owner to admin so a read_write owner can mint tokens for their own workspace. Non-owners with no permission still get the original error. Companion to #959 (get_permission strongest-of, already merged): together they let a normal workspace owner start their own server-apps without an admin token. Adds a regression test (owner mints a token through a read_write token).
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.
Summary
Fixes the remaining half of #958. A workspace owner cannot generate a token
for their own workspace when the token they are acting through only grants
read_write— they hitPermissionError("Only admin can generate token."). Inpractice this blocks a normal user from starting their own server-app:
apps.startcalls
workspace.generate_token, and Svamp's stored/derived token for the user'sown workspace is a child
read_writetoken.#959 (already merged) fixed the scope-shadowing half —
get_permissionnowreturns the strongest of
*and the specific-workspace grant. This PR fixes theownership-recognition half so the two together let an owner start their own
server-apps without an admin token.
Root cause
generate_token()only ran its owner-elevation fallback when the resolvedpermission was falsy:
An owner acting through a
read_writetoken hasmaximum_permission == read_write,skips the fallback entirely, and hits "Only admin can generate token."
There is a second, related gap. A child token minted via
generate_token()getsa fresh random
idand carriesparent = <original user id>, butowned_by()onlymatched on
id/emailbeing present in the workspaceownerslist. A personalworkspace
ws-user-<uid>does not necessarily materialise the email inowners, soowned_by()returnedFalsefor the user's own child token even though it is thesame user.
Changes
WorkspaceInfo.owned_by()also recognises a user's personal workspace byconstruction —
ws-user-<user.id>, andws-user-<user.parent>for a child token.The parent chain is assigned server-side inside
generate_token()and is notsettable by a caller, so this cannot be forged. This makes ownership recognition
consistent with how personal workspaces are keyed, independent of what is
materialised in
owners.generate_token()runs the ownership fallback whenever the resolvedpermission is below admin (not only when it is
None). A non-owner with nopermission at all still gets the original "no permission" error; a non-owner with
read_writestill gets "Only admin can generate token."Test
Adds
test_owner_can_generate_token_with_read_write_token: an owner connects,mints a
read_writetoken, reconnects with it, and mints a further token for theirown workspace — which raised "Only admin can generate token" before this change.
Notes
This is currently applied in production as a runtime monkeypatch (the amun-ai
platform's
hypha-fix958launcher, "owner-elevation" patch); merging this lets usdrop that patch. No behavior change for non-owners.
🤖 Generated with Claude Code