Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NextAuth.js - Check if email is exist in database before sign with GoogleProvider

I am using NextAuth.js for authentication and MongoDB to save the user information.

When the user registers with email & password, it saves to MongoDB.

If this user login with a Google account that has the same email address, it returns Error: Action login with HTTP GET is not supported by NextAuth.js

If the Google email address does not exist in the DB, then it works okay.

How do I check if the email address exists in the DB before login into the website by using GoogleProvider?

import { MongoDBAdapter } from '@next-auth/mongodb-adapter';
import clientPromise from '../../../lib/mongodb';
import CredentialsProvider from 'next-auth/providers/credentials';
import GoogleProvider from 'next-auth/providers/google';
import { verifyPassword } from '../../../lib/auth';
import { connectToDatabase } from '../../../lib/db';
const { parseCookies } = require('nookies');

export default async function auth(req, res) {
    const cookies = parseCookies({ req });
    const maxAge =
        cookies.remember === 'true' ? 30 * 24 * 60 * 60 : 1 * 24 * 60 * 60; // 30 days, 1 day

    return await NextAuth(req, res, {
        providers: [
            CredentialsProvider({
                async authorize(credentials) {
                    const client = await connectToDatabase();
                    const usersCollection = await client.db().collection('users');
                    const result = await usersCollection.findOne({
                        email: credentials.email,
                    });

                    if (!result) {
                        client.close();
                        throw new Error('No user found!');
                    }

                    const isValid = await verifyPassword(
                        credentials.password,
                        result.password
                    );

                    if (!isValid) {
                        client.close();

                        throw new Error('Could not log you in!');
                    }

                    client.close();
                    const user = {
                        id: result._id,
                        email: result.email,
                        name: result.name,
                        role: result.role,
                        remember: credentials.remember,
                    };

                    return user;
                },
            }),

            GoogleProvider({
                clientId: process.env.GOOGLE_ID,
                clientSecret: process.env.GOOGLE_SECRET,
            }),
        ],

        adapter: MongoDBAdapter(clientPromise),
        callbacks: {
            // called after sucessful signin
            jwt: async ({ token, user }) => {
                user && (token.user = user);
                return token;
            }, // called whenever session is checked
            session: async (data) => {
                const { session, token } = data;
                session.user = token.user;
                return session;
            },
        },
        secret: process.env.SECRET_KEY,
        session: {
            strategy: 'jwt',
            maxAge: maxAge,
        },
        jwt: {
            secret: process.env.SECRET_KEY,
            encryption: true,
        },
        pages: {
            signIn: './login',
        },
    });
}
like image 348
Brandon Han Avatar asked Oct 26 '25 05:10

Brandon Han


1 Answers

You can use the SignIn callback to control if a user is allowed to sign in https://next-auth.js.org/configuration/callbacks#sign-in-callback

callbacks: {
  async signIn({ user, account, profile, email, credentials }) {
    if(account.provider === 'google') {
        
      //check the user on your database and return true if is allowed to signIn
      const isAllowedToSignIn = true
        
      if (isAllowedToSignIn) {
        return true
      } else {
        // Return false to display a default error message
        return false
        // Or you can return a URL to redirect to:
        // return '/unauthorized'
      }
    }
  }
}
like image 178
Gustavo Rivero Avatar answered Oct 29 '25 08:10

Gustavo Rivero