Auth Overview
authenticate app users
The Auth client SDK authenticates users and notify the app about Auth events. It provides several authentication flows.
auth helper and reading currentUser across the app
We keep a reference to the auth helper to read currentUser. We also provide this helper when using some auth related functions.
const auth = getAuth(app)
auth.currentUser // User | null
currentUser starts as null. When the SDK has finished loading, and given that the user has logged-in, currentUser switches to a User instance.
As a User instance, It holds the user unique identifier (uid). Other properties may be empty:
currentUser.uid
currentUser.email
currentUser.phoneNumber
currentUser.displayName
currentUser.isAnonymous
react to authentication events
We register a callback on onAuthStateChanged, which Firebase runs on auth events. Firebase gives us a user object (of type User | null).
onAuthStateChanged(auth, (user) => {
if (user) {
// user.uid
}
})
Auth events:
-
the auth SDK has finished loading and no user is authenticated
-
the user has registered (sign up)
-
the user has logged in (sign in)
-
the user has logged out (sign out)
Login occurs in three specific scenarios:
- the user fills the standard login form or logs in through an identity provider (hard-login)
- the user is recognized by the SDK and is logged in automatically (credentials stored in browser)
- (canonically a registration) the user is automatically logged-in after a successful sign-up. Note: a single authentication event occurs.
React patterns
We make the authentication status part of the React state. For example, we work with a isSignedIn variable. We make the display of the authenticated area conditional on isSignedIn being true.
On page load, the Auth SDK is loading: If we initialize isSignedIn to false, it may not reflect the Auth reality, and may instantly switch to true once the SDK is loaded, which triggers a UI flicker.
It's best to wait for the SDK to load before making any use of isSignedIn. As such, we track the loading state in a one-off state variable, which becomes true on the first authentication event. Only then do we read isSignedIn.
const [hasLoaded, setHasLoaded] = useState(false)
const [isSignedIn, setisSignedIn] = useState(false)
useEffect(() => {
const unsub = onAuthStateChanged(auth, (user) => {
setHasLoaded(true)
setisSignedIn(Boolean(user))
})
return unsub
}, []) // subscribe once, subscribe automatically.
if (!hasLoaded) return null
if (!isSignedIn) return <Lobby />
return <Ingame />
sign out
sign out is consistent across all authentication flows:
signOut(auth)