fix(auth): reject PAT and service user when parent org is disabled#1792
Conversation
Disabling an org flipped its state but left credentials owned by that org working. The PAT and service-user auth paths fetched the principal without looking at the org state. Each PAT and service-user authenticator now checks the parent org through a new organization.IsEnabled. A disabled or missing org returns 403. The platform org (bootstrap superuser) is skipped so break-glass credentials keep working. Part of #1585. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 19 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughChangesOrganization authentication gating
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 91a8ec78-77cf-43e9-8d72-70e6b345b9b7
📒 Files selected for processing (8)
cmd/serve.gocore/authenticate/authenticators.gocore/authenticate/mocks/org_service.gocore/authenticate/service.gocore/authenticate/service_test.gocore/organization/service.gocore/organization/service_test.gointernal/api/v1beta1connect/authenticate.go
Coverage Report for CI Build 29986303562Warning No base build found for commit Coverage: 46.266%Details
Uncovered Changes
Coverage RegressionsRequires a base build to compare against. How to fix this → Coverage Stats
💛 - Coveralls |
An empty org id skipped the gate, so a PAT or service user with no resolvable org would authenticate. Return 403 for an empty id; only the platform org (a fixed UUID) is exempt. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the parent-org check out of the individual authenticators into a single point in GetPrincipal, keyed off the resolved principal type. Same behavior, one check instead of five, and any future authenticator that returns a PAT or service user principal is covered automatically. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use func() setup closures that capture the outer t (matching the existing GetPrincipal table) and add t.Helper() to the org test helper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Part of #1585.
Problem
A PAT or service user tied to a disabled org keeps authenticating.
Fix
Once a PAT or service user is resolved,
GetPrincipalchecks the parent org in one place. A disabled or missing org returns403 Forbidden. The missing-org case also covers service users left orphaned by a deleted org.The check sits at the auth boundary, not inside the shared service
Getmethods, so admin and list views can still surface principals from disabled orgs. The platform org (used by the bootstrap superuser) is skipped, so break-glass credentials keep working.Testing
Verified live against a local server. Probe RPC:
FrontierService/GetCurrentUser(it fails at the auth boundary, so its status reflects the gate directly). The org was disabled withFrontierService/DisableOrganizationas the bootstrap superuser.Bearer(authenticateWithPAT)Basicclient credentials (authenticateWithClientCredentials)Opaque service-user tokens (
CreateServiceUserToken) authenticate through the same client-credentials path, and every authenticator funnels through the singleGetPrincipalcheck.Unit tests cover disabled-org, missing-org, and empty-org for PAT and both service-user paths, plus
IsEnabledfor enabled / disabled / missing / unexpected-error.🤖 Generated with Claude Code