Home > front end >  Why does this specific instance of .save() throw Version Error while other instances of .save() in s
Why does this specific instance of .save() throw Version Error while other instances of .save() in s

Time:07-09

I updated some of my Controller files to implement refresh token rotation, and that included my refreshTokenController file, which used to return a new access token on receiving an api call with a valid refresh token cookie. However, since then, it's throwing a Version Error on receiving the api call, but I can't figure out why the error is specifically coming from the third instance of .save() on line 61 (i.e., the error disappears only when I comment out the third instance of .save(), but not when I comment out either or both of the previous two instances of .save() on lines 32 and 49). Any insight would be appreciated. Thanks.

1    const jwt = require('jsonwebtoken');
2    const { defineModel } = require('../services/dbHandler');
3    const { userSchema } = require('../schemas/userSchema');
4    const { authTokenErr, cookieOptions, serverErr } = require('../utils');
5
6    const refreshAccessToken = async (req, res) => {
7      const prevRefreshToken = req.cookies?.refToken;
8
9      if (!prevRefreshToken) return res.status(401).json(authTokenErr);
10
11     res.clearCookie('refToken', prevRefreshToken, cookieOptions);
12
13     try {
14       const User = await defineModel('global', 'User', userSchema);
15
16       const dbUserWithToken = await User.findOne({
17         refreshToken: prevRefreshToken,
18       }).exec();
19
20       if (!dbUserWithToken) {
21         jwt.verify(
22           prevRefreshToken,
23           process.env.REFRESH_TOKEN_SECRET,
24           async (err, payload) => {
25             if (err) return res.status(401).json(authTokenErr);
26
27             const compromisedDbUser = await User.findOne({
28               _id: payload._uid,
29             }).exec();
30
31             compromisedDbUser.refreshToken = [];
32             await compromisedDbUser.save();
33           }
34         );
35
36         return res.status(401).json(authTokenErr);
37       }
38
39       const updatedTokenArr = dbUserWithToken.refreshToken.filter(
40         (token) => token !== prevRefreshToken
41       );
42
43       jwt.verify(
44         prevRefreshToken,
45         process.env.REFRESH_TOKEN_SECRET,
46         async (err, payload) => {
47           if (err || payload._uid !== dbUserWithToken._id.toString()) {
48             dbUserWithToken.refreshToken = [...updatedTokenArr];
49             const result = await dbUserWithToken.save();
50
51             return res.status(401).json(authTokenErr);
52           }
53
54           const renewedRefreshToken = dbUserWithToken.generateRefreshToken();
55           const renewedAccessToken = dbUserWithToken.generateAccessToken();
56
57           dbUserWithToken.refreshToken = [
58             ...updatedTokenArr,
59             renewedRefreshToken,
60           ];
61           await dbUserWithToken.save();    // <---- Cause of Version Error
62
63           res.cookie('refToken', renewedRefreshToken, cookieOptions);
64
65           return res.status(200).json({ accessToken: renewedAccessToken });
66         }
67       );
68     } catch (err) {
69       res.status(500).json(serverErr);
70       console.error(err);
71     }
72   };
73
74   module.exports = { refreshAccessToken };

CodePudding user response:

I also found that this was only occurring with my useEffect api fetches. Seeing as I'm now on react 18, I tried disabling strict mode, and the Version Error disappeared. So in the end, the versioning error was caused by react 18's new double-rendering of all useEffect hooks in strict mode (and had nothing to do with my 3 instances of document.save() in the same file after all). Now I just have to figure out why my clean-up function is not working on my useFetch hook.

  • Related