Can’t get userId to check Refresh Token (express/node authentication)

I am baffled. I am trying to follow a tutorial to create a api with authentication using refresh and access tokens.

I have it working when the access token doesn’t need to be updated/refreshed. However, as soon as it does I run into an issue.

I can’t check if the refreshToken is valid because I am storing refresh token in a database (containing the userId and the refresh token). However, I can’t fetch it, because I can’t get the userId from req.user.userId since the access token is expired meaning that the userId is now undefined. Therefore I can’t see if the refresh token is valid, and can’t create a new access token

/*ISSUE: I need to get userID here to check if the refresh token is valid via database,
  but req.user is undefined since the access token expired */
const storedRefreshToken = await findRefreshToken(req.user.userId);

if (!storedRefreshToken) {
   return res.status(401).json({ error: 'Invalid refresh token' });
}

Maybe I am completely misunderstanding the guide I am following because this makes no sense, feel free to tell me I am completely doing everything wrong

authentication Middleware:

const { verify } = require('jsonwebtoken');
const { findRefreshToken} = require('./userModel');
const { generateAccessToken} = require('./authHelper');

const tokenValidation = async (req, res, next) => {
  const accessToken = req.header('Authorization') ? req.header('Authorization').replace('Bearer ', '') : null;

  if (!accessToken) {
    return res.status(401).json({ error: 'Access token not found' });
  }

  try {
    const decoded = verify(accessToken, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    if (error.name === 'TokenExpiredError') {
      try {
        const storedRefreshToken = await findRefreshToken(req.user.userId /*I NEED TO GET THE userID here to check if the refresh token is valid but can't*/);

        if (!storedRefreshToken) {
          return res.status(401).json({ error: 'Invalid refresh token' });
        }

        const newAccessToken = generateAccessToken(newRefreshToken);

        req.user = jwt.verify(newAccessToken, process.env.JWT_SECRET);
    res.setHeader('Authorization', `Bearer ${newAccessToken}`);
        next();
      } catch (error) {
        return res.status(401).json({ error: 'Failed to refresh token' });
      }
    } else {
      return res.status(401).json({ error: 'Invalid token' });
    }
  }
};

module.exports = tokenValidation;

User Model for storing/fetching refresh tokens:

const storeRefreshToken = async (userId, refreshToken) => {
  const [result] = await db.execute(
    'INSERT INTO refresh_tokens (userId, refreshToken) VALUES (?, ?) ON DUPLICATE KEY UPDATE refreshToken = VALUES(refreshToken)',
    [userId, refreshToken]
  );
  return result;
};

const findRefreshToken = async (userId) => {
  const [rows] = await db.execute('SELECT * FROM refreshToken WHERE userId = ?', [userId]);
  return rows[0];
};

Generating tokens:

const { sign } = require('jsonwebtoken');

const generateAccessToken = (userId) => {
  return sign({ userId }, process.env.JWT_SECRET, { expiresIn: '10s' }); /*10s for testing*/
};

module.exports = {
  generateAccessToken
};