vuesion/vuesion

View on GitHub
src/server/api/auth/[...].ts

Summary

Maintainability
A
0 mins
Test Coverage
import { compare } from 'bcrypt';
import CredentialsProvider from 'next-auth/providers/credentials';
import { PrismaClient } from '@prisma/client';
import { NuxtAuthHandler } from '#auth';

const prisma = new PrismaClient();

export const comparePasswords = (plainPassword: string, hashedPassword: string): Promise<boolean> => {
  return new Promise((resolve, reject) => {
    compare(plainPassword, hashedPassword, function (err, isPasswordMatch) {
      if (err) {
        reject(err);
      } else {
        resolve(isPasswordMatch);
      }
    });
  });
};

export default NuxtAuthHandler({
  // secret needed to run nuxt-auth in production mode (used to encrypt data)
  secret: process.env.NUXT_AUTH_SECRET,
  pages: {
    signIn: '/',
  },
  session: {
    strategy: 'jwt',
    maxAge: 30 * 24 * 60 * 60, // 30 days
    updateAge: 24 * 60 * 60, // 24 hours
  },
  callbacks: {
    jwt({ token, user }) {
      if (user) {
        token.id = user.id;
      }

      return token;
    },
    session({ session, token }) {
      if (token && session.user) {
        session.user.id = token.id as string;
      }

      return session;
    },
  },
  providers: [
    // @ts-ignore Import is exported on .default during SSR, so we need to call it this way. May be fixed via Vite at some point
    CredentialsProvider.default({
      async authorize(credentials: any) {
        const email = credentials.email;
        const password = credentials.password;
        const accountRecord = await prisma.account.findUnique({ where: { email } });

        if (accountRecord === null) {
          return null;
        }

        const isMatchingPassword = await comparePasswords(password, accountRecord?.password);

        accountRecord.password = '';

        if (isMatchingPassword) {
          return accountRecord;
        } else {
          return null;
        }
      },
    }),
  ],
});