React Authentication - network error when verifying if user is logged in, via token in local storage

Viewed 736

TL;DR: On production, our React app is throwing a network error when trying to verify whether a user is logged in, via a token from localstorage...

We're using Sentry for error tracking / reporting, and Sentry has now flagged a few times an error that we have been unable to recreate on our end:

enter image description here

and when we view the error in Sentry, we get some additional information, including a key breadcrumb pointing to our tokenIsValid post request:

enter image description here

Our react app calls tokenIsValid one-time in our top-level App.js file, and this request checks to see if a user was previously logged in (via a token saved in localstorage). Here's the useEffect from our App.js:

Edit: with error reporting added

router.post("/tokenIsValid", async (req, res) => {
    try {
        const token = req.header("x-auth-token");
        if (!token) return res.json(false);

        const verified = jwt.verify(token, process.env.JWT_SECRET);
        if (!verified) return res.json(false);

        const user = await User.findById(verified.id);
        if (!user) return res.json(false);

        return res.json(true);
    } catch (err) {
        // update: ive added Sentry error handling here
        res.status(500).json({ error: err.message });
    }
});

We followed this tutorial for react authentication with hooks. Everything seemed to work okay when we tested it, but now Sentry is alerting us of some errors as users try to sign up & log into our website.

enter image description here

Edit: Even though I've tagged this as a React + React Authentication problem, Network Error leads me to think the issue is related to our Node API simply not staying up, and users not being able to hit this endpoint in the Node API. This post hints at that... our Node API is deployed in a docker container using GCP's Cloud Run.

Also, maybe it's a cors issue, per this (last answer by Tiago), and I should add app.use(cors({origin: true, credentials: true})); when I call cors().

1 Answers

You may be facing issues due to the values returned and how you consume the returned value. With the below-refactored code, you can just check the authenticated key in the returned object, use the message key for human-readable status message, and use the error key for detailed error in the event of a 500 error.

// An authentication middleware, abstacted from the code within route controller
const authMiddlware = (req, res, next) => {
    try {
        // Get token from header
        const token = req.header("x-auth-token");
        if (!token) {
            return res.status(401).json({
                message: 'Token required'
            });
        }

        // validate token
        const { id } = jwt.verify(token, process.env.JWT_SECRET);
        if (id) {
            req.verified = {
                id
            };
            return next();
        } else {
            return res.state(401).json({
                message: 'Invalid token'
            });
        }
    } catch (err) {
        res.status(500).json({
            error: err,
            message: err.message
        });
    }

};

// Apply the auth middleware
router.post("/tokenIsValid", authMiddlware, async (req, res) => {
    try {
        const user = await User.findById(req.verified.id);
        if (user) {
            return res.status(200).json({
                authenticated: true,
                message: 'Authenticated successfully'
            });
        } else {
            return res.state(401).json({
                message: 'Invalid user'
            });
        }
    } catch (err) {
        res.status(500).json({
            error: err,
            message: err.message
        });
    }
});
Related