I have a simple react app using firebase authentication. After successful Login the firebase:authUser is stored in localStorage. But on every page refresh localStorage is being cleared and the session is lost. Browsing through other pages doesn't clear localStorage though.
Here is what it looks like in code:
- Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
- App.js
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Login from './Login';
import Main from './Main';
import Info from './Info';
import './App.css';
function App() {
return (
<div className="App">
<Router>
<Routes>
<Route path="/login" element={<Login/>} />
<Route path="/" element={<Main/>} />
<Route path="/info" element={<Info/>} />
</Routes>
</Router>
</div>
);
}
export default App;
- Info.js → random page that I can view without authentication needed. Refreshing while on this page (http://localhost:3000/info) also clears localStorage
import { useNavigate } from "react-router-dom";
function Info() {
const navigate = useNavigate();
return (
<div>
<div>
Info page
</div>
<button
onClick={() => {
navigate('/');
}
}>
Go to Main
</button>
</div>
);
}
export default Info;
Here is firebase.js I use to authenticate user
import { initializeApp } from 'firebase/app';
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, signOut, setPersistence, browserLocalPersistence } from 'firebase/auth';
const firebaseConfig = {
// Here is my config
};
initializeApp(firebaseConfig);
// Auth
const auth = getAuth();
var email;
var password;
// Auth - set persistance
setPersistence(auth, browserLocalPersistence);
// Auth - create
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
});
// Auth - Login
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
});
// Auth - signOut
signOut(auth).then(() => {
// Sign-out successful.
}).catch((error) => {
// An error happened.
});
export {
auth,
db,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut
};
I have a simple react app using firebase authentication. After successful Login the firebase:authUser is stored in localStorage. But on every page refresh localStorage is being cleared and the session is lost. Browsing through other pages doesn't clear localStorage though.
Here is what it looks like in code:
- Index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
- App.js
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Login from './Login';
import Main from './Main';
import Info from './Info';
import './App.css';
function App() {
return (
<div className="App">
<Router>
<Routes>
<Route path="/login" element={<Login/>} />
<Route path="/" element={<Main/>} />
<Route path="/info" element={<Info/>} />
</Routes>
</Router>
</div>
);
}
export default App;
- Info.js → random page that I can view without authentication needed. Refreshing while on this page (http://localhost:3000/info) also clears localStorage
import { useNavigate } from "react-router-dom";
function Info() {
const navigate = useNavigate();
return (
<div>
<div>
Info page
</div>
<button
onClick={() => {
navigate('/');
}
}>
Go to Main
</button>
</div>
);
}
export default Info;
Here is firebase.js I use to authenticate user
import { initializeApp } from 'firebase/app';
import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, signOut, setPersistence, browserLocalPersistence } from 'firebase/auth';
const firebaseConfig = {
// Here is my config
};
initializeApp(firebaseConfig);
// Auth
const auth = getAuth();
var email;
var password;
// Auth - set persistance
setPersistence(auth, browserLocalPersistence);
// Auth - create
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
});
// Auth - Login
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
});
// Auth - signOut
signOut(auth).then(() => {
// Sign-out successful.
}).catch((error) => {
// An error happened.
});
export {
auth,
db,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut
};
Share
Improve this question
edited Nov 7, 2021 at 15:51
Frank van Puffelen
601k85 gold badges890 silver badges860 bronze badges
Recognized by Google Cloud Collective
asked Nov 7, 2021 at 8:45
kenkechkenkech
731 silver badge5 bronze badges
2
- Are you sure it's not your browser configuration? Try changing your browser – Nestor Solalinde Commented Nov 7, 2021 at 9:04
- @NestorSolalinde I have tried chrome & safari. Both act the same. Also I have tried to use SessionStorage instead of local and it has the same effect → on refresh firebase:authUser just disappears – kenkech Commented Nov 7, 2021 at 9:53
2 Answers
Reset to default 4In most browsers, when you reload the page, Firebase already restores the users authentication state from local storage by default. But since this requires it to call to the server, it may take a moment before it initialized the current user and you should use a so-called auth state listener as shown in the first code sample in the documentation on getting the current user:
import { getAuth, onAuthStateChanged } from "firebase/auth";
const auth = getAuth();
onAuthStateChanged(auth, (user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google./docs/reference/js/firebase.User
const uid = user.uid;
// ...
} else {
// User is signed out
// ...
}
});
Your code only seems to handle the case where the user explicitly logs in, so it never picks up the restored user.
If the above works, check if you actually need the call to setPersistence(auth, browserLocalPersistence);
. As said, on browsers this should already be the default behavior.
Some times the onAuthStateChanged method don't solve the problem. At least in my case. Doug Stevenson wrote a blog about the "Why is my currentUser == null in Firebase Auth?".(link).
First of all the current user not binary it is actually trinary:
- unknown (still not read)
- sing in %100
- sing out %100
so you need to consider there cases handle individually. He has his own example implementation in the his blog post so I will my solution here.
const [user, setUser] = useState<User | null | undefined>(undefined);
I defined my user with 3 possible values so I can handle each cases. user object enitial value is null so it is the unknown case
auth.onAuthStateChanged(function (firebaseUser) {
if (firebaseUser) {
setUser(firebaseUser);
} else {
setUser(null);
}
});
If the user is signed out %100 the the value is null.
In my auth provider I checked all there cases
if (user == undefined) {
return <h1>loading...</h1>;
} else if (!user) {
return <Navigate to={"/login"} />;
}
return <what ever you content is />;