Skip to content

fix(fastify): read the session cookie on routes outside the plugin - #209

Merged
Bccorb merged 1 commit into
mainfrom
fix/fastify-require-auth-cookie
Oct 8, 2026
Merged

Bccorb merged 1 commit into
mainfrom
fix/fastify-require-auth-cookie

Conversation

@Bccorb

@Bccorb Bccorb commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Closes #207.

Why

The README offers requireAuth (and getSeamlessUser) for an application's own routes, with app.get("/api/me", { preHandler: requireAuth(...) }) as the example. With a cookie session that route answered 401.

The plugin registers @fastify/cookie inside its own encapsulated scope, so request.cookies exists only on the plugin's routes. Two things went wrong elsewhere:

  • requireAuth read req.cookies?.[cookieName], found nothing, and refused.
  • getSeamlessUser found no session either.

Bearer tokens worked, which hid the problem from native clients. An adopter could not register @fastify/cookie at the root to work around it, because the plugin registers it again and the two collide.

This was found by the new adapter conformance suite (fells-code/seamless-cli#246). The Express reference app passed GET /api/me with a cookie session; the Fastify one answered 401.

What changes

  • requestCookies (Fastify, internal). Returns request.cookies when a cookie plugin parsed them, and otherwise parses the Cookie header with @fastify/cookie's own parse. requireAuth and getSeamlessUser use it.
  • getSeamlessUser (core). When the caller supplies no authorization, it now sends the access token from the verified cookie.
    • Before this, outside the adapter's own routes the cookie verified but the request reached the auth API with no token, because nothing had loaded the cookie payload.
    • The Express adapter benefits the same way.
    • A caller-supplied authorization still wins.

The cookie is still verified against cookieSecret before anything is read from it, and a forged cookie is still refused.

Checks

  • pnpm test: core 403, express 210, fastify 160, nextjs 165, all passing.
  • New tests:
    • Fastify: requireAuth on a root route next to the plugin accepts a cookie session, refuses a forged cookie, and refuses a request with no Cookie header. getSeamlessUser reads the cookie from the header.
    • Core: the token from the verified cookie is sent when no authorization is given, and a caller's authorization is preferred.
  • Adapter conformance suite (feat(verify): extract a language-agnostic adapter conformance suite seamless-cli#246) against the Express and Fastify reference apps built from this branch: 48 of 48, three runs in a row.

Patch changeset for core, express and fastify.

The plugin registers @fastify/cookie in its own encapsulated scope, so an
application route registered elsewhere has no request.cookies. requireAuth
refused every cookie session there and getSeamlessUser found none, though
the README offers both for exactly those routes. Both now parse the Cookie
header themselves when nothing else did.

getSeamlessUser in core also sends the token from the verified cookie when
the caller passes no authorization, which is the case on any route the
adapter's own hooks did not run on.

Closes #207.
@Bccorb
Bccorb merged commit 330c0fc into main Oct 8, 2026
4 checks passed
@Bccorb
Bccorb deleted the fix/fastify-require-auth-cookie branch October 15, 2026 03:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(fastify): requireAuth cannot read the session cookie on routes outside the plugin

1 participant