Estoy usando next-auth con el adaptador firebase. Todo funciona bien en términos de guardar usuarios en la base de datos, pero algo no funciona en términos de autenticación.
import NextAuth from "next-auth" import GoogleProvider from "next-auth/providers/google" import { FirebaseAdapter } from "@next-auth/firebase-adapter" import { db } from "../../../utils/firebase/firebase" import * as firestoreFunctions from 'firebase/firestore' import { adminAuth } from "../../../utils/firebase/firebaseAdmin" import { getAuth, signInWithCustomToken } from "firebase/auth" const auth = getAuth() export default NextAuth({ providers: [ GoogleProvider({ clientId: process.env.GOOGLE_ID, clientSecret: process.env.GOOGLE_SECRET, state: false, }), ], adapter: FirebaseAdapter({ db: db, ...firestoreFunctions, }), callbacks: { async signIn({ user, account, profile, email, credentials }) { console.log(user, 'user') const customToken = await adminAuth.createCustomToken(user.id) const customSignIn = await signInWithCustomToken(auth, customToken) console.log(customSignIn, 'customSignIn') console.log(customSignIn.user, 'customSignIn.user') user = customSignIn.user console.log(user, 'user 2') return true }, async redirect({ url, baseUrl }) { return baseUrl }, async session({ session, user, token }) { if (session?.user) { session.user.id = token.sub } return session }, async jwt({ token, user, account, profile, isNewUser }) { if (isNewUser) { const additionalClaims = { isStudent: true, isTeacher: false, isStaff: false, isAdmin: false } const customToken = await adminAuth.createCustomToken(token.sub, additionalClaims) const customSignIn = await signInWithCustomToken(auth, customToken) user = customSignIn.user } return token } }, session: { strategy: 'jwt', }, })Mis usuarios pueden iniciar sesión, pero no están autenticados.
const auth = getAuth() onAuthStateChanged(auth, (user) => { if (user) { // User is signed in, see docs for a list of available properties // https://firebase.google.com/docs/reference/js/firebase.User console.log('user') console.log(user) // ... } else { console.log('no user') // User is signed out // ... } })El observador devuelve 'sin usuario', pero estoy conectado.
No está viendo un usuario conectado porque la autenticación de Firebase se realiza en el lado del servidor y no en el lado del cliente.
Debe intentar pasar el customToken a la sesión, luego usarlo en el lado del cliente para iniciar sesión en la autenticación de firebase.
También querrá envolver el enlace useSession en un enlace personalizado como el que se muestra a continuación y usarlo en lugar de useSession.
const useFirebaseSession = () => { const session = useSession(); const [status, setStatus] = useState(session.status); useEffect(() => { if (session && session.status === 'authenticated') { signInWithCustomToken(auth, session.customToken).then(() => { setStatus('authenticated'); }); } }, [session]); useEffect(() => { if(session.status !== 'authenticated') { setStatus(session.status) } }, [session.status]); return { data: session.data, status }; }Ok, lo que finalmente hice fue: como dijo @esi, pase el token personalizado creado con la autenticación de firebase a la sesión:
async jwt({ token, user, account, profile, isNewUser }) { if (isNewUser || user) { const additionalClaims = { isStudent: true, isTeacher: false, isStaff: false, isAdmin: false } const customToken = await adminAuth.createCustomToken(token.sub, additionalClaims) console.log(customToken, '***customToken') token.customToken = customToken } return token }Luego, en la devolución de llamada de la sesión:
async session({ session, token, user }) { if (session ? .user) { session.user.id = token.sub session.customToken = token.customToken } return session },Y por último, en la página a la que se redirige a los usuarios por primera vez:
const [user, setUser] = useState() useEffect(() => { if (status === "authenticated") { const loggedInUser = { userName: session.user.name, userEmail: session.user.email, userPhoto: session.user.image, userUID: session.user.id, } signInWithCustomToken(auth, session.customToken) dispatch(setActiveUser(loggedInUser)) } }, [status]) const handleLogOut = () => { dispatch(setUserLogOutState()) logout() signOut({ callbackUrl: '/' }) //TODO: goodbye page // Rest of jsx code when session is trueY eso es. Espero que funcione para alguien más también.
Gracias !