mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-20 16:04:16 +00:00
171 lines
5.1 KiB
JavaScript
Executable File
171 lines
5.1 KiB
JavaScript
Executable File
import jwt from "jsonwebtoken"
|
|
import { Session, RegenerationToken } from "../../models"
|
|
|
|
export async function regenerateSession(expiredToken, refreshToken) {
|
|
// search for a regeneration token with the expired token (Should exist only one)
|
|
const regenerationToken = await RegenerationToken.findOne({ refreshToken: refreshToken })
|
|
|
|
if (!regenerationToken) {
|
|
throw new Error("Cannot find regeneration token")
|
|
}
|
|
|
|
// check if the regeneration token is valid and not expired
|
|
let decodedRefreshToken = null
|
|
let decodedExpiredToken = null
|
|
|
|
try {
|
|
decodedRefreshToken = jwt.decode(refreshToken)
|
|
decodedExpiredToken = jwt.decode(expiredToken)
|
|
} catch (error) {
|
|
console.error(error)
|
|
// TODO: Storage this incident
|
|
}
|
|
|
|
if (!decodedRefreshToken) {
|
|
throw new Error("Cannot decode refresh token")
|
|
}
|
|
|
|
if (!decodedExpiredToken) {
|
|
throw new Error("Cannot decode expired token")
|
|
}
|
|
|
|
// is not needed to verify the expired token, because it suppossed to be expired
|
|
|
|
// verify refresh token
|
|
await jwt.verify(refreshToken, global.jwtStrategy.secretOrKey, async (err) => {
|
|
// check if is expired
|
|
if (err) {
|
|
if (err.message === "jwt expired") {
|
|
// check if server has enabled the enforcement of regeneration token expiration
|
|
if (global.jwtStrategy.enforceRegenerationTokenExpiration) {
|
|
// delete the regeneration token
|
|
await RegenerationToken.deleteOne({ refreshToken: refreshToken })
|
|
|
|
throw new Error("Regeneration token expired and cannot be regenerated due server has enabled enforcement security policy")
|
|
}
|
|
}
|
|
}
|
|
|
|
// check if the regeneration token is associated with the expired token
|
|
if (decodedRefreshToken.expiredToken !== expiredToken) {
|
|
throw new Error("Regeneration token is not associated with the expired token")
|
|
}
|
|
})
|
|
|
|
// find the session associated with the expired token
|
|
const session = await Session.findOne({ token: expiredToken })
|
|
|
|
if (!session) {
|
|
throw new Error("Cannot find session associated with the expired token")
|
|
}
|
|
|
|
// generate a new token
|
|
const newToken = await createNewAuthToken(decodedExpiredToken, {
|
|
updateSession: session._id,
|
|
})
|
|
|
|
// delete the regeneration token
|
|
await RegenerationToken.deleteOne({ refreshToken: refreshToken })
|
|
|
|
return newToken
|
|
}
|
|
|
|
export async function getRegenerationToken(expiredToken) {
|
|
const regenerationToken = await RegenerationToken.findOne({ expiredToken }).catch((error) => false)
|
|
|
|
return regenerationToken ?? false
|
|
}
|
|
|
|
export async function createNewRegenerationToken(expiredToken) {
|
|
// check if token is only expired, if is corrupted, reject
|
|
let decoded = null
|
|
|
|
try {
|
|
decoded = jwt.decode(expiredToken)
|
|
} catch (error) {
|
|
console.error(error)
|
|
}
|
|
|
|
if (!decoded) {
|
|
return false
|
|
}
|
|
|
|
// check if token exists on a session
|
|
const sessions = await Session.find({ user_id: decoded.user_id })
|
|
const currentSession = sessions.find((session) => session.token === expiredToken)
|
|
|
|
if (!currentSession) {
|
|
throw new Error("This token is not associated with any session")
|
|
}
|
|
|
|
// create a new refresh token and sign it with maximum expiration time of 1 day
|
|
const refreshToken = jwt.sign(
|
|
{
|
|
expiredToken
|
|
},
|
|
global.jwtStrategy.secretOrKey,
|
|
{
|
|
expiresIn: "1d"
|
|
}
|
|
)
|
|
|
|
// create a new regeneration token and save it
|
|
const regenerationToken = new RegenerationToken({
|
|
expiredToken,
|
|
refreshToken,
|
|
})
|
|
|
|
await regenerationToken.save()
|
|
|
|
// return the regeneration token
|
|
return regenerationToken
|
|
}
|
|
|
|
export async function createNewAuthToken(user, options = {}) {
|
|
const payload = {
|
|
user_id: user._id ?? user.user_id,
|
|
username: user.username,
|
|
email: user.email,
|
|
signLocation: global.signLocation,
|
|
}
|
|
|
|
return await signNewAuthToken(payload, options)
|
|
}
|
|
|
|
export async function signNewAuthToken(payload, options = {}) {
|
|
if (options.updateSession) {
|
|
const sessionData = await Session.findOne({ _id: options.updateSession })
|
|
|
|
payload.session_uuid = sessionData.session_uuid
|
|
} else {
|
|
payload.session_uuid = global.nanoid()
|
|
}
|
|
|
|
const token = jwt.sign(payload, global.jwtStrategy.secretOrKey, {
|
|
expiresIn: global.jwtStrategy.expiresIn ?? "1h",
|
|
algorithm: global.jwtStrategy.algorithm ?? "HS256"
|
|
})
|
|
|
|
const session = {
|
|
token: token,
|
|
session_uuid: payload.session_uuid,
|
|
username: payload.username,
|
|
user_id: payload.user_id,
|
|
date: new Date().getTime(),
|
|
location: payload.signLocation ?? "rs-auth",
|
|
}
|
|
|
|
if (options.updateSession) {
|
|
await Session.findByIdAndUpdate(options.updateSession, {
|
|
token: session.token,
|
|
date: session.date,
|
|
location: session.location,
|
|
})
|
|
} else {
|
|
let newSession = new Session(session)
|
|
|
|
await newSession.save()
|
|
}
|
|
|
|
return token
|
|
} |