adrianhajdin / project_next_14_ai_prompt_sharing

Next.js recently became the official React framework as outlined in React docs. In this course, you'll learn the most important Next.js concepts and how they fit into the React ecosystem. Finally, you'll put your skills to the test by building a modern full-stack Next 14 application.
https://www.jsmastery.pro/ultimate-next-course
2.58k stars 396 forks source link

Access blocked: Authorization Error [Error 401: invalid_client] #75

Closed MorkWood2 closed 7 months ago

MorkWood2 commented 7 months ago
Screenshot 2023-11-29 at 11 24 36 AM

Hey everybody,

@ 1:43 in the video I am getting a error 401 when I try to log in. Access blocked: Authorization Error, The OAuth client was not found. [Error 401: invalid_client]

My google id and google client is correct. All my extensions are disabled (in case add blocker is blocking client).

In google "Client Id for Web Application"

Authorized javascript origins is set to http://localhost:3000

Authorized redirect URIs is set to http://localhost:3000 and http://localhost:3000/api/auth/callback/google

For safe keeping I even added my email to test users in the OAuth consent screen

route.js

import GoogleProvider from 'next-auth/providers/google';
//https://console.cloud.google.com/

import { connectToDB } from '@utils/database';
import User from '@models/user';
const handler = NextAuth({
  providers: [
    GoogleProvider({
      clientId: 'process.env.GOOGLE_ID',
      clientSecret: 'process.env.GOOGLE_CLIENT_SECRET',
    }),
  ],
  async session({ session }) {
    const sessionUser = await User.findOne({
      email: session.user.email,
    });

    session.user.id = sessionUser._id.toString();
    return session;
  },
  async signIn({ profile }) {
    try {
      //serverless -> Lambda -> dynamodb
      await connectToDB();

      //check if user is already exists
      const userExist = await User.findOne({
        email: profile.email,
      });

      //if not create a new user
      if (!userExist) {
        await User.create({
          email: profile.email,
          userName: profile.name.replace(' ', '').toLowerCase(),
          image: profile.picture,
        });
      }
      return true;
    } catch (error) {
      console.log(error);
      return false;
    }
  },
});

export { handler as GET, handler as POST };

Nav.js


import Link from 'next/link';
import Image from 'next/image';
import { useState, useEffect } from 'react';
import { signIn, signOut, useSession, getProviders } from 'next-auth/react';

const Nav = () => {
  const { data: session } = useSession();
  const [providers, setProviders] = useState(null);
  const [toggleDropdown, setToggleDropdown] = useState(false);
  useEffect(() => {
    const setUpProviders = async () => {
      const response = await getProviders();
      setProviders(response);
    };

    setUpProviders();
  }, []);

  return (
    <nav className='flex-between w-full mb-16 pt-3'>
      {' '}
      <Link href='/' className='flex gap-2 flex-center'>
        <Image
          src='/assets/images/logo.svg'
          alt='prompt share logo'
          width={30}
          height={30}
          className='object-contain'
        />
        <p className='logo_text'>Prompt Share</p>
      </Link>
      {/* Desktop Nav */}
      <div className='sm:flex hidden'>
        {session?.user ? (
          <div className='flex gap-3 md:gap-5'>
            {' '}
            <Link href='/create-prompt' className='black_btn'>
              Create Post
            </Link>{' '}
            <button type='button' onClick={signOut} className='outline_btn'>
              Sign Out
            </button>
            <Link href='/profile'>
              <Image
                src='/assets/images/logo.svg'
                width={37}
                height={37}
                className='rounded-full'
                alt='profile'
              />
            </Link>
          </div>
        ) : (
          <div>
            {' '}
            {providers &&
              Object.values(providers).map((provider) => (
                <button
                  type='button'
                  key={provider.name}
                  onClick={() => signIn(provider.id)}
                  className='black_btn'
                >
                  Sign In
                </button>
              ))}{' '}
          </div>
        )}
      </div>
      {/* Mobile Navigation*/}
      <div className='sm:hidden flex relative'>
        {session?.user ? (
          <div>
            {' '}
            <Image
              src='/assets/images/logo.svg'
              width={37}
              height={37}
              className='rounded-full'
              alt='profile'
              onClick={() => setToggleDropdown((prev) => !prev)}
            />
            {toggleDropdown && (
              <div className='dropdown'>
                <Link
                  href='/profile'
                  className='dropdown_link'
                  onClick={() => setToggleDropdown(false)}
                >
                  My Profile
                </Link>
                <Link
                  href='/create-prompt'
                  className='dropdown_link'
                  onClick={() => setToggleDropdown(false)}
                >
                  Create Prompt
                </Link>
                <button
                  type='button'
                  onClick={() => {
                    setToggleDropdown(false);
                    signOut();
                  }}
                  className='mt-5 w-full black_btn'
                >
                  Sign Out
                </button>
              </div>
            )}
          </div>
        ) : (
          <div>
            {' '}
            {providers &&
              Object.values(providers).map((provider) => (
                <button
                  type='button'
                  key={provider.name}
                  onClick={() => signIn(provider.id)}
                  className='black_btn'
                >
                  Sign In
                </button>
              ))}{' '}
          </div>
        )}
      </div>
    </nav>
  );
};

export default Nav;
Screenshot 2023-11-29 at 1 30 40 PM