Skip to content

Cookie-based session model, admin role gate and 401 handling - #2049

Merged
yusuftomilola merged 1 commit into
DistinctCodes:mainfrom
ykargeee-bit:feature/auth-session-hardening
Oct 18, 2026
Merged

yusuftomilola merged 1 commit into
DistinctCodes:mainfrom
ykargeee-bit:feature/auth-session-hardening

Conversation

@ykargeee-bit

Copy link
Copy Markdown
Contributor

Summary

Implements the auth session hardening assigned to ykargeee-bit:

Backend changes

Limited to the new GET /auth/me endpoint (reads the guarded request user). Login/register/logout are untouched.

Test updates

  • auth-form.test.tsx — setSession, role "user"
  • payments-api.test.ts / credits-api.test.ts / wallet-api.test.ts — removed Bearer/Authorization assertions (no client-side bearer); wallet credentials expectation moved to include
  • payment-return-page.test.tsx — user/status mock + bootstrap mock
  • require-admin.test.tsx — rewritten for the role-based gate
  • New: session-expiry.test.ts, auth-api.test.ts, api-401.test.ts, middleware.test.ts, app/payments/__tests__/page.test.tsx

Merge coordination

Closes #1975
Closes #1977
Closes #1974
Closes #1973

…e-bit)

- Adopt the backend's HttpOnly accessToken cookie as the single session
  store: every fetch sends credentials: "include", the js-cookie mirror and
  all bearer-header/token threading are removed from the client, and the
  session store keeps only the in-memory copy of the login token plus the
  user (Closes DistinctCodes#1975)
- Add GET /auth/me (backend) and useSessionBootstrap so a reload restores
  who is signed in without reading cookies from JavaScript, fixing the
  hydration-mismatch class of bugs at the source
- Gate /admin routes by role: middleware decodes the verified admin claim
  and redirects members to a new /admin/forbidden page; RequireAdmin is
  rewritten as a session-driven client backstop with a not-authorised
  state (Closes DistinctCodes#1973)
- React to rejected sessions centrally: expireSession() clears the store,
  toasts once and redirects to /login?returnTo=... with loop protection,
  wired into every *-api helper (Closes DistinctCodes#1977)
- Add logout() (POST /auth/logout with credentials), a shared useSignOut
  hook and a UserMenu on wallet, payments, usage, credits and admin
  headers so sign-out reaches the backend everywhere (Closes DistinctCodes#1974)

Notes for reviewers:
- Backend change is limited to the new GET /auth/me endpoint reading the
  guarded request user; login/register/logout are untouched.
- The api modules' tests keep the same behavior coverage: the "Bearer"
  header assertions were dropped (no client-side bearer) and the wallet
  credentials expectation moved from same-origin to include.
- Keep an eye on merge order with DistinctCodes#1976 (shared lib/http.ts by
  devrabiuhussain): both PRs touch the five *-api modules and their
  callers. DistinctCodes#1976 keeps an optional accessToken param for compatibility;
  this PR removes the parameter and headers entirely, so resolve in favor
  of this one's cookie session semantics.
- The query-client side of the 401 reaction (skip retries for 401/403)
  lands with the providers consolidation in DistinctCodes#1980 to avoid both PRs
  editing the same provider files.
@vercel

vercel Bot commented Oct 17, 2026

Copy link
Copy Markdown

@ykargeee-bit is attempting to deploy a commit to the naijabuz's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Oct 17, 2026

Copy link
Copy Markdown

@ykargeee-bit Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@yusuftomilola
yusuftomilola merged commit f79eb26 into DistinctCodes:main Oct 18, 2026
1 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment