OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

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

  • Thread starter Thread starter Max Jones
  • Start date Start date
M

Max Jones

Guest
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

Code:
/*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:

Code:
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:

Code:
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:

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

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

module.exports = {
  generateAccessToken
};

<p>I am baffled. I am trying to follow a tutorial to create a api with authentication using refresh and access tokens.</p>
<p>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.</p>
<p>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</p>
<pre><code>/*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' });
}
</code></pre>
<p>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</p>
<p>authentication Middleware:</p>
<pre><code>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;
</code></pre>
<p>User Model for storing/fetching refresh tokens:</p>
<pre><code>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];
};
</code></pre>
<p>Generating tokens:</p>
<pre><code>const { sign } = require('jsonwebtoken');

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

module.exports = {
generateAccessToken
};
</code></pre>
 

Latest posts

Top