fix(oauth): isolate follow token from auth token to prevent scope overwrite#274
Open
Ridanshi wants to merge 1 commit into
Open
fix(oauth): isolate follow token from auth token to prevent scope overwrite#274Ridanshi wants to merge 1 commit into
Ridanshi wants to merge 1 commit into
Conversation
…rwrite The GitHub connect flow (user:follow scope) and the GitHub login flow (read:user user:email scope) both performed an upsert against the same OAuthToken record keyed on (userId, 'github'). Whichever executed last silently replaced the other's access token. The practical effect: every re-authentication destroyed the user's GitHub follow capability. Fix (no schema migration required): - Introduce GITHUB_FOLLOW_PLATFORM = 'github_follow' constant in connect.ts - connect.ts callback: write the follow-capable token to platform='github_follow' instead of platform='github'. The auth flow (auth.ts) continues writing to 'github' — the two records now have independent keys and can never overwrite each other. - follow.ts: resolve the GitHub token lookup to 'github_follow' so the follow route reads from the correct record. All non-GitHub platforms are unaffected. Backward compatibility: - Existing 'github' auth token records remain intact and continue to be used by the login flow. - Users with a pre-existing 'github' follow token will need to re-run the connect flow (one-time action) to populate the new 'github_follow' record. The existing record is not deleted or modified. Tests added (oauth-scope.test.ts): - Connect callback writes to github_follow, never to github - Scope and encrypted token stored correctly in the follow record - Follow route looks up github_follow, never the auth token - Follow route returns 400+requiresAuth when github_follow is absent (no fallback) - Non-GitHub platforms use their own name unchanged - Repeated connect cycles only touch github_follow - Follow succeeds after a connect cycle - Follow survives a simulated re-login cycle - Encrypted token persistence: raw token is never stored verbatim - Follow route decrypts before calling GitHub API
Contributor
|
@Ridanshi Allow some time to review this PR. |
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.
Problem
The GitHub login flow and GitHub connect/follow flow both persisted OAuth tokens into the same
OAuthTokenrecord keyed by:despite requiring different permission scopes.
Login flow (
auth.ts)Stored tokens with:
Connect flow (
connect.ts)Stored tokens with:
Because both flows used Prisma
upserton the same(userId, platform)key, whichever flow executed last silently overwrote the previous token.In practice:
Root Cause
OAuthTokenis uniquely keyed by:@@unique([userId, platform])Both flows persisted tokens using:
This created a deterministic overwrite lifecycle where:
The issue was difficult to diagnose because:
Fix
Implemented deterministic scope-safe token isolation.
Scope Handling Strategy
The authentication flow and follow-capable flow now use separate platform keys:
auth.ts)githubread:user user:emailconnect.ts)github_followuser:followThis completely prevents cross-flow token overwrites.
No schema migration was required because:
platformis already a free-form string,Changes
apps/backend/src/routes/connect.tsupsertlogic to use the dedicated follow token keyapps/backend/src/routes/follow.tsapps/backend/src/routes/auth.tsBackward Compatibility
The updated structure also creates a clean pattern for future scope-specific OAuth integrations:
{platform}_{purpose}Tests
Added comprehensive regression coverage in:
Coverage includes:
Result
Fixes #225