I will go crazy if i keep getting the same error for one more day, as i’m literally stuck trying to fix that serverless function error on netlify ! It all works fine when running on development mode, but when i deploy on netlify and hitting the “signin” link on the navbar, it suddenly gives error as follows, im sure nothing is wrong with the logic both in frontend and backend. Asking netlify to increase timeout limit makes just no sense in my opinion because most users wont even wait for the page to load more than 4 seconds. All the other pages works perfectly and i cant really make sense of that, any help is wholeheartedly appreciated, thanks in advance ! i need to show the current part of the site to customer soon and im just stuck here…
there is almost nothing left i have not yet given a go…
production link: https://main--musical-lokum-78f90a.netlify.app/
one of the errors popping out so often as soon as i hit the “signin”:
.env file
MONGODB_URL=mongodb+srv://xxxxxx:xxxxxxxxxxxx@cluster0.9ksscei.mongodb.net/?retryWrites=true&w=majority
GOOGLE_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxxxx
JWT_SECRET=aWRlYWNoYW1iZXJwbGFjZXdvb2RmaXNoaXRzYWRkd2l0aGRpcnR5aHVycnlyZWNlbnQ=
NEXTAUTH_SECRET=ZnVydGhlcmxhcmdlc3RkaXNjdXNzaW9udGhvdXNhbmRtYWlsbWluZXJhbHNmdWxscmU=
NEXTAUTH_URL=https://musical-lokum-78f90a.netlify.app
ACTIVATION_TOKEN_SECRET=1996021996
BASE_URL=https://musical-lokum-78f90a.netlify.app
MAILING_SERVICE_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
MAILING_SERVICE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxxxxxxx
MAILING_SERVICE_CLIENT_REFRESH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
SENDER_EMAIL=xxxxx@gmail.com
RESET_SECRET=1996021996
[…nextauth].js file
import NextAuth from 'next-auth'
import GoogleProvider from 'next-auth/providers/google'
import GithubProvider from 'next-auth/providers/github'
import CredentialsProvider from "next-auth/providers/credentials";
import dotenv from 'dotenv'
import User from '../../../models/User'
import bcrypt from 'bcrypt'
import joi from 'joi'
import {connectDB, disconnect} from '../../../utils/db'
import {MongoDBAdapter} from '@next-auth/mongodb-adapter'
import clientPromise from './lib/mongodb'
import { getToken } from 'next-auth/jwt'
dotenv.config()
const loginSchema = joi.object({
email: joi.string().email().required(),
password: joi.string().min(6).required(),
});
export default NextAuth({
adapter : MongoDBAdapter(clientPromise),
providers: [
CredentialsProvider({
id: 'credentials',
name : 'Sign in',
credentials : {
email: { label: "Username", type: "text", placeholder: "jsmith" },
password: { label: "Password", type: "password", placeholder: "********" }
},
async authorize(credentials,req) {
try {
await connectDB()
const email = credentials.email
const password = credentials.password
console.log(email,password)
if (!email || !password) {
throw new Error('Please provide an email and password.');
}
const {error} = loginSchema.validate({email,password})
if (error) {
await disconnect()
throw new Error(error.details[0].message);
}
const user = await User.findOne({email})
if (!user) {
await disconnect()
throw new Error('Invalid email or password.');
}
const checkMatch = await bcrypt.compare(password, user.password)
if (!checkMatch) {
await disconnect()
throw new Error('Invalid email or password.');
}
return user
} catch (error) {
await disconnect()
throw new Error(error.message);
}
}
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret:process.env.GOOGLE_CLIENT_SECRET,
}),
GithubProvider({
clientId: "Iv1.2a94b24ea5010c98",
clientSecret: "71ff167e340484f06b9e03ff73bb64e4e667f8cb",
}),
],
pages: {
signIn: '/signin',
},
callbacks: {
async session({session, token}) {
let user = await User.findById(token.sub);
session.user.id = token.sub || user?._id?.toString();
session.user.role = user?.role || 'user';
return session;
}
},
session: {
strategy: 'jwt',
},
jwt: {
secret: process.env.JWT_SECRET,
},
secret: process.env.NEXTAUTH_SECRET,
})
signin.js page (frontend)
import React from "react";
import styles from "../styles/signin.module.scss";
import { BiLeftArrowAlt } from "react-icons/bi";
import Link from "next/link";
import LoginInput from "../components/custom/loginIput";
import Image from "next/image";
import { signIn } from "next-auth/react";
import { useState } from "react";
import { getProviders } from "next-auth/react";
import { useRouter } from "next/router";
import { getSession } from "next-auth/react";
import BarLoader from "react-spinners/BarLoader";
import {getCsrfToken} from 'next-auth/react'
function Signin({ providers, csrfToken, callbackUrl }) {
const [user, setUser] = useState({
email: "",
password: "",
});
const router = useRouter();
const [message, setMessage] = useState({
error: "",
successMessage: "",
});
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
const result = await signIn("credentials", {
redirect: false,
email: user.email,
password: user.password,
});
if (result?.error) {
setLoading(false);
setMessage({ ...message, error: result.error });
}
if (result?.ok) {
const session = await getSession();
console.log(session);
const successMessage = "You have successfully logged in !";
const waitTime = 3000;
setLoading(false);
setMessage({ ...message, successMessage });
let timer = setTimeout(() => {
router.push(callbackUrl || "/");
}, waitTime);
return () => {
clearTimeout(timer);
};
}
};
const handleChange = (e) => {
const { name, value } = e.target;
setUser({ ...user, [name]: value });
};
return (
<>
<div className={styles.login}>
<div className={styles.login__container}>
<div className={styles.login__header}>
<div className={styles.goback__svg}>
<BiLeftArrowAlt />
</div>
<span>Shop over +1 million products !</span>
</div>
<div className={styles.login__form}>
<Image src="/profilelogo.svg" width={100} height={100} alt="not" />
<h3>Sign in</h3>
<p> Sign in and start shopping immediately !</p>
<form onSubmit={handleSubmit}>
<LoginInput
icon="user"
placeholder="Username"
onChange={handleChange}
type="text"
name="email"
value={user.email}
required={true}
/>
<LoginInput
icon="password"
placeholder="Password"
onChange={handleChange}
type="password"
name="password"
value={user.password}
required={true}
/>
{message.error && (
<div
className={styles.login__error}
onAnimationEnd={() => setMessage({ ...message, error: "" })}
key={message.error}
>
<p>{message.error}</p>
</div>
)}
{message.successMessage && (
<div
className={styles.login__success}
onAnimationEnd={() =>
setMessage({ ...message, successMessage: "" })
}
key={message.successMessage}
>
<p>{message.successMessage}</p>
</div>
)}
<div className={styles.links}>
<span>
<Link className={styles.links__span__a} href="/signup">
Create an account
</Link>
</span>
<span>
<Link
className={styles.links__span__a}
href="auth/forgot"
>
Forgot password
</Link>
</span>
</div>
<button className={styles.loginButton} type="submit">
{
loading ? <BarLoader
color="#fff"
height={5}
loading = {loading}
speedMultiplier={2}
width={100}
/>
: "Sign in"
}
</button>
<div className={styles.divider}>
<span>or</span>
</div>
{ providers &&
Object.values(providers).map((item, index) =>
item.id === "credentials" ? null : (
<div className={styles.login__social} key={index}>
<a onClick={() => signIn(item.id)}>
<Image
src={`/${item.id}.svg`}
width={20}
height={20}
alt={`${item.name}`}
/>
<span>Continue with {`${item.name}`}</span>
</a>
</div>
)
)}
</form>
</div>
</div>
</div>
</>
);
}
export default Signin;
export async function getServerSideProps(context) {
const { req, query } = context;
const providers = await getProviders();
const session = await getSession({ req });
const csrfToken = await getCsrfToken(context);
const { callbackUrl } = query;
let defaultCallbackUrl = "/";
if (callbackUrl) {
defaultCallbackUrl = callbackUrl;
}
if (session) {
return {
redirect: {
destination: defaultCallbackUrl,
},
};
}
return {
props: { providers, session, csrfToken, callbackUrl: defaultCallbackUrl },
};
}
mongodb.js (next auth adapter)
import { MongoClient } from "mongodb";
const uri = process.env.MONGODB_URL;
const options = {
useUnifiedTopology: true,
useNewUrlParser: true,
};
let client;
let clientPromise;
if (!process.env.MONGODB_URL) {
throw new Error("Please add your Mongo URI to .env.local");
}
if (process.env.NODE_ENV === "development") {
if (!global._mongoClientPromise) {
client = new MongoClient(uri, options);
global._mongoClientPromise = client.connect();
}
clientPromise = global._mongoClientPromise;
} else {
client = new MongoClient(uri, options);
clientPromise = client.connect();
}
export default clientPromise;