next-auth icon indicating copy to clipboard operation
next-auth copied to clipboard

Magic Link works locally and throws Error: EmailSignin in prod

Open kevinggrimm opened this issue 3 years ago • 0 comments

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

kevinggrimm avatar Aug 07 '22 00:08 kevinggrimm