fix(security): remove GitHub access token from client session#2300
fix(security): remove GitHub access token from client session#2300VIDYANKSHINI wants to merge 4 commits into
Conversation
|
@VIDYANKSHINI is attempting to deploy a commit to the PRIYANSHU DOSHI's projects Team on Vercel. A member of the Team first needs to authorize it. |
GSSoC Label Checklist 🏷️@Priyanshu-byte-coder — please apply the appropriate labels before merging: Difficulty (pick one):
Quality (optional):
Validation (required to score):
|
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR centralizes server-side session retrieval to include the NextAuth access token (without adding it to the standard session callback), and updates pages/routes to use the new helper.
Changes:
- Added
getServerAuthSession()to fetch the session and (optionally) injectaccessTokenserver-side by decoding the session cookie. - Removed
accessTokeninjection from the NextAuthsessioncallback. - Replaced
getServerSession(authOptions)calls across app pages and API routes withgetServerAuthSession().
Reviewed changes
Copilot reviewed 88 out of 88 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/lib/server-auth.ts | New helper to fetch server session and inject accessToken by decoding the session cookie. |
| src/lib/auth.ts | Stops adding accessToken to the NextAuth session callback. |
| src/app/page.tsx | Uses getServerAuthSession() for auth gating / redirects. |
| src/app/dashboard/page.tsx | Uses getServerAuthSession() for auth gating / redirects. |
| src/app/dashboard/career-intelligence/page.tsx | Uses getServerAuthSession() for auth gating / redirects. |
| src/app/dashboard/repo-health/page.tsx | Uses getServerAuthSession() for auth gating / redirects. |
| src/app/project-tutor/page.tsx | Uses getServerAuthSession() for auth gating / redirects. |
| src/app/rooms/page.tsx | Uses getServerAuthSession() for auth gating / redirects. |
| src/app/rooms/[roomId]/page.tsx | Uses getServerAuthSession() for auth gating / redirects. |
| src/app/u/[username]/page.tsx | Uses getServerAuthSession() for auth gating / redirects. |
| src/app/wrapped/page.tsx | Uses getServerAuthSession() for auth gating / redirects. |
| src/app/api/ai-insights/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/ai/weekly-summary/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/auth/link-github/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/auth/link-github/callback/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/cv/analyze/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/cv/export/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/cv/generate/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/daily-focus/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/daily-note/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/debug/health/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/goals/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/goals/[id]/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/goals/history/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/goals/sync/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/integrations/jira/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/integrations/jira/credentials/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/local-coding/keys/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/local-coding/stats/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/activity/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/achievement-progress/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/achievements/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/ci/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/coding-activity-insights/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/commit-times/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/community-engagement/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/compare/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/consistency-score/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/contributions/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/contributions/daily/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/contributions/hourly/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/devtrack-badges/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/discussions/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/inactive-repos/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/issues/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/languages/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/pinned-repos/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/pr-breakdown/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/pr-review-time/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/prs/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/productive-hours/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/repo-analytics/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/repo-explorer/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/repo-health/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/repos/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/repos/[owner]/[name]/commits/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/streak/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/metrics/weekly-summary/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/notifications/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/notifications/[id]/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/project-tutor/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/rooms/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/rooms/[roomId]/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/rooms/[roomId]/invite/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/rooms/[roomId]/members/[username]/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/rooms/[roomId]/messages/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/stream/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/streak/freeze/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/user/dashboard-layout/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/user/data-export/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/user/export/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/user/github-accounts/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/user/github-accounts/[githubId]/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/user/github-orgs/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/user/orgs/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/user/pinned-repos/details/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/user/settings/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/user/settings/discord-test/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/users/search/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/wakatime/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/webhooks/custom/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/webhooks/custom/[id]/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/webhooks/custom/[id]/rotate-secret/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/webhooks/custom/[id]/test/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/webhooks/custom/[id]/deliveries/[deliveryId]/retry/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/webhooks/dispatch/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/webhooks/dispatch/metrics/route.ts | Uses getServerAuthSession() for API authentication. |
| src/app/api/wrapped/route.ts | Uses getServerAuthSession() for API authentication. |
Comments suppressed due to low confidence (3)
src/lib/server-auth.ts:1
- Hard-coding the session cookie name based on
NODE_ENV(and a Playwright flag) does not match NextAuth’s actual secure-cookie logic and ignores anyauthOptions.cookies.sessionToken.nameoverrides. This can causetokenCookieto be missed (e.g., HTTPS dev/preview environments, custom cookie prefixes), makingaccessTokenundefined and leading to widespread 401s. Prefer deriving the cookie name from NextAuth config (e.g.,authOptions.cookies?.sessionToken?.nameandauthOptions.useSecureCookies) or using a NextAuth helper designed to read/decode the token so cookie naming stays in sync with NextAuth.
src/lib/server-auth.ts:1 cookies()fromnext/headersis synchronous in the App Router;await cookies()is redundant and makes the intent less clear. Call it withoutawait.
src/app/wrapped/page.tsx:1- After switching to
getServerAuthSession()(which importsauthOptionsinternally),authOptionsis likely no longer needed in this file. If it isn’t referenced elsewhere in the file, remove the import to avoid unused-import lint/build failures.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
This PR has merge conflicts with the current git fetch origin main
git merge origin/main
# resolve conflicts
git push |
|
This PR has merge conflicts with |
|
CI is failing on this PR. Please fix the TypeScript/test errors before we can merge. Run |
|
Closing — duplicate of #2875 (same security fix). Also includes a |
Summary
This PR resolves a critical security vulnerability where the highly privileged GitHub OAuth access token was being exposed to the client-side session in plaintext. The token is now securely maintained entirely on the server-side, mitigating the risk of token exfiltration via XSS or malicious frontend dependencies.
Closes #2299
Type of Change
What Changed
src/lib/auth.ts: Removedsession.accessToken = token.accessTokenfrom the NextAuthsessioncallback to ensure the token is stripped from the payload sent to the browser.src/lib/server-auth.ts: Created a new server-side helper functiongetServerAuthSession(). It securely reads the raw JWT cookie (next-auth.session-token) usingnext/headersand decodes theaccessTokendirectly on the backend.src/app/api/...: Performed a global automated refactor across ~86 API routes to replacegetServerSession(authOptions)with the newgetServerAuthSession()wrapper. This guarantees all backend features (metrics, integrations, syncs) retain authenticated GitHub access without compromising the frontend.How to Test
npm run dev).await fetch('/api/auth/session').then(res => res.json())in the console.accessTokenis undefined or missing from the returned object.Expected result: The application works flawlessly, but the client session no longer contains the plaintext GitHub access token.
Screenshots / Recordings
N/A (Backend / Security Architecture change)
Checklist
console.log, debug code, or commented-out blocksnpm run lintpasses locallynpm run type-check)Accessibility (UI changes only)
N/A
Additional Context
Because this refactor modifies how
getServerSessionworks globally within API routes, extensive care was taken to ensure TypeScript typings remain valid. The newgetServerAuthSessionstrictly handles parsing standard NextAuth JWT cookies dynamically based on the active environment (PLAYWRIGHT_SERVER_MODE,production__Secure-prefixes, etc.) to ensure E2E tests still pass alongside production deployments.