You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js集成Firebase Google登录重定向后无法认证用户

Next.js + Firebase Google认证异常:重定向后未完成登录

问题现象

在Next.js应用中集成Firebase Google认证时,用户点击「Login with Google」按钮后可正常跳转至Google账号选择页面,但选择账号后被重定向回登录页面,认证流程未完成。控制台重复输出以下日志:

No user authenticated
Redirect result: null
No redirect result found
Redirect result: null
No redirect result found

已执行操作

  • 在Next.js应用中实现Firebase Google认证功能
  • 在/lib/firebase.js中完成Firebase配置及认证服务初始化
  • 在/app/login/page.js开发包含Google登录按钮的登录页面
  • 编写重定向结果处理逻辑,用于捕获登录后的用户数据并跳转至仪表盘
  • 检查Firebase项目的重定向URI配置(怀疑此处存在错误)

预期结果

  • 点击「Login with Google」按钮后跳转至Google账号选择页面
  • 用户选择账号后自动重定向回应用
  • 成功捕获并存储用户数据,自动跳转至仪表盘页面

实际结果

  • 用户选择Google账号后被重定向回登录页面
  • 控制台显示无已认证用户,且无法获取重定向结果
  • 控制台重复输出以下日志:
No user authenticated
Redirect result: null
No redirect result found
Redirect result: null
No redirect result found

登录页面代码

"use client";

import { useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { signInWithGoogle, getRedirectResultHandler, auth } from '@/lib/firebase';
import { useToggle } from '@mantine/hooks';
import { useForm } from '@mantine/form';
import { Paper, Group, Title } from '@mantine/core';
import { GoogleButton } from '@/components/buttons/GoogleButton';
import { useUser } from '@/context/UserContext';
import { onAuthStateChanged } from 'firebase/auth';
import classes from './page.module.css';

export default function AuthenticationImage() {
  const router = useRouter();
  const { setUser } = useUser();
  const [type, toggle] = useToggle(['login', 'register']);
  const form = useForm({
    initialValues: {
      email: '',
      name: '',
      password: '',
      terms: true,
    },
    validate: {
      email: (val) => (/^\S+@\S+$/.test(val) ? null : 'Invalid email'),
      password: (val) => (val.length <= 6 ? 'Password should include at least 6 characters' : null),
    },
  });

  useEffect(() => {
    const handleRedirectResult = async () => {
      console.log('Checking redirect result...');
      const result = await getRedirectResultHandler();
      console.log('Redirect result:', result);

      if (result) {
        const { user } = result;
        const userData = {
          photoURL: user.photoURL,
          displayName: user.displayName,
          email: user.email,
          uid: user.uid,
        };
        console.log('User data retrieved:', userData);
        setUser(userData);

        try {
          const res = await fetch('http://localhost:5000/api/login-google', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify(userData),
          });

          if (!res.ok) {
            throw new Error(`HTTP error! status: ${res.status}`);
          }

          const result = await res.json();
          console.log('API response:', result);
          localStorage.setItem('user', JSON.stringify(userData));
          router.push('/dashboard');
        } catch (error) {
          console.error('Error posting user data to API:', error);
        }
      } else {
        console.log('No redirect result found');
      }
    };

    const handleAuthStateChange = (user) => {
      if (user) {
        const userData = {
          photoURL: user.photoURL,
          displayName: user.displayName,
          email: user.email,
          uid: user.uid,
        };
        console.log('User authenticated:', userData);
        setUser(userData);
        router.push('/dashboard');
      } else {
        console.log('No user authenticated');
      }
    };

    handleRedirectResult();
    const unsubscribe = onAuthStateChanged(auth, handleAuthStateChange);

    return () => unsubscribe();
  }, [router, setUser]);

  const handleLogin = async () => {
    try {
      await signInWithGoogle();
    } catch (error) {
      console.error('Login failed', error);
    }
  };

  return (
    <div className={classes.wrapper}>
      <div className={classes.overlay}></div>
      <Paper className={classes.form} radius={0} p={30}>
        <Title order={2} className={classes.title} ta="center" mt="md" mb={50}>
          Welcome to Wealth Wise!
        </Title>
        <Group grow mb="md" mt="md">
          <GoogleButton radius="xl" className={classes.button} onClick={handleLogin}>Login with Google</GoogleButton>
        </Group>
      </Paper>
    </div>
  );
}

排查与解决方案

1. 检查Firebase重定向URI配置

  • 登录Firebase控制台 → 认证 → 登录方法 → Google → 已获授权的重定向URI
  • 确保添加了Next.js应用的完整URL,比如开发环境的http://localhost:3000/login(注意端口需与本地服务一致)
  • 生产环境需添加线上域名对应的URI,必须精确匹配,不能有多余斜杠或路径错误

2. 修正getRedirectResultHandler实现

该函数需直接调用Firebase官方方法,确保逻辑正确:

// /lib/firebase.js中的正确实现
import { getRedirectResult } from "firebase/auth";
import { auth } from "./firebase";

export const getRedirectResultHandler = async () => {
  try {
    const result = await getRedirectResult(auth);
    return result;
  } catch (error) {
    console.error("获取重定向结果失败:", error);
    return null;
  }
};

3. 避免重复处理重定向结果

Next.js App Router中useEffect可能重复执行,添加状态标记防止重复调用:

// 在组件内添加状态
const [checkedRedirect, setCheckedRedirect] = useState(false);

useEffect(() => {
  const handleRedirectResult = async () => {
    if (checkedRedirect) return;
    setCheckedRedirect(true);
    
    // 原逻辑不变
  };

  // 原逻辑不变
}, [router, setUser, checkedRedirect]);

4. 确认Firebase Auth初始化顺序

确保auth实例在调用认证方法前已完全初始化:

// /lib/firebase.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";

const firebaseConfig = {
  // 你的Firebase配置信息
};

const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);

5. 清除浏览器缓存与Cookie

浏览器缓存的旧认证状态可能导致异常,尝试清除当前域名的Cookie和缓存后重新测试。


内容的提问来源于stack exchange,提问作者Jayana N

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 14:05:58