Skip to content

Auth — session helpers + error page #498

Description

@adityapat24

Context

Last sprint shipped auth routing, admin/user redirects, logout, and magic-link email delivery. What's left is the reusable session helpers every other endpoint needs, plus the friendly error page.

Tasks

Session helpers

  • Implement getSession() in src/lib/auth/session.ts that returns the typed Session (email, isAdmin) or null. Use NextAuth's getServerSession under the hood.
    • What this accomplishes: Any server component or route handler can call one function to know who's signed in. Encapsulates the NextAuth API so if it changes, only one file needs updating.
  • Implement requireUser() in src/lib/auth/guards.ts. Calls getSession(), returns the user if present, throws a typed error if not. The error should be catchable by route handlers and convertible to a 401 response.
    • What this accomplishes: One line at the top of any protected route handler enforces authentication. This is the helper every other ticket is waiting for.
  • Implement requireAdmin() in the same file. Calls requireUser(), then throws if the email doesn't end with @hackbeanpot.com. Converts to a 403 response in route handlers.
    • What this accomplishes: Same pattern for admin-only routes. Domain-based admin check keeps the rule dead simple.
  • Wire requireUser() into src/app/api/v1/user/route.ts (currently probably returns mock or unguarded data).
    • What this accomplishes: The endpoint the frontend uses to fetch the current user now actually returns real session data and correctly 401s when unauthed.

Session lifecycle

  • Confirm the logout flow (already shipped) actually invalidates the session in Mongo, not just the client cookie. Check the sessions collection after a logout to confirm the row is deleted.
    • What this accomplishes: Prevents the security bug where a "logged out" user's session token, if intercepted, would still be valid. Session invalidation on the server matters.
  • Confirm sessions have a reasonable expiration (e.g., 30 days). Set via NextAuth config session.maxAge if not already set.
    • What this accomplishes: Long-lived sessions mean users don't have to sign in every visit, but not so long that a stolen cookie is a lifetime problem.

Error page

  • src/app/auth/error/page.tsx reads the error query param and displays a specific message for each NextAuth error code (Verification = expired/reused link, EmailSignin = SMTP failure, AccessDenied = admin-only route, etc.). Include a "back to sign-in" link.
    • What this accomplishes: Users who hit an error (expired link, bad SMTP, etc.) see something useful instead of a cryptic code. Reduces support burden during application season.

Documentation

  • Add comments to getSession, requireUser, requireAdmin documenting return types, exceptions thrown, and one-line usage examples.
    • What this accomplishes: Every other ticket owner about to wire these in doesn't need to read the source or ping you to understand how they work.

Definition of done

  • getSession(), requireUser(), and requireAdmin() are exported and usable by any ticket.
  • The /api/v1/user endpoint uses requireUser() and returns the real session user.
  • Logout invalidates the session server-side (verified by checking the sessions collection).
  • The error page shows friendly messages for each error code.
  • Helpers are documented with comments.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions