2

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().

Canovice
  • 9,012
  • 22
  • 93
  • 211
  • does sentry give more details about the error? if not try reporting the error manually https://docs.sentry.io/clients/javascript/#manually-reporting-errors, it'd be good to also configure error reporting in the backend to have a full picture about what's happening – diedu Nov 09 '20 at 00:18
  • I'm [following this](https://docs.sentry.io/platforms/node/usage/) to setup sentry with my node js backend. Sentry also gives info on the browser and OS info for each user who hit the error on the website (screenshot added). Lots of Windows users, but not all. – Canovice Nov 09 '20 at 04:56
  • I will update if / when I get another network error with the backend error reporting now set up... – Canovice Nov 09 '20 at 05:42
  • 1
    you say "Here's the `useEffect` from our `App.js`:" but the only code I'm seeing looks more like a backend node.js handler... – andersryanc Nov 09 '20 at 06:04
  • you say you haven't been able to reproduce the error yourself? I'm assuming by that you mean you are able to login to the production app just fine yourself? and that this is an intermittent issue for only some users? does Sentry also provide data about which browser is being uses and/or operating system, etc? do you see any trends for the environment this error comes up? – andersryanc Nov 09 '20 at 06:08
  • @andersryanc I removed the `useEffect` to clean up the question because I don't think it helped / was related to the network error. I'll edit the question to reflect this. – Canovice Nov 09 '20 at 08:36
  • as far as browser / OS trends are concerned, I added a screenshot which shows this info for ~20 of the ~25 Network Errors. Lots of Windows and Windows 10, although a few on Mac/Android/iOS... – Canovice Nov 09 '20 at 08:38
  • what other info do you get about the error? do you get the http status code? – diedu Nov 09 '20 at 15:28
  • I think I will get an http status code once the backend error reporting catches the error. So far, only catching "Network Error" in the front end. So I don't have any other info on the http request itself. – Canovice Nov 09 '20 at 18:40
  • It does seem like our Node API either (a) isn't staying up 100% of the time, or (b) users mostly on Windows 10 are timing out / getting Network errors hitting our API from the website... – Canovice Nov 09 '20 at 18:40
  • seeing as the error is happening on the frontend and/or is possibly related to a CORS issue, I'm not sure the error handling you added inside that specific backend handler may even report anything to sentry... according to some other posts I found re: axios + "Network Error", some people have suggested logging `err.response` and/or `err.response.data` on the frontend as they may contain more specific data about the server response which could help with debugging. – andersryanc Nov 09 '20 at 21:03
  • looks like the only thing(s) that would trigger your `catch (err)` block inside your `/tokenIsValid` handler would be `await User.findById()` and *maybe* `jwt.verify()`... and I'm guessing the likelihood of those failing is pretty slim – andersryanc Nov 09 '20 at 21:05
  • I don't think the `tokenIsValid` or `jwt.verify()` endpoints are failing. I just realized that when I use `Axios.post()` to call my `tokenIsValid` endpoint, that this is not currently wrapped in a try/catch, whereas my other API calls are. I'm going to update this and redeploy, and then see what happens if the error is hit again. – Canovice Nov 10 '20 at 18:11
  • i need more code to make this clear. May be cors issue, may be something else. `console.log(res)` in your `try` function and see what's wrong. – darkscripter Nov 12 '20 at 13:18

1 Answers1

1

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
        });
    }
});
Dharman
  • 30,962
  • 25
  • 85
  • 135
Grey
  • 489
  • 3
  • 7