Web firebase 保持用户登录

Web firebase keep user signed in

我正在为我的网络应用程序使用 firebase 身份验证。似乎在用户登录后,他们的会话只持续了大约一个小时,然后在他们返回网站或重新加载页面后,他们将被注销并需要重新登录。他们不是手动注销,而是在一段时间后被注销。 有没有办法让用户无限期地保持登录状态,直到他们要求退出?

代码如下:

/********************************************************************************
 *** Description: A hook which listens for Firebase changes.
 ***
 *** https://blog.logrocket.com/implementing-authentication-in-next-js-with-firebase/
 ********************************************************************************/

//==============================================================================
// IMPORTS
//==============================================================================

/* Yarn */
import { useState, useEffect } from 'react';
import {
    getAuth,
    signInWithEmailAndPassword,
    createUserWithEmailAndPassword,
    sendPasswordResetEmail,
    updateProfile
} from "firebase/auth";
import type { User } from "firebase/auth";

/* Personal */
import Firebase from '.';

//==============================================================================
// HELPER FUNCTIONS
//==============================================================================

/**
 * Returns necessary information from a firebase user.
 *
 * @param user Firebase User.
 * @returns An object containing the user's uid, email, and displayName.
 */
const formatAuthUser = (user: User) => ({
    uid: user.uid,
    email: user.email,
    displayName: user.displayName
});

//==============================================================================
// EXPORTS
//==============================================================================

export default function useFirebaseAuth() {
    const [authUser, setAuthUser] = useState(null);
    const [loading, setLoading] = useState(true);

    /**
     * Callback function when authentication state changes.
     *
     * @param authState User's state.
     * @returns
     */
    const authStateChanged = async (authState: User) => {
        if (!authState) {
            setAuthUser(null);
            setLoading(false);
            return;
        }

        setLoading(true);
        const formattedUser = formatAuthUser(authState);
        setAuthUser(formattedUser);
        setLoading(false);
    };

    /**
     * Clear user.
     */
    const clear = () => {
        setAuthUser(null);
        setLoading(true);
    };

    /**
     * Sign in with email and password.
     *
     * @param email User's email.
     * @param password User's password.
     * @returns Promise of the UserCredentials.
     */
    const signInWithEmailAndPasswordWrapper = (email: string, password: string) =>
        signInWithEmailAndPassword(getAuth(Firebase), email, password);

    /**
     * Create a new account.
     *
     * @param email User's email.
     * @param password User's password
     * @returns Promise of the UserCredentials.
     */
    const createUserWithEmailAndPasswordWrapper = (email: string, password: string) =>
        createUserWithEmailAndPassword(getAuth(Firebase), email, password);

    /**
     * Updates a user's display name.
     *
     * @param displayName Unique username.
     * @returns
     */
    const updateUserDisplayName = (displayName: string) => {
        setLoading(true);
        const currentUser = getAuth(Firebase).currentUser;
        updateProfile(currentUser, { displayName });
        const formattedUser = {
            uid: currentUser.uid,
            email: currentUser.email,
            displayName
        };
        setAuthUser(formattedUser);
        setLoading(false);
    }

    /**
     * Sends a password reset email.
     *
     * @param email Email to send password reset to.
     * @returns
     */
    const sendPasswordResetEmailWrapper = (email: string) =>
        sendPasswordResetEmail(getAuth(Firebase), email)

    /**
     * Remove authentication.
     *
     * @returns
     */
    const signOut = () => getAuth(Firebase).signOut().then(clear);

    // Listen for Firebase state change.
    useEffect(() => {
        const unsubscribe = getAuth(Firebase).onAuthStateChanged(authStateChanged);
        return () => unsubscribe();
    }, []);

    return {
        authUser,
        loading,
        signInWithEmailAndPasswordWrapper,
        createUserWithEmailAndPasswordWrapper,
        updateUserDisplayName,
        sendPasswordResetEmailWrapper,
        signOut
    };
}

这在上下文中用于访问应用程序中任何位置的身份验证状态:

/********************************************************************************
 *** Description: Creates a wrapper to access auth variables in any component.
 ***
 *** https://blog.logrocket.com/implementing-authentication-in-next-js-with-firebase/
 ********************************************************************************/

//==============================================================================
// IMPORTS
//==============================================================================

/* Yarn */
import { createContext, useContext } from 'react'

/* Personal */
import useFirebaseAuth from './useFirebaseAuth';

//==============================================================================
// CREATE CONTEXT
//==============================================================================

const authUserContext = createContext({
    authUser: null,
    loading: true,
    signInWithEmailAndPasswordWrapper: (email: string, password: string) => null,
    createUserWithEmailAndPasswordWrapper: (email: string, password: string) => null,
    updateUserDisplayName: (displayName: string) => null,
    sendPasswordResetEmailWrapper: (email: string) => null,
    signOut: () => null
});

//==============================================================================
// EXPORTS
//==============================================================================

export function AuthUserProvider({ children }) {
    const auth = useFirebaseAuth();
    return <authUserContext.Provider value={auth}>{children}</authUserContext.Provider>;
}

/**
 * Custom hook to use the authUserContext.
 */
export const useAuth = () => useContext(authUserContext);

整个应用程序都包含在 AuthUserProvider 中。

您需要启用令牌服务 API 和身份工具包 API 才能保持用户的登录状态。 我最初只有身份Toolkit API,因此当每小时请求一个新令牌时,它会失败,然后用户将被注销。