Duplicate requests causing verification token to be invalidated #7363
-
A user is attempting to log in via email (passwordless), and the login email is successfully delivered to them. When they click the login link in that email, I'm seeing two separate requests to The first request succeeds, which logs the user in. But that request uses the verification token from the email, which invalidates it, and so the second request to the same URL fails. The user ends up being redirected back to the login page, with Any ideas for a workaround here? My temporary fix is to allow the verification token to be used an unlimited amount of times before its expiry, though that's not the most secure solution. Separately, any ideas for why these duplicate requests are happening? I'm guessing it has to do with VPN routing. Edit: If you want to allow the verification token to be reused, you can override For example, for the Prisma adapter, write this in your NextAuth.js options: import { PrismaAdapter } from '@next-auth/prisma-adapter'
import type { NextAuthOptions } from 'next-auth'
import remeda from 'remeda'
import prisma from '~/prisma/client.ts'
const nextAuthOptions: NextAuthOptions = {
adapter: {
...PrismaAdapter(prisma),
async useVerificationToken({ identifier, token }) {
const verificationToken = await prisma.verificationToken.findFirst({
where: { identifier, token },
})
if (!verificationToken) {
return null
}
return remeda.omit(verificationToken, ['id'])
},
},
...
} |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
I am seeing something similar here as well |
Beta Was this translation helpful? Give feedback.
-
Sharing a DynamoDB version for the adapter: {
...DynamoDBAdapter(
client,
{
tableName: process.env.NEXT_AUTH_AWS_DDB_TABLE_NAME
}
),
async useVerificationToken({ identifier, token }) {
const TableName = process.env.NEXT_AUTH_AWS_DDB_TABLE_NAME ?? "next-auth";
const data = await client.get({
TableName,
Key: {
["pk"]: `VT#${identifier}`,
["sk"]: `VT#${token}`,
}
})
return format.from<VerificationToken>(data.Item)
},
}, |
Beta Was this translation helpful? Give feedback.
We are sending the user to a page that redirects the user to the magic link after a settimeout. This mitigates the need to create a token with no expiration date. This option should probably be built into next-auth.
You create a page like the one we have
/auth/magiclink?redirect=
with theredirect
param set to the actual magic link. Then in your page you decide what logic you want to use. You can force the user to click a button, do an auto redirection after a set timeout, or both. You probably also want to check to make sure you're not creating an open redirect vulnerability in your redirection page.