Skip to content

fix(auth): load projects for project-scoped OAuth#3552

Open
dmarticus wants to merge 4 commits into
mainfrom
posthog-code/fix-local-project-scoped-auth
Open

fix(auth): load projects for project-scoped OAuth#3552
dmarticus wants to merge 4 commits into
mainfrom
posthog-code/fix-local-project-scoped-auth

Conversation

@dmarticus

@dmarticus dmarticus commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Problem

Project-scoped OAuth tokens expose authorized project IDs in scoped_teams, but PostHog Code discarded that field and tried to load projects through the organization endpoint. When the backend rejects project-scoped tokens on organization endpoints, the session remains authenticated with “No project selected.”

This follows #3279, merged on July 8, 2026. That fix correctly handled empty scoped_organizations by falling back to the user’s current organization, but it depended on the organization endpoint accepting the team-scoped token. The direct scoped-project path removes that dependency.

Why: Local development should work when a developer grants project-level access instead of organization-level access during OAuth authorization.

Changes

  • Preserve scoped_teams from OAuth token responses and hydrate those projects directly through project-scoped endpoints.
  • Keep the existing organization-scoped and legacy fallback paths, including transient recovery behavior.
  • Cover both runtime token parsing and the flow where organization access is forbidden.

How did you test this?

  • pnpm build:deps
  • pnpm --filter @posthog/core exec vitest run src/auth/auth.test.ts src/auth/oauth.schemas.test.ts
  • pnpm --filter @posthog/core typecheck
  • pnpm exec biome lint packages/core

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Created with PostHog Code

Generated-By: PostHog Code
Task-Id: 07b377f9-4583-463c-b256-cc29621375e6
@trunk-io

trunk-io Bot commented Jul 17, 2026

Copy link
Copy Markdown

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit 446da28.

Generated-By: PostHog Code
Task-Id: 07b377f9-4583-463c-b256-cc29621375e6
Generated-By: PostHog Code
Task-Id: 07b377f9-4583-463c-b256-cc29621375e6

Copy link
Copy Markdown
Contributor Author

CI follow-up: all code-owned checks on this PR passed (build, unit/integration/E2E, typecheck, quality, and security scans). The remaining Trunk Impacted Targets / upload failure is repository-wide: TRUNK_API_TOKEN is empty and the Trunk API returns HTTP 401. Recent unrelated PRs are failing the same workflow. I updated this branch from main, and the fresh run reproduced the same infrastructure failure; no workflow or secret changes are included in this PR.

@dmarticus
dmarticus marked this pull request as ready for review July 17, 2026 22:12
@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "Merge branch 'main' into posthog-code/fi..." | Re-trigger Greptile

Comment thread packages/core/src/auth/auth.ts Outdated
Comment on lines +650 to +657
scopedOrgIds.length > 0
? await this.buildOrgProjectsMap(
tokenResponse.access_token,
options.cloudRegion,
scopedOrgIds,
previousMap,
)
: scopedProjectIds.length > 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Mixed Scopes Skip Project Hydration

When a token contains both scoped_organizations and scoped_teams, this branch uses only the organization path. If the organization endpoint rejects the project-scoped token or omits its team-only projects, those authorized projects disappear from the picker even though their IDs were supplied in scoped_teams.

Rule Used: When implementing new features, ensure that owners... (source)

Learned From
PostHog/posthog#31236

Comment thread packages/core/src/auth/auth.ts Outdated
Comment on lines +683 to +686
const resolvedCurrentOrgId =
currentOrgId && orgProjectsMap[currentOrgId]
? currentOrgId
: (Object.keys(orgProjectsMap)[0] ?? currentOrgId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Organization And Project Can Diverge

For scoped projects spanning multiple organizations, pickInitialProjectId can restore a preferred project from one organization while this independent fallback chooses the first organization in the map. The session then exposes a current organization that does not own the current project, so the picker and later organization-scoped operations can target different organizations.

Comment on lines +724 to +727

const { orgId, project } = result.data;
const existing = map[orgId];
map[orgId] = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Permanent Failure Silently Drops Scope

If one scoped project returns a non-retryable response such as 403, 404, or malformed successful JSON, this path omits it without marking the map incomplete. The session is then committed with recovery disabled, so that token-provided project remains missing until the user authenticates again.

Generated-By: PostHog Code
Task-Id: 07b377f9-4583-463c-b256-cc29621375e6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant