When refreshing the page, client Firebase seems to think I have an authenticated user, but the firestore firebase rules imply that I don't have an authenticated user.
I have a Firebase app where users sign in with email and password via signInWithEmailAndPassword
. I set persistence to browserLocalPersistence
. Normally when a user logs in, the onAuthStateChanged
method is called with the authenticated user object and the application runs normally. When the user refreshes the page, my onAuthStateChanged
method fires again with a non-null user, but all Firebase queries fail due to my security rules. What am I doing wrong there.
This is a reactjs application. Please let me know if I can provide any other answers that might inspire you.
My firebase rules:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if isAuthenticated(); } function isAuthenticated() { return request.auth != null && request.auth.uid != null; } } }
My login code:
setPersistence(sharedFirebaseAuth, browserLocalPersistence) .then(() => { signInWithEmailAndPassword(sharedFirebaseAuth, email, password) .then((userCredential) => { }) .catch((error) => { }); })
My onAuthStateChanged code
onAuthStateChanged(sharedFirebaseAuth, (user) => { if(user){ user.reload().then(()=>{ requestDocs(); }); } })
P粉2587888312024-02-26 20:51:07
I think you forgot the comma between read
and write
, it should look like allow read, write: if isAuthenticated();
P粉8541192632024-02-26 14:51:34
I ended up having to implement an authentication provider so that it retained my user information.
New file AuthContext.tsx
import React from "react" import { User } from "firebase/auth"; export const AuthContext = React.createContext(null)
New file AuthProvider.tsx
import { FC, useEffect, useState } from "react"; import { User } from "firebase/auth"; import { sharedFirebaseAuth } from "../Utils/SharedFirebase"; import { AuthContext } from "./AuthContext"; export interface AuthProviderProps { children: JSX.Element; } export const AuthProvider: FC= ({ children }: AuthProviderProps) => { const [user, setUser] = useState (null); useEffect(() => { const unsubscribe = sharedFirebaseAuth.onAuthStateChanged((firebaseUser) => { setUser(firebaseUser); }); return unsubscribe }, []); return ( {children} ); };
Then I updated my index.tsx like this
import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; import { AuthProvider } from './provider/AuthProvider'; import "bootstrap/dist/css/bootstrap.min.css"; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render();
Then update the part of app.tsx where I call onAuthStateChanged to the following
const user = useContext(AuthContext); useEffect(() => { if(user){ requestDocs(); } },[user]);
After refreshing, it seems to retain all the necessary authentication information to extract the document.