Search code examples
javascriptreactjsfirebasefrontendredux-toolkit

Why i can't create persistence authentication (firebase) in my login component?


Hello everyone, I'm doing a react test and I want to implement firebase authentication persistence in my Login component. I know you need to use setPersistence for this, but for some reason, the authentication doesn't persist after a reboot. In general, my authentication and registration work correctly (I have several components - Register.jsx , Login.jsx and Form.jsx which serves as the base for Register and Login. It's just that when the page is reloaded, the authentication is reset as before, without any errors. Also i have redux-toolkit in my app. Can you help me? What am I doing wrong?

This is my base.js file:

import firebase from 'firebase/compat/app';
import { getDatabase } from 'firebase/database';
import 'firebase/compat/auth';

const firebaseConfig = {
    apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
    authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
    projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
    storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
    appId: process.env.REACT_APP_FIREBASE_APP_ID,
    databaseURL: process.env.REACT_APP_FIREBASE_DATABASE,
};

const app = firebase.initializeApp(firebaseConfig);

const database = getDatabase(app);

export default app;

This is my Login component:

import { Form } from './Form';
import { useDispatch } from 'react-redux';
import { setUser } from '../store/slices/userSlice';
import {
    getAuth,
    setPersistence,
    signInWithEmailAndPassword,
    browserSessionPersistence,
} from 'firebase/auth';
import { useNavigate } from 'react-router-dom';

const Login = () => {
    const dispatch = useDispatch();
    const navigate = useNavigate();

    const auth = getAuth();

    const handleLogin = async (email, password) => {
        try {
            await setPersistence(auth, browserSessionPersistence);
            signInWithEmailAndPassword(auth, email, password).then(({ user }) => {
                console.log(user);
                dispatch(
                    setUser({
                        email: user.email,
                        id: user.uid,
                        token: user.accessToken,
                    })
                );
                navigate('/');
            });
        } catch (error) {
            console.error('Invalid email or password', error);
        }
    };
    return <Form title='sign in' handleClick={handleLogin} />;
};

export { Login };

Solution

  • In your Firebase config file, import browserLocalPersistence and initializeAuth from firebase/auth, define a exported variable auth and assign it the value of initializeAuth with your app and a empty object as a second parameter, inside the empty object create a key, persistence, and give it a value of browserLocalPersistence.

    import { getApps, initializeApp } from "firebase/app";
    import { browserLocalPersistence, initializeAuth } from "firebase/auth";
    
    const firebaseConfig = {...};
    
    export const firebaseApp =
      getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0];
    
    export const auth = initializeAuth(firebaseApp, {
        persistence: browserLocalPersistence,
    });
    

    Now, later when, for example, signInWithEmailAndPassword is invoked, Firebase will persistent the data returned in accordance with the persistence type specified by the options object passed to initializeAuth. Additionally, if you would like Firebase Auth to use multiple persistence types, make the value of the persistence key an array and include the persistence types in the array. You can then use setPersistence to specify how you want Firebase Auth to persist the data among the available options included in the array.

    import {
      signInWithCredential,
      GoogleAuthProvider,
      setPersistence,
      browserLocalPersistence,
    } from "firebase/auth";
    import { auth } from "../lib/firebase/config";
    import { useNavigate } from "react-router-dom";
    
    const SignInPage = () => {
        const navigate = useNavigate;
        
      const handleClick = async () => {
        try {
          const authResponse = await chrome.runtime.sendMessage({
            action: "invokeFirebaseAuth",
          });
          const credential = GoogleAuthProvider.credentialFromResult(
            authResponse.credentials
          );
            
          signInWithCredential(auth, credential)
            .then((userCredential) => {
              const user = userCredential.user;
            })
            .catch((error) =>
              console.error(
                "There was an error signing in with credentials: ",
                error
              )
            );
        } catch (error) {
          console.error(error);
        }
      };
    
      return (
        <div id={"sign-in-page"}>
          <div style={{ margin: "20px 0" }}>
            <button onClick={handleClick}> Firebase Auth</button>
          </div>
        </div>
      );
    };
    
    export default SignInPage;
    

    If setting the persistence type among available options.

      const handleClick = async () => {
        try {
          const authResponse = await chrome.runtime.sendMessage({
            action: "invokeFirebaseAuth",
          });
          const credential = GoogleAuthProvider.credentialFromResult(
            authResponse.credentials
          );
          setPersistence(auth, browserLocalPersistence)
            .then(() => {
              return signInWithCredential(auth, credential);
            })
            .then((user) => {
              navigate("/");
            })
            .catch((error) => {
              console.error(
                "There was an error setting persistence: ", error
              );
            });
        } catch (error) {
          console.error(error);
        }
      };
    

    You can see the documentation explaining this here.