Remove membership requirement from granular token authorization
What does this MR do and why?
Fine-grained personal access tokens are scoped to a group or project (a "boundary") plus a list of permissions. GitLab additionally required the token's owner to be a member of that group or project — but membership isn't how GitLab grants access, so users were denied things they're allowed to do.
Example: any signed-in user can create an issue in a public project without
being a member, but a token scoped to that project with Issue: Create got a
403 naming the very permission it held. An old api-scope token worked, so
moving to fine-grained tokens lost functionality. The same applied to internal
projects (non-members got no permissions at all), members of a subproject
reading its parent group, and organization owners acting on projects in their
organization.
This removes the membership check from the permission rule. The policy now answers only "what does this token permit?". Whether the user is allowed is decided by the endpoint's own authorization, which already runs after this check on every request.
Token creation still requires membership to pick a boundary; that half is tracked in the issue.
References
Screenshots or screen recordings
Not applicable — no UI changes.
How to set up and validate locally
-
Create a public project your user is not a member of.
-
Create a fine-grained personal access token with "all memberships" access and the
Issue: Createpermission. -
Post an issue to that project:
curl --request POST --header "PRIVATE-TOKEN: <token>" \ "http://gdk.test:3000/api/v4/projects/<project_id>/issues?title=test" -
Before:
403 Access denied: ... [Issue: Create]. After: the issue is created.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.
Specs run locally, all green: boundary_policy, authorize_granular_scopes_service,
middleware/go, git_access (granular block), and api/group_packages.