javascriptmongodbauthenticationnext.jsnext-auth

Next-auth 403 forbidden important error while everything is correct


after entering correct email and password combination i can see the user in the server console which means it is correctly returning the user but after the signin the response i get in the console is:

POST http://localhost:3000/api/auth/callback/credentials 403 (Forbidden)
{error: 'AccessDenied', status: 403, ok: false, url: null}

pls try to Help me

I am trying to sign in the account with email and password which is saved in mongodb in format:

{
  "_id": {
    "$oid": "676d1d11309c3cdb5b8c37df"
  },
  "email": "akhildwivedi21092006@gmail.com",
  "name": "Amit Dwivedi",
  "isverified": true,
  "age": "50",
  "password": "yash"
}

But when i was entering right email and password i was getting an unusual behaviour in the client console:

POST http://localhost:3000/api/auth/callback/credentials 403 (Forbidden)
{error: 'AccessDenied', status: 403, ok: false, url: null}

i think someone more experienced could help me in this.

this is in api/auth/[...nextauth]/route.js:

import NextAuth from 'next-auth'
import GithubProvider from 'next-auth/providers/github'
import GoogleProvider from 'next-auth/providers/google'
import CredentialsProvider from 'next-auth/providers/credentials'
import clientPromise from '@/app/lib/clientprom'

export const authOptions = NextAuth({
  providers: [
    CredentialsProvider({
      name: 'Credentials',
      async authorize(credentials) {
        let client = await clientPromise
        const db = client.db()
        const collection = db.collection('users')
        const user = await collection.findOne({ email: credentials.email, password: credentials.password })

        if (user) {
          console.log(user)
          return Promise.resolve(user)
        } else {
          return null  // or throw new Error("Invalid credentials");
        }
      },
    }),
    GithubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
      authorization: { params: { prompt: 'login' } },
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_ID,
      clientSecret: process.env.GOOGLE_SECRET
    }),
  ],
  callbacks: {
    async signIn({ user, account, profile, email }) {
      const client = await clientPromise
      const db = client.db()
      const collection = db.collection('users')

      if (account.provider === 'google' || account.provider === 'github') {
        let existingUser = await collection.findOne({ email: user.email, isverified: true })
        
        if (existingUser) {
          return true
        } else {
          await collection.insertOne({ email: user.email, name: profile.name, isverified: false })
          return true
        }
      }
    },
  },
})

export { authOptions as GET, authOptions as POST }

and this is in login/page.js:

"use client";
import React, { useEffect ,useState} from "react";
import { signIn ,getCsrfToken} from "next-auth/react";
import { useForm } from "react-hook-form";
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";

const Login = () => {
   
    const router = useRouter();
    const [csrfToken, setCsrfToken] = useState("")
    
    const {data:session} = useSession()

    useEffect(() => { 
      const fetchCsrfToken = async () => {
      const token = await getCsrfToken();
      setCsrfToken(token);
    };

    fetchCsrfToken();
        document.title = "Login - Get Me a Chai"
        if (session) {
            router.push("/createaccount");
        }
     
   }, [ session])
  const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting },
  } = useForm();

  const onSubmit = async (data) => {
   let response = await signIn("credentials", {
      email: data.email,
      password: data.password,
      csrfToken,
      redirect: false,
    });
    console.log(response)
  }

  const handleProviderSignIn = async (provider) => {
    const response = await signIn(provider);
  
  };
  return (
    <main className="flex">
      <div className="w-1/2 p-10">
      <div className="flex font-semibold text-[28px] leading-9 items-center"><p>Bittree</p> <img className="" width={22} src="greenlogo.svg" alt="" /></div>
     <div className="flex items-center flex-col gap-4 py-10 mt-16">
      <h1 className="font-extrabold text-[42px] leading-9 text-black">Sign Up or Log In</h1> 
      <p className="text-[#676b5f] font-normal">Welcome! Welcome! Welcome!</p>
      </div>
      <form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-4 px-10">
        <div className="flex flex-col">
        {errors.email && <span className="text-sm text-[#ff6b6b] font-semibold ">Please enter an email</span>}
        
        <input
          {...register("email", { required: true })}
          type="text"
          placeholder="Enter your Email*"
          className="bg-[#f6f7f5] p-4 outline-none border rounded-lg border-[#9a9a9a]"
        id="email"
        />
        </div>
        <div className="flex flex-col">
          {errors.password && <span className="text-sm text-[#ff6b6b] font-semibold ">Please enter an Password</span>}
        <input
          {...register("password", { required: true })}
          type="password"
          placeholder="Enter your Password*"
          className="bg-[#f6f7f5] p-4 outline-none border rounded-lg border-[#9a9a9a]"
        />
        </div>
          <button className="bg-[#8129d9] disabled:bg-[#8129d9c8] text-white p-3 font-semibold rounded-full" disabled={isSubmitting} type="submit">
          Sign In
        </button>
      </form>
      <p className="text-[#676b5f] font-normal text-center my-4">OR</p>
      <div className="flex flex-col gap-3 px-10">
      <button
        onClick={() => handleProviderSignIn("google")}
        type="button"
        className="text-black bg-[white] justify-center hover:bg-[#f6f7f5] border font-bold rounded-full items-center hover:border-[#f6f7f5] px-5 py-2.5 text-center inline-flex dark:focus:ring-[#4285F4]/55  gap-2"
      >
        <img src="google.svg" alt="" />
        Continue with Google
      </button>
      <button
        onClick={() =>handleProviderSignIn("github")}
        type="button"
        className="text-white bg-[#24292F] justify-center hover:bg-[#24292F]/90 font-bold rounded-full gap-1 px-5 py-2.5 text-center inline-flex items-center dark:focus:ring-gray-500 dark:hover:bg-[#050708]/30 me-2 mb-2"
      >
        <svg
          className="w-4 h-4 me-2"
          aria-hidden="true"
          xmlns="http://www.w3.org/2000/svg"
          fill="currentColor"
          viewBox="0 0 20 20"
        >
          <path
            fillRule="evenodd"
            d="M10 .333A9.911 9.911 0 0 0 6.866 19.65c.5.092.678-.215.678-.477 0-.237-.01-1.017-.014-1.845-2.757.6-3.338-1.169-3.338-1.169a2.627 2.627 0 0 0-1.1-1.451c-.9-.615.07-.6.07-.6a2.084 2.084 0 0 1 1.518 1.021 2.11 2.11 0 0 0 2.884.823c.044-.503.268-.973.63-1.325-2.2-.25-4.516-1.1-4.516-4.9A3.832 3.832 0 0 1 4.7 7.068a3.56 3.56 0 0 1 .095-2.623s.832-.266 2.726 1.016a9.409 9.409 0 0 1 4.962 0c1.89-1.282 2.717-1.016 2.717-1.016.366.83.402 1.768.1 2.623a3.827 3.827 0 0 1 1.02 2.659c0 3.807-2.319 4.644-4.525 4.889a2.366 2.366 0 0 1 .673 1.834c0 1.326-.012 2.394-.012 2.72 0 .263.18.572.681.475A9.911 9.911 0 0 0 10 .333Z"
            clipRule="evenodd"
          />
        </svg>
        Continue with Github
      </button>

</div>
      </div>

      <div className="w-1/2 relative overflow-hidden"><img className="absolute translate-y-[-20%]" src="images/banner.png" alt="" /></div>
    </main>
  );
};

export default Login;

Solution

  • What a insteresting thing i am the one who asked this question and too i am answering this question:

    So, i found out that i am not returning anything in signin callback and everything is just perfect. so i added this just after pervious condition of google and github:

    if (account.provider === 'credential-provider') {
            let existing user = await collection.findOne({email:user.email, password:userpassword)}
            if (existingUser) {
              return true
            } else {
              return false
            }
          }
    

    and the problem is solved, hey stackoverflow if you wanna reach me you can find me by REACH ME this is my link created by my own Website