Next.js Discord

Discord Forum

I cannot redirect after google Oauth login with google

Unanswered
Alligator mississippiensis posted this in #help-forum
Open in Discord
Alligator mississippiensisOP
I am basically following the official Next Tutorial and doing the login part, instead of login with email. I am trying to do login with google. but every time after I login with google, I got redirect to the link below start with /auth/callback/google?code= and not to the original page. can anybody help?

NextJS authentication tutorial:
https://nextjs.org/learn/dashboard-app/adding-authentication#adding-the-credentials-provider

Link I got redirect to this page and show 404.
http://localhost:3000/api/auth/callback/google?code=4%2F0AcvDMrDwKh3uqo7lG5d13DXt4P1K0Zu-oOAg-5MrZY63NkJh-GbrAN4GXz-6tztr6vfvoQ&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=1&hd=blastedge-games.co.jp&prompt=consent



and my .env correctly set up the GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET

36 Replies

Alligator mississippiensisOP
this is my package.json
 json
{
  "private": true,
  "scripts": {
    "build": "next build",
    "dev": "next dev",
    "lint": "next lint",
    "prettier": "prettier --write --ignore-unknown .",
    "prettier:check": "prettier --check --ignore-unknown .",
    "seed": "node -r dotenv/config ./scripts/seed.js",
    "start": "next start"
  },
  "dependencies": {
    "@formatjs/intl-localematcher": "^0.5.4",
    "@heroicons/react": "^2.0.18",
    "@mdx-js/loader": "^3.0.1",
    "@mdx-js/react": "^3.0.1",
    "@next/mdx": "^14.2.5",
    "@nextui-org/dropdown": "^2.1.29",
    "@nextui-org/react": "^2.4.6",
    "@tailwindcss/forms": "^0.5.7",
    "@types/mdx": "^2.0.13",
    "@types/negotiator": "^0.6.3",
    "@types/node": "20.5.7",
    "@types/pg-format": "^1.0.5",
    "@uiw/react-markdown-preview": "^5.1.2",
    "@uiw/react-md-editor": "^4.0.4",
    "@vercel/postgres": "^0.9.0",
    "autoprefixer": "10.4.15",
    "bcrypt": "^5.1.1",
    "clsx": "^2.0.0",
    "framer-motion": "^11.3.17",
    "install": "^0.13.0",
    "negotiator": "^0.6.3",
    "next": "14.2.5",
    "next-auth": "5.0.0-beta.20",
    "next-cloudinary": "^6.6.2",
    "next-mdx-remote": "^5.0.0",
    "next-remove-imports": "^1.0.12",
    "parse-numeric-range": "^1.3.0",
    "pg-format": "^1.0.4",
    "postcss": "8.4.31",
    "prismjs": "^1.29.0",
    "react": "18.2.0",
    "react-copy-to-clipboard": "^5.1.0",
    "react-dom": "18.2.0",
    "react-markdown": "^9.0.1",
    "react-syntax-highlighter": "^15.5.0",
    "rehype-raw": "^7.0.0",
    "remark-gfm": "^4.0.0",
    "tailwindcss": "3.4.0",
    "typescript": "5.2.2",
    "use-debounce": "^9.0.4",
    "vercel": "^32.3.0",
    "zod": "^3.22.2",
    "zustand": "^4.5.4"
  },
"devDependencies": {
    "@tailwindcss/typography": "^0.5.13",
    "@types/bcrypt": "^5.0.1",
    "@types/react": "18.2.21",
    "@types/react-dom": "18.2.14",
    "@types/react-syntax-highlighter": "^15.5.13",
    "@vercel/style-guide": "^5.0.1",
    "dotenv": "^16.3.1",
    "eslint": "^8.52.0",
    "eslint-config-next": "15.0.0-rc.0",
    "eslint-config-prettier": "9.0.0",
    "prettier": "^3.0.3",
    "prettier-plugin-tailwindcss": "0.5.4"
  },
  "engines": {
    "node": ">=18.17.0"
  }
}
this is my login function
export async function authenticate(locale: string) {
  const lang = GetLangFromLocale(locale);
  try {
    const callbackUrl = 'http://localhost:3000/en/'; // Replace 'your-callback-url' with the actual callback URL
    console.log(`Attempting to sign in with callback URL: ${callbackUrl}`);
    await signIn('google', { 
      callbackUrl: callbackUrl,
    });
    console.log('Sign-in successful');
  } catch (error) {
    if (error instanceof AuthError) {
      switch (error.type) {
        case 'CredentialsSignin':
          return 'Invalid credentials.';
        default:
          return 'Something went wrong.';
      }
    }
    throw error;
  }
}
and this is my auth.ts
export const { auth, signIn, signOut } = NextAuth({
  ...authConfig,
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET
    }),

    // not use credentials
    Credentials({
      async authorize(credentials) {
        const parsedCredentials = z
          .object({ email: z.string().email(), password: z.string().min(6) })
          .safeParse(credentials);

        if (parsedCredentials.success) {
          const { email, password } = parsedCredentials.data;

          const user = await getUser(email);
          if (!user) return null;

          if (user.password) {
            const passwordsMatch = await bcrypt.compare(password, user.password);
            if (passwordsMatch) return user;
          }
          console.log('Invalid credentials');
          return null;
        }

        console.log('Invalid credentials');
        return null;
      },
    }),
  ],
});
and auth.config.ts
import type { NextAuthConfig } from 'next-auth';

export const authConfig = {
 
  providers: [
    // added later in auth.ts since it requires bcrypt which is only compatible with Node.js
    // while this file is also used in non-Node.js environments
  ],
  callbacks: {

    async redirect({ url, baseUrl }) {
      console.log("redirect", url, baseUrl);
      if (url.startsWith(baseUrl)) return url;
      return baseUrl;
    },
  },
} satisfies NextAuthConfig;
I got log like these, notice that "Attmpting to sign in...", " redirecct to localhost:3000/en" show up, but "Sign-iun successful" does not.
Attempting to sign in with callback URL: http://localhost:3000/en/
[auth][warn][env-url-basepath-redundant] Read more: https://warnings.authjs.dev#env-url-basepath-redundant
redirect http://localhost:3000/en http://localhost:3000
 POST /en 303 in 254ms
 GET /api/auth/callback/google?code=4%2F0AcvDMrDwKh3uqo7lG5d13DXt4P1K0Zu-oOAg-5MrZY63NkJh-GbrAN4GXz-6tztr6vfvoQ&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=1&hd=blastedge-games.co.jp&prompt=consent 404 in 73ms
 ✓ Compiled in 370ms (2845 modules)
 ○ Compiling /_not-found ...
 ✓ Compiled /_not-found in 681ms (6487 modules)
 GET /api/auth/callback/google?code=4%2F0AcvDMrDwKh3uqo7lG5d13DXt4P1K0Zu-oOAg-5MrZY63NkJh-GbrAN4GXz-6tztr6vfvoQ&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=1&hd=blastedge-games.co.jp&prompt=consent 404 in 51ms
 GET /api/auth/callback/google?code=4%2F0AcvDMrCjf8cinDOT4E2kCSw4BxZyy8jT8EoRFy9kfq1EAU0_U_x0PDi6SsM5-2qC34dYoA&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&prompt=consent 404 in 39ms
 GET /api/auth/callback/google?code=4%2F0AcvDMrCrQ8LeWtmtF_EP8wMCt67lwzyZskgr7kqZ3sz-IrzFp0wI2KWJWDdm57gWNYjLKw&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&prompt=consent 404 in 42ms
Chum salmon
It's so easy, you just specify callbackUrl (mine uses prop).
I uses prop because I use google login in different places. If I use it in a popup when a user is not logged in but want to create a post, the callbackUrl will be the create post form after they login with google. If they try to access a dashboard the callbackUrl will be the dashbord after they login. So using a prop like what I did here is very convenient and adaptable.
Alligator mississippiensisOP
I did try but not work @Chum salmon
Chum salmon
I just reviewed your code. It looks like you already specified callbackUrl. I'm trying to see what went wrong in your work right now.
Chum salmon
are you using next.js 13 or above?
I'm asking because the structure should look like this image but your post says auth.ts
Chum salmon
@Alligator mississippiensis remove http://localhost:3000 from your callbackUrl. Only put /en/

const callbackUrl = '/en/';
^ Try this first
Alligator mississippiensisOP
I am using next 14
So my auth config file is at root

Like this tutorial

https://nextjs.org/learn/dashboard-app/adding-authentication#adding-the-credentials-provider
Chum salmon
works?
@Chum salmon works?
Alligator mississippiensisOP
Sorry I am working.

I will try at night (Tokyo time) (9hour later)
Chum salmon
がんばってね!
😂
Alligator mississippiensisOP
@Chum salmon doesn't work
Alligator mississippiensisOP
btw I try the credentials login identical with the tutorial, and add redirectTo in signIn function, it successfully redirect. notice the param structure of signIn() had been changed.

but for google, still not work, even i use redirectTo
Alligator mississippiensisOP
I fixed it!

I searched in github, found out people use the same way as I use signIn()

and I browse their config and setting. notice that they have a route.js at /app/api/auth/[...nextauth]/route.js
and only 1 line of code.

and then he export
handler: { GET, POST} 
at the auth config file

After I do the same thing, it redirect corecttly.
Alligator mississippiensisOP
and this time I cannot redirect correctly with signOut().
my page does not refresh after I click sign out button.
I got error message @Chum salmon
@Alligator mississippiensis and this time I cannot redirect correctly with signOut(). my page does not refresh after I click sign out button. I got error message <@229440990245552129>
Chum salmon
I checked at your code again and I noticed I missed one thing.
Don't put / at the end of the line. try /en
It works for me
Alligator mississippiensisOP
I didn’t put / at the end this time.
My signIn work but signOut not work…
With error
Chum salmon
Does it work when you don't use the redirecturl?
One think that I noticed is that you use redirectTo instead of callbackUrl

Can you try
signOut({ callbackUrl: '/url' });
if it doesn't work, try setting redirect prop to too
signOut({ callbackUrl: '/url', redirect:true });
Alligator mississippiensisOP
I found out that the offcial one of signOut does redirect correctly. he was doing like this.

So I did a lot of A/B testing.

finally the reason is because of try catch block
after I remove the try catch block, it work
Alligator mississippiensisOP
and another solution found out from github issue https://github.com/nextauthjs/next-auth/discussions/9389

was using
import { isRedirectError } from 'next/dist/client/components/redirect';
if (isRedirectError(error)) {
      throw error;
    }
thank you for helping @Chum salmon
Chum salmon
That's great. Thank you for sharing your process!