🐛 Fix magic link consumed before user gets it (#909)

* 🐛 Fix magic link consumed before user gets it

* Improve abstraction

* Remove extra comment
This commit is contained in:
Luke Vella 2023-10-23 18:54:39 +01:00 committed by GitHub
parent ac1d844b7a
commit d95d648012
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 2 deletions

View file

@ -1,4 +1,3 @@
import { PrismaAdapter } from "@auth/prisma-adapter";
import { RegistrationTokenPayload } from "@rallly/backend";
import { decryptToken } from "@rallly/backend/session";
import { generateOtp, randomid } from "@rallly/backend/utils/nanoid";
@ -17,13 +16,14 @@ import NextAuth, {
import CredentialsProvider from "next-auth/providers/credentials";
import EmailProvider from "next-auth/providers/email";
import { CustomPrismaAdapter } from "@/utils/auth/custom-prisma-adapter";
import { LegacyTokenProvider } from "@/utils/auth/legacy-token-provider";
import { mergeGuestsIntoUser } from "@/utils/auth/merge-user";
import { emailClient } from "@/utils/emails";
const getAuthOptions = (...args: GetServerSessionParams) =>
({
adapter: PrismaAdapter(prisma),
adapter: CustomPrismaAdapter(prisma),
secret: process.env.SECRET_PASSWORD,
session: {
strategy: "jwt",

View file

@ -0,0 +1,38 @@
import { PrismaAdapter } from "@auth/prisma-adapter";
import { Prisma, PrismaClient } from "@prisma/client";
import { Adapter } from "next-auth/adapters";
export function CustomPrismaAdapter(prisma: PrismaClient): Adapter {
const adapter = PrismaAdapter(prisma);
return {
...adapter,
// NOTE: Some users have inboxes with spam filters that check all links before they are delivered.
// This means the verification link will be used before the user gets it. To get around this, we
// avoid deleting the verification token when it is used. Instead we delete all verification tokens
// for an email address when a new verification token is created.
async createVerificationToken(data) {
await prisma.verificationToken.deleteMany({
where: { identifier: data.identifier },
});
const verificationToken = await prisma.verificationToken.create({
data,
});
return verificationToken;
},
async useVerificationToken(identifier_token) {
try {
const verificationToken = await prisma.verificationToken.findUnique({
where: { identifier_token },
});
return verificationToken;
} catch (error) {
// https://www.prisma.io/docs/reference/api-reference/error-reference#p2025
if ((error as Prisma.PrismaClientKnownRequestError).code === "P2025")
return null;
throw error;
}
},
};
}