Tips for maintaining authentication in a Next.js application with Firebase even when tokens expire or the page is refreshed

Struggling with firebase authentication flows while building an app using firebase and next.js. Everything was going smoothly until I encountered a bug or error. When my computer remains logged in to the app for some time and I refresh the page, it redirects me back to the login page. The issue seems to be related to onAuthStateChange not being checked in time for const { user } = useAuth() to run after a refresh, leading to redirection as there is no user at initial page load. However, clicking on a protected page like the dashboard keeps me authenticated without any redirections. Below is the code for my Auth component:

AuthComp.js:

import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { useAuth } from "../../context/AuthContext";
function LoadingScreen() {
    return <div className="fixed top-0 right-0 h-screen w-screen z-50 flex justify-center items-center">
        <div className="animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-gray-900"></div>
    </div>
}
export function AuthComp(props) {
    const [isAuthenticated, setIsAuthenticated] = useState(false)
    const router = useRouter();
    const { user } = useAuth();
    useEffect(() => {
        let out;
        if (user) {
            setIsAuthenticated(true)
            return () => out ? out() : null
        } else {
            router.push('/auth')
        }
        return () => out;
    }, [user])
    if (!user && (!isAuthenticated)) {
        return <LoadingScreen />;
    }
    return <props.Component user={user} />
};

Here is my code for my auth context file: AuthContext.js:

import React, { useState, useEffect, createContext, useContext } from 'react'
import { fbase } from '../utils/auth/firebaseClient'

export const AuthContext = createContext()

export default function AuthProvider({ children }) {
    const [user, setUser] = useState(null)
    const [loadingUser, setLoadingUser] = useState(true) // Helpful, to update the UI accordingly.

    useEffect(() => {
        // Listen authenticated user
        const unsubscriber = fbase.auth.onAuthStateChanged(async (user) => {
            try {
                if (user) {
                    setUser(user);
                } else {
                    setUser(null)
                    return;

                }
            } catch (error) {
                // Most probably a connection error. Handle appropriately.
                console.log('an error occurred', error);
            } finally {
                setLoadingUser(false)
            }
        })

        // Unsubscribe auth listener on unmount
        return () => unsubscriber()
    }, [])

    return (
        <AuthContext.Provider value={{ user, setUser, loadingUser }}>
            {children}
        </AuthContext.Provider>
    )
}

// Custom hook that shorthands the context!
export const useAuth = () => useContext(AuthContext)

Answer №1

there might not be sufficient time for the onAuthStateChange to be checked right away

The initial response from onAuthStateChanged may not occur instantly. It is important to understand that there could be a delay as the user's token is loaded and verified.

Until the first callback is triggered, it is best to consider the user's state as "unknown." They are neither logged in nor logged out until that initial callback occurs. It is advisable to design your application with this understanding of a trinary state in mind. (Additionally, firebase.auth().currentUser will always be null when a page initially loads.) For further insights into this behavior, I recommend checking out this blog post.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Adding a version number to the splash screen in Cordova: A step-by-step guide

After successfully integrating the Cordova Splashscreen plugin into my Ionic project, everything is running smoothly. However, I am now looking to dynamically add a version number to the splash screen without manually editing the Splash Screen PNG file e ...

Is it possible to determine if jQuery find returns true or false?

Snippet of HTML Code <div class="container1"> <div class="box1">Box 1</div> <div class="box2">Box 2</div> <div class="box3">Box 3</div> </div> <div clas ...

Leveraging Next.js for "client-side rendering" in React Encapsulations

My dilemma involves a component housing content crucial for SEO optimization. Here is an excerpt from my code: <AnimatedElement className="flex flex-col justify-start items-center gap-4 w-full" duration={500}> <h2 class ...

What is the best way to create an index for a user-provided value in a textbox

Looking for guidance on how to set an index to user-provided values in a textbox, append them to a table in a new row, and display that index in the first column of every row. I am unfamiliar with this type of functionality. $(document).ready(function() ...

Exploring the functionalities of using Script in Next.js 13

I want to include a vanilla JavaScript script in my next.js application like this: import Script from "next/script"; <Component {...pageProps} /> <Script id="raychat-widget" strategy="afterInteractive&quo ...

Having issues with Bootstrap flip div not functioning properly when clicked on a mobile device?

I am currently working on a website and encountering an issue. Here is the code snippet I am using: https://jsfiddle.net/3caq0L8u/ The objective is to flip a div when a button is clicked. The button responsible for flipping the div resides in both the " ...

Unable to extract attributes from a different model within Sails.js

I'm working on populating a customer model with attributes from the address.js model. However, when trying to post JSON using Postman, I keep getting a 500 Validation Error and struggling to pinpoint the cause of the issue. Any assistance would be gre ...

Access to PHP script (IF) unattainable following a POST occurrence

I'm completely new at this. I am attempting to create a contact form using HTML5 and PHP mail function, but I am facing an issue with my form action pointing to contacto.php. After submitting the form, it seems to be skipping over the IF condition wi ...

Retrieve data using the designated key and convert it into JSON format

If I have the following JSON array: [ {"data": [ {"W":1,"A1":"123"}, {"W":1,"A1":"456"}, {"W":2,"A1":"4578"}, {"W":2,"A1":"2423"}, {"W":2,"A1":"2432"}, {"W":2,"A1":"24324" ...

As soon as I inserted the image, the text vanished into thin air

The phrase "welcome" is not displaying after I included the av tag <!DOCTYPE html> <html> <style> @font-face { font-family: OpenSans; src: url(OpenSans-Bold.ttf); } * { ...

Vue.JS enables the seamless addition of rows to a form on the fly

I am currently working on creating a dynamic form using Vue. The concept is that when the user clicks the add button, another row will appear for them to input data. However, I encountered an issue where initially only 1 row was set up, but when I added th ...

Passing an unpredictable amount of parameters to react router in a dynamic way

Within my React application, users have the ability to create both folders and files. A folder can contain an indefinite number of subfolders within it. Here is an example structure: Folder-1 |_Folder-1-1 |_Folder-1-2 |_Folder-1-2-1 |_Folder- ...

Tips for removing information from a nested array that aligns with an ID in a separate array

Can anyone assist me with removing a nested array that matches the id of the main array? Here is arrayOne: [ { "id": "1", "role": [ "pos_cashier_1", "pos_manager" ...

Tips for substituting commas and slashes within an input text box

For instance, if the input is "1,23/456", the output should be "123456". When "1,23/456" is entered into the input field and "enter" is pressed, it should automatically convert to "123456". <input id="Id" ng-model="Id" name="searchInput" type="text"&g ...

bootstrap used for creating horizontal radio buttons

I'm attempting to horizontally align radio buttons within a form without relying on the Bootstrap library. The following code achieves this: <form id="test_form"> <div class="control-group"> <label for="Q1">First question</ ...

Is there a way to restrict the number of line breaks in a multiline asp:TextBox control?

Is it possible to restrict a multiline asp:TextBox to only display content on 3 lines using either javascript or C#? ...

What is the process for loading Syntax Highlighter on pages with pre tags?

As a Blogger, I often find myself in need of demonstrating codes on my blog. To achieve this, I have been using a Syntax Highlighter developed by Alex Gorbatchev. However, a recurring issue I face is that the files load on every single page of my blog, cau ...

Displaying error messages in React Hook Form when passing state

After reviewing the responses below, I have updated my code as follows: import { useState } from "react"; import Head from "next/head"; import Link from "next/link"; import Image from "next/image"; import Background ...

How can I retrieve both the keys and values of $scope in AngularJS?

Here is the code I have written to retrieve all key values using $scope. $scope.Signup={}; $scope.Message=''; $scope.SubmitPhysicianSignup = function() { var url = site_url + 'webservices/physician_signup'; //console.lo ...

The Bootstrap modal fails to appear when closed

After opening and closing the modal window, clicking on the button does not display the modal window again. The screen remains grayed out and the content of the modal window does not appear. yyyyyyyyyyyyyyyy function customShortcode() { ob_start(); ...