I am working on a simple app with Auth.js and Next.js. In specific, I am using it with WebAuthn authentication.
So, I have a pretty similar auth.ts
setup:
export const { handlers, signIn, signOut, auth } = NextAuth({
basePath: "/auth",
experimental: { enableWebAuthn: true },
session: {
strategy: "jwt",
},
adapter: DrizzleAdapter(db, {
usersTable: schema.users,
sessionsTable: schema.sessions,
verificationTokensTable: schema.verificationTokens,
accountsTable: schema.accounts,
authenticatorsTable: schema.authenticators,
}),
providers: [
Passkey,
]
});
And then I have a pretty similar frontend (signin-button.tsx
):
import { signIn } from "@/lib/auth";
export function SignIn() {
return (
<form
action={async () => {
"use server";
await signIn();
}}
>
<button
type="submit"
>
Sign in
</button>
</form>
);
}
- When I run my app locally, everything works perfectly.
- When I run my app on Vercel, everything works perfectly.
- When I run my app on Cloudflare, I can't Sign In.
I have done some debugging, but cannot understand why still.
When the UI calls the POST /auth/callback/passkey
endpoint, the following Response header is returned:
__Secure-authjs.challenge=; Max-Age=0; Path=/; HttpOnly; Secure; SameSite=Lax, __Secure-authjs.session-token=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwia2lkIjoibFZWQkpCOFhRbUZPTFBDbElkNVZpTFdhY0JyVUl0emRVTVg1b1FEdGZkeERpVVlabXhUUjlfdzFxeE9paUlSbUFVZ01RdTU4SVZGMEZVVHplOXhvdmcifQ..3P1NvZbR8CXT-Xa7qKwCuQ.uKAx8IfKPPeAUZXc1W4sJCfWC2gAAEdZpSHvr_eV1XrlJnxUKRlsgBi67kXheLsB-cy7ljM44sccynCPtObQlvRvn5fZiqo4Chi_1UU8Em57KUA5m_vJVQ2jeN8H6dlqvfBQoq7U89qCfT11SkKtEzfQDLtlyD2dalEfUUVvB_yv4fgoVD4_NAy4lYz6MJOHNi8W71II6l7U5TsIIVAsuTjtkdntWUVyTGo4sZF8wLWp0SvFtAYH40s7fkvtLFJX.UQ8wANChM2gk-8SyAzqCANM1G3FF5YSAoNN1wK5Dk0w; Path=/; Expires=Tue, 06 Aug 2024 17:16:55 GMT; HttpOnly; Secure; SameSite=Lax
But then, when I look at the Cookies tab for that network request, the __Secure-authjs.session-token
cookie is not included in the "Response Cookies":
Compared to Vercel, where it is included for the same network request:
We can also compare the network requests themselves (first Cloudflare, then Vercel):
There are a few interesting differences:
- Vercel splits up the
Set-Cookie
response headers into two - Vercel always sends
Strict-Transport-Security
asmax-age=63072000; includeSubDomains; preload
However, I cannot understand why the response cookie would work for the exact same app hosted on Vercel, but not on Cloudflare Pages/Workers.