next-auth
next-auth copied to clipboard
Magic Link works locally and throws Error: EmailSignin in prod
Question 💬
I have logic in the signIn callback that is supposed to only send emails to the whitelisted email addresses. This works totally fine in a local environment but throws an Error: EmailSignin non-local.
This is deployed on AWS, and I have a NEXTAUTH_URL defined within my .env file.
Adding relevant code for [...nextauth].js and the sign-in page below.
How to reproduce ☕️
// pages/auth/signin.js
import { signIn } from 'next-auth/react';
// ... more code
const handleSignIn = async e => {
e.preventDefault();
try {
const { error, ok, url, status } = await signIn("email", {
email,
redirect: false,
callbackUrl: `https://MySiteURL/auth/confirm-request`,
});
if (error) {
throw new Error(error);
}
setError(null);
setShowModal(true);
} catch (error) {
console.log('Unable to sign-in: ', error)
setError(error);
}
}
// [...nextauth].js
import NextAuth from 'next-auth';
import EmailProvider from 'next-auth/providers/email';
import nodemailer from 'nodemailer';
import Handlebars from 'handlebars';
import { DynamoDB } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb";
import { DynamoDBAdapter } from "@next-auth/dynamodb-adapter";
import { readFileSync } from 'fs';
import path from 'path';
const transporter = nodemailer.createTransport({
host: process.env.EMAIL_SERVER_HOST,
port: process.env.EMAIL_SERVER_PORT,
auth: {
user: process.env.EMAIL_SERVER_USER,
pass: process.env.EMAIL_SERVER_PASSWORD,
},
tls: {
ciphers: 'SSLv3'
}
});
const emailsDir = path.resolve(process.cwd(), 'src', 'emails');
const sendVerificationRequest = ({
identifier,
url
}) => {
console.log('Sending verification request....')
const emailFile = readFileSync(path.join(emailsDir, 'confirm-email.html'), {
encoding: 'utf-8',
});
const emailTemplate = Handlebars.compile(emailFile);
try {
console.log('Sending email...')
transporter.sendMail({
from: `${process.env.EMAIL_FROM}`,
to: identifier,
subject: 'Your sign-in link',
html: emailTemplate({
signin_url: url,
email: identifier,
}),
});
} catch (error) {
console.log('Could not send email: ', error)
}
};
const config = {
credentials: {
accessKeyId: process.env.NEXTAUTH_AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.NEXTAUTH_AWS_SECRET_ACCESS_KEY,
},
region: process.env.NEXTAUTH_AWS_REGION,
};
const client = DynamoDBDocument.from(new DynamoDB(config), {
marshallOptions: {
convertEmptyValues: true,
removeUndefinedValues: true,
convertClassInstanceToMap: true,
},
})
const dynamoDbAdapter = DynamoDBAdapter(client, {
tableName: "my-table-name",
});
export const authOptions = {
providers: [
EmailProvider({
maxAge: 15*60,
sendVerificationRequest,
}),
],
session: {
strategy: "database",
maxAge: 30*60*60*24,
updateAge: 10*60*60*24
},
secret: "mySuperSecretSecret",
adapter: dynamoDbAdapter,
pages: {
signIn: '/auth/signin',
signOut: '/',
},
callbacks: {
async signIn({ user, account, profile, email, credentials }) {
const verificationRequest = email.verificationRequest;
if (verificationRequest) {
const EMAIL_WHITELIST = ["whitelisted_email.hotmail.com"];
const { email: emailAddress } = user;
if (!EMAIL_WHITELIST.includes(emailAddress)) {
console.log("Invalid email address - not allowed to sign in");
return false;
}
}
return true;
},
},
debug: true,
}
export default NextAuth({...authOptions})
This is my first time using NextAuth, so I am going to air on the side of caution and predict that I'm overlooking something.
Contributing 🙌🏽
No, I am afraid I cannot help regarding this