I'm not senior in Node/Express/Passport and here is what I currently have set up on my application I have a LocalStrategy on my Login request that allow me to connect with email and password.
passport.js
passport.use(
new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password'
},
async (email, password, done) => {
try {
const user = await User.findOne({ email })
if (!user || !user.comparePassword(password)) {
return done(null, false, { message: 'Invalid email or password' })
}
const _user = user.toJSON()
return done(null, { ..._user})
} catch (error) {
return done(error)
}
}
)
)
app.js
app.post('/api/login', (req, res, next) => {
passport.authenticate('local', { session: false }, (err, user, info) => {
if (err || !user) {
return res.status(400).json({ message: 'Invalid email or password' })
}
req.login(user, { session: false }, (err) => {
if (err) {
return res.status(500).json({ message: 'Internal server error' })
}
const token = jwt.sign(
{
sub: user._id
},
JWT_SECRET,
{ expiresIn: JWT_EXPIRATION_TIME }
)
res.cookie('jwt', token, { httpOnly: true })
return res.json({ user, token })
})
})(req, res, next)
})
Then i use a JwtStrategy on all others requests
passport.js
const cookieExtractor = function (req) {
let token = null
if (req && req.cookies.jwt) {
token = req.cookies.jwt
} else if (req && req.headers.authorization) {
token = req.headers.authorization.split(' ')[1]
}
return { token }
}
const jwtOptions = {
jwtFromRequest: cookieExtractor,
secretOrKey: process.env.JWT_SECRET
}
passport.use(
new JwtStrategy(jwtOptions, async (payload, done) => {
try {
const user = await User.findById(payload.sub)
// If the user doesn't exist, return an error
if (!user) {
return done(null, false)
}
const _user = user.toJSON()
return done(null, { ..._user})
} catch (error) {
return done(error)
}
})
)
app.js
app.use(
'/api',
passport.authenticate('jwt', { session: false }),
indexRouter(thirdParty)
)
After several research, I came to want to implement a more secure solution using 2 tokens, 1 access token stored in cookies and 1 refresh token stored in the frontend part in the sessionStorage/localStorage depending on the choice of a user to stay connected or not. In addition I would like to store all valid tokens in a cache using node-cache in order to add protection. I haven't been able to find a similar solution on the net or any cases that could help me move forward on stackoverflow. What I currently tried is to return a token via cookie and a token in the payload during login.
app.js -> /api/login
const refreshToken = jwt.sign(
{
sub: user._id
token: TOKEN_TYPE.REFRESH
},
JWT_SECRET,
{ expiresIn: JWT_EXPIRATION_TIME }
)
const accessToken = jwt.sign(
{
sub: user._id,
token: TOKEN_TYPE.ACCESS
},
JWT_SECRET,
{ expiresIn: JWT_EXPIRATION_TIME_ACCESS }
)
res.cookie('jwt', accessToken, { httpOnly: true })
// TODO: add refresh token to node-cache
return res.json({ user, refreshToken })
But I can't see how to make a request for the refresh token when the access token expires without going through the JwtStrategy cookieExtractor which will allow me to deserialize the refreshToken in order to have access to its data and be sure that 'it is still valid and if it is still valid to create 2 new access and refresh tokens which I return as in the login part (cookie and payload) And finally I was also wondering how I should store these tokens in my node-cache, deserialized or not and where do you think?
Thanks for the help