Search code examples
javascriptnext.jsfirebase-authenticationgoogle-oauth

Firebase Google Auth does not work on Vercel


I use Vercel for deployment. After build, google auth works fine only first time, after log out currentUser always is equal null.

But on localhost it works good, I can re-login a dozen times and everything is going well and currentUser always object with data.

I tried to play with dependencies in useEffect, but always get the same issue.

Also tried to disable chrome://flags/#third-party-storage-partitioning - it does not help

'use client'
import { useEffect, useState, useContext, createContext } from 'react'
import { useRouter } from 'next/navigation'
import {getAuth, GoogleAuthProvider, onAuthStateChanged, signInWithRedirect} from 'firebase/auth'
import { User } from 'firebase/auth'
import '@/services/firebaseConfig'
import { DocumentData, doc, getDoc } from 'firebase/firestore'
import {auth, db} from '@/services/firebaseConfig'
import { usePathname } from 'next/navigation'
import {DEFAULT_REDIRECT_PATH} from "@/config/constants";

interface AuthProviderProps {
  children: React.ReactNode
}

interface AuthContextType {
  user: User | null
  authLoading: boolean
  userData: DocumentData | undefined
  setUser: (user: User | null) => void
  setUserData: (user: DocumentData | undefined) => void
}

const AuthContext = createContext<AuthContextType | null>(null)

export const useAuth = () => {
  return useContext(AuthContext)
}

export const AuthProvider = ({ children }: AuthProviderProps) => {
  const router = useRouter()
  const [authLoading, setAuthLoading] = useState(false)
  const [user, setUser] = useState<User | null>(null)
  const [userData, setUserData] = useState<DocumentData | undefined>()
  const pathname = usePathname()

  useEffect(() => {
    const auth = getAuth()
    const unsubscribe = onAuthStateChanged(auth,  (currentUser) => {
      if (currentUser) {
        const userRef = doc(db, 'users', currentUser.uid)
        // const userDoc = await getDoc(userRef)
        // setUser(currentUser)
        // setUserData(userDoc.data())
        if (['/login', '/register'].includes(pathname || '')) {
          if(currentUser.emailVerified) {
            router.replace(DEFAULT_REDIRECT_PATH)
          }
        }
      }
      else {
        // setUser(null)
        // setUserData(undefined)

      }
      console.log('currentUser', currentUser)

      if (
        !currentUser &&
        !['/', '/register', '/legal', '/login'].includes(pathname || '')
      ) {
        router.replace('/login')
      } else {
        // setAuthLoading(false)
      }
    })

    return () => unsubscribe()
  }, [user])

  return (
    <AuthContext.Provider value={{ user, authLoading, userData, setUser, setUserData }}>
      {children}
    </AuthContext.Provider>
  )
}

Solution

  • Did you follow the recommendations for signinwith redirect? https://firebase.google.com/docs/auth/web/redirect-best-practices

    At the root of your application (not inside src) put a vercel.json file with:

    {
        "rewrites": [
          {
            "source": "/__/auth/(.*)",
            "destination": "https://redseat.firebaseapp.com/__/auth/$1"
          }
        ]
      }