Repository navigation
fix(core): keep ephemeral tokens out of cookie-transport bodies - #206
Merged
Merged
Conversation
Under cookie transport the OTP send routes returned the ephemeral token the auth API re-mints on every send, and registration returned the token it had just stored in the registration cookie. Page scripts could read both, which is what the httpOnly cookie exists to prevent. Both now drop token and refreshToken from the body in cookie transport, through one helper the manifest proxy also uses. requestOtpHandler takes a transport option, which every adapter passes; without it the token is dropped. Bearer transport is unchanged. Closes #202.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #202.
Why
Under cookie transport the adapter keeps every auth token in an httpOnly cookie so page scripts never see one. Two flows broke that by returning the upstream body unchanged:
POST /otp/generate-email-otp,/otp/generate-phone-otp,/otp/generate-login-email-otpand/otp/generate-login-phone-otpreturned the ephemeral token the auth API re-mints on every send.POST /registration/registerstored the registration token in its cookie and also returned it in the body.Any script on the adopter's origin could read those tokens, and so could anything that captures bodies (devtools exports, APM payload capture, service workers, proxy logs). They are pre-auth tokens, not sessions, so the impact is limited, but it breaks the guarantee the cookie is there to give.
What changes
withoutTokensin core removes top-leveltokenandrefreshToken. The manifest proxy from feat(core): serve auth API routes from the adapter manifest #203 now uses it too, so both paths strip the same way.registerHandler. Strips the body in cookie transport.requestOtpHandler. Takes an optionaltransportand strips unless it isbearer. Express, Fastify and Next.js all pass it. A caller that omits it gets the safe default.delivery.token(the OTP code) is nested, so it is left forapplyExternalDeliveryto send and strip as before.I checked the auth API: these are the only flows that return a token through an adapter's unchanged-body path. Magic-link request and verify, the OAuth start routes, and the admin, session and system-config passthroughs return no
token.Downstream
Nothing reads these tokens through an adapter's cookie transport:
@seamless-auth/clientreads no body tokens in cookie mode. In bearer mode it reads them from register, which still returns them.Checks
pnpm test: core 401, express 210, fastify 156, nextjs 165, all passing.pnpm check:types-currentpasses.Patch changeset for all four packages.