Skip to content

fix(auth): return structured token_expired 401 error and add auto-red… - #3261

Open
Nareshkumawat-star wants to merge 1 commit into
Priyanshu-byte-coder:mainfrom
Nareshkumawat-star:fix/github-oauth-token-expired-handling
Open

fix(auth): return structured token_expired 401 error and add auto-red…#3261
Nareshkumawat-star wants to merge 1 commit into
Priyanshu-byte-coder:mainfrom
Nareshkumawat-star:fix/github-oauth-token-expired-handling

Conversation

@Nareshkumawat-star

Copy link
Copy Markdown
Contributor

Summary

Gracefully handles expired or revoked GitHub OAuth tokens across API route handlers (/api/metrics/*) by returning structured 401 JSON responses ({ error: "token_expired" }). Dashboard components detect token expiration, display a "Session expired — please sign in again" banner, and auto-redirect to /api/auth/signin after 3 seconds.

Closes #3244


Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that changes existing behavior)
  • 📝 Documentation update
  • ♻️ Refactor / code cleanup (no functional change)
  • ⚡ Performance improvement
  • 🔒 Security fix
  • 🧪 Tests only

What Changed

  • src/lib/github-fetch.ts: Returns GitHubAuthError on HTTP 401 responses.
  • src/app/api/metrics/contributions/route.ts & src/app/api/metrics/prs/route.ts: Returns githubAuthErrorResponse() (HTTP 401 { error: "token_expired" }) when authentication is invalid or revoked.
  • src/components/ContributionGraph.tsx: Catches 401 token_expired errors, shows a session expiration banner, and auto-redirects to /api/auth/signin after 3 seconds.

How to Test

  1. Sign in to DevTrack.
  2. Revoke the DevTrack OAuth app token in GitHub Settings → Applications → Authorized OAuth Apps.
  3. Trigger a metric fetch or time-range change on the dashboard.
  4. Verify that the dashboard displays the "Your session expired — please sign in again" alert banner instead of freezing or throwing unhandled console errors.
  5. Verify auto-redirection to /api/auth/signin after 3 seconds.

Checklist

  • Self-reviewed my own diff
  • No unnecessary console.log or debug code
  • Structured 401 error response code verified
  • Auto-redirection user experience tested

@github-actions github-actions Bot added gssoc26 GSSoC 2026 contribution type:bug GSSoC type bonus: bug fix type:feature GSSoC type bonus: new feature type:security GSSoC type bonus: security (+20 pts) labels Jul 28, 2026
@github-actions

Copy link
Copy Markdown

GSSoC Label Checklist 🏷️

@Priyanshu-byte-coder — please apply the appropriate labels before merging:

Difficulty (pick one):

  • level:beginner — 20 pts
  • level:intermediate — 35 pts
  • level:advanced — 55 pts
  • level:critical — 80 pts

Quality (optional):

  • quality:clean — ×1.2 multiplier
  • quality:exceptional — ×1.5 multiplier

Validation (required to score):

  • gssoc:approved — counts for points
  • gssoc:invalid / gssoc:spam / gssoc:ai-slop — does not score

Type labels (type:*) are auto-detected from files and title. Review and adjust if needed.
Points formula: (difficulty × quality_multiplier) + type_bonus

@github-actions github-actions Bot added type:design GSSoC type bonus: UI/design (+10 pts) type:performance GSSoC type bonus: performance (+15 pts) labels Jul 28, 2026
@Nareshkumawat-star

Copy link
Copy Markdown
Contributor Author

Hi @Priyanshu-byte-coder kindly review and merge it

@Priyanshu-byte-coder

Copy link
Copy Markdown
Owner

Verified against current main: type-check clean, full suite 2383 passing, no regressions. The core of this is good and I want it in.

The best part is the github-fetch.ts change — having buildGitHubError return GitHubAuthError on 401 makes every caller's auth handling consistent instead of each route re-deriving it. That's the right fix in the right place.

Three things to resolve first.

1. The banner is unreadable in light themes. text-amber-300 (#fcd34d) on the amber-500/10 card measures 1.35:1. DevTrack ships several light themes and defaults to one, so on a default install the "Your session expired" message — the single message a user most needs to read — is close to invisible. On the dark card it's 12:1 and fine.

text-amber-700 dark:text-amber-300

gets you 4.71:1 on light and keeps the current dark appearance.

2. The 3-second auto-redirect. window.location.href = "/api/auth/signin" fires from inside a widget, so if another widget hits the same 401 you get competing redirects, and a hard navigation discards anything the user was in the middle of. You've already added a "Sign in now" button, which is the better interaction. I'd drop the timer and keep the button.

3. !session?.accessToken now returns token_expired. That branch also covers "never signed in", where telling someone their session expired is inaccurate. Worth keeping Unauthorized for the no-session case and reserving token_expired for a real 401 from GitHub — which the catch block now handles properly anyway.

Also: the client checks for errData.error === "Unauthorized" and treats it as expiry. If you make the change in (3), that check should go too.

Fix those and I'll merge it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gssoc26 GSSoC 2026 contribution type:bug GSSoC type bonus: bug fix type:design GSSoC type bonus: UI/design (+10 pts) type:feature GSSoC type bonus: new feature type:performance GSSoC type bonus: performance (+15 pts) type:security GSSoC type bonus: security (+20 pts)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Dashboard crashes with unhandled error when GitHub OAuth token expires mid-session

2 participants