Auth.js v5 signup and login, cookie bridge to Express backend

juanjo replaces Supabase Auth with Auth.js v5 on the Next.js frontend and wires the resulting session cookie into the Express backend. The backend's auth middleware is ~50 lines; there's a hard-coded salt bug that will break HTTPS deployments until fixed.

infrastructuresecurity

The frontend half (20ea4b2) installs next-auth@5, @auth/drizzle-adapter, and bcryptjs. frontend/src/auth.ts configures a Credentials provider that bcrypt-verifies against the local users table via Drizzle. A new /api/signup route creates user and user_profiles rows in a single transaction. AuthContext.tsx is rewritten on top of useSession().

Two tightening commits follow: the signup form's minimum password length was 6 in the UI but 8 on the server - that gets aligned (1ab63b7). Then a follow-up (2d8ee13) adds a 72-character maximum (the bcrypt truncation limit), a unique-constraint race backstop (23505 Postgres code caught in a try/catch), and pipes organisation through to the user_profiles insert.

The bridge commit (7baab52) is the technically interesting piece. backend/src/middleware/auth.ts drops the Authorization: Bearer pattern entirely. Instead it reads the authjs.session-token cookie (or __Secure-authjs.session-token in production), decodes it with next-auth/jwt's decode() using the shared AUTH_SECRET, and extracts sub and email from the JWT payload. frontend/next.config.ts adds a /api/backend/:path* rewrite so the browser sends the cookie automatically on every backend call. mikeApi.ts switches to relative URLs and credentials: "include".

There is a documented bug (9e99b3a): the decode() salt is hard-coded to the dev cookie name (authjs.session-token), so the production __Secure- variant will fail to decode. The comment says to fix this before deploying to HTTPS; it's not fixed in this branch. Anyone copying backend/src/middleware/auth.ts needs to handle both cookie name variants.

The user-profile route (c7d112e) migrates /user/me, /user/profile, and /user/account to Drizzle as the first end-to-end demo of the full stack.

So what Worth a look if you want a cookie-bridge pattern for decoding Auth.js JWTs in a non-Next.js service using a shared secret. `backend/src/middleware/auth.ts` is the artifact - ~50 lines, easy to port. Fix the hard-coded salt before any HTTPS deployment.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

7 commits from juanjo/mike, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
20ea4b25 feat(frontend): wire Auth.js + Drizzle (signup, login, session provider) Juan Vidal 2026-05-08 ↗ GitHub
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1ab63b75 fix(frontend): align signup min-length with server (6→8) Juan Vidal 2026-05-08 ↗ GitHub
2d8ee13b fix(signup): max-length cap + unique-race backstop + wire org/name to profile Juan Vidal 2026-05-08 ↗ GitHub
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7baab523 feat: cookie-based auth bridge between Auth.js and Express Juan Vidal 2026-05-08 ↗ GitHub
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
9e99b3ac chore(backend): document salt hard-coding in auth middleware Juan Vidal 2026-05-08 ↗ GitHub
c7d112e2 feat(backend): migrate user-profile route to Drizzle (vertical slice) Juan Vidal 2026-05-08 ↗ GitHub
Adds GET /user/me; ports POST /user/profile and DELETE /user/account from
supabase-js to Drizzle. Cookie-based requireAuth still gates all three.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
d2a95f5f docs(serena): update memories for local-Postgres + Auth.js stack (Plan 1) Juan Vidal 2026-05-08 ↗ GitHub

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-181.md from inside the repo you want the changes in.

⬇ Download capture-thread-181.md