繁体   English   中英

Firebase 使用next auth时不认证

[英]Firebase does not authenticate when using next auth

我正在使用带 firebase 适配器的 next-auth。 在数据库中保存用户方面一切正常,但在身份验证方面有些问题。

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',
  },
})

我的用户可以登录,但未通过身份验证。

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
    // ...
  }
})

观察者返回“无用户”,但我已登录。

您没有看到登录用户,因为 firebase 身份验证是在服务器端而不是客户端完成的。

您应该尝试将 customToken 传递给 session,然后在客户端使用它来将用户登录到 firebase 身份验证。

您还希望将 useSession 挂钩包装在如下所示的自定义挂钩中,并使用它代替 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 };
}

好的,所以我最后做的是:正如@esi 所说,将使用 firebase auth 创建的 customToken 传递给 session:

 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 }

然后,在 session 回调中:

 async session({ session, token, user }) { if (session? .user) { session.user.id = token.sub session.customToken = token.customToken } return session },

最后,在首次重定向用户的页面中:

 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 true

就是这样。 希望它也适用于其他人。

谢谢 !

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM