Re-validate JWT against the DB in isLoggedIn (#12)
isLoggedIn trusted id and role straight from the JWT and never re-checked the database, so a demoted admin kept their old role and a deleted user kept a working session until the token expired (up to JWT_EXPIRES_IN). This also undercut the "last admin" guards. isLoggedIn now loads the user from the DB by the token's id on every request: a missing user returns 401 (deleted), and req.user carries the fresh DB row so the current role is always used downstream. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ const jwt = require('jsonwebtoken')
|
|||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
|
|
||||||
const log = require('./logger')('auth')
|
const log = require('./logger')('auth')
|
||||||
|
const users = require('../model/users/users.model')
|
||||||
|
|
||||||
const JWT_SECRET = process.env.JWT_SECRET
|
const JWT_SECRET = process.env.JWT_SECRET
|
||||||
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '1d'
|
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '1d'
|
||||||
@@ -77,12 +78,22 @@ function getUserFromRequest(req) {
|
|||||||
return verifyToken(token)
|
return verifyToken(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gate middleware for protected (admin) routes.
|
// Gate middleware for protected (admin) routes. Re-validates the token against
|
||||||
function isLoggedIn(req, res, next) {
|
// the database on every request so a demoted or deleted user loses access
|
||||||
const user = getUserFromRequest(req)
|
// immediately, instead of keeping their old role (or a working session) until
|
||||||
if (!user) return res.status(401).json({ message: 'Unauthorized' })
|
// the JWT expires. req.user carries the fresh DB row, not the token payload.
|
||||||
|
async function isLoggedIn(req, res, next) {
|
||||||
|
const decoded = getUserFromRequest(req)
|
||||||
|
if (!decoded) return res.status(401).json({ message: 'Unauthorized' })
|
||||||
|
try {
|
||||||
|
const user = await users.getById(decoded.id)
|
||||||
|
if (!user) return res.status(401).json({ message: 'Unauthorized' }) // deleted since token issued
|
||||||
req.user = user
|
req.user = user
|
||||||
return next()
|
return next()
|
||||||
|
} catch (err) {
|
||||||
|
log.error('isLoggedIn', err)
|
||||||
|
return res.status(500).json({ message: 'Internal Server Error' })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
Reference in New Issue
Block a user