improve auth behavior

This commit is contained in:
SrGooglo 2023-04-04 12:30:23 +00:00
parent 1536573dd5
commit 09a39b69a9

View File

@ -12,111 +12,120 @@ export default async (req, res, next) => {
try {
const tokenAuthHeader = req.headers?.authorization?.split(" ")
const serverTokenHeader = req.headers?.server_token
if (!serverTokenHeader && !tokenAuthHeader) {
if (!tokenAuthHeader) {
return reject("Missing token header")
}
if (serverTokenHeader) {
const [client_id, token] = serverTokenHeader.split(":")
if (client_id === "undefined" || token === "undefined") {
return reject("Invalid server token")
}
const secureEntries = new SecureEntry(authorizedServerTokens)
const serverTokenEntry = await secureEntries.get(client_id, undefined, {
keyName: "client_id",
valueName: "token",
})
if (!serverTokenEntry) {
return reject("Invalid server token")
}
if (serverTokenEntry !== token) {
return reject("Missmatching server token")
}
req.user = {
__server: true,
_id: client_id,
roles: ["server"],
}
return next()
if (!tokenAuthHeader[1]) {
return reject("Recived header, missing token")
}
if (!serverTokenHeader && tokenAuthHeader && tokenAuthHeader[0] === "Bearer") {
const token = tokenAuthHeader[1]
let decoded = null
switch (tokenAuthHeader[0]) {
case "Bearer": {
const token = tokenAuthHeader[1]
let decoded = null
try {
decoded = jwt.decode(token)
} catch (error) {
console.error(error)
}
if (!decoded) {
return reject("Cannot decode token")
}
jwt.verify(token, global.jwtStrategy.secretOrKey, async (err) => {
const sessions = await Session.find({ user_id: decoded.user_id })
const currentSession = sessions.find((session) => session.token === token)
if (!currentSession) {
return reject("Cannot find session")
try {
decoded = jwt.decode(token)
} catch (error) {
console.error(error)
}
const userData = await User.findOne({ _id: currentSession.user_id }).select("+refreshToken")
if (!userData) {
return res.status(404).json({ error: "No user data found" })
if (!decoded) {
return reject("Cannot decode token")
}
// if cannot verify token, start regeneration process
if (err) {
// first check if token is only expired, if is corrupted, reject
if (err.name !== "TokenExpiredError") {
return reject("Invalid token, cannot regenerate")
jwt.verify(token, global.jwtStrategy.secretOrKey, async (err) => {
const sessions = await Session.find({ user_id: decoded.user_id })
const currentSession = sessions.find((session) => session.token === token)
if (!currentSession) {
return reject("Cannot find session")
}
let regenerationToken = null
const userData = await User.findOne({ _id: currentSession.user_id }).select("+refreshToken")
// check if this expired token has a regeneration token associated
const associatedRegenerationToken = await Token.getRegenerationToken(token)
if (!userData) {
return res.status(404).json({ error: "No user data found" })
}
if (associatedRegenerationToken) {
regenerationToken = associatedRegenerationToken.refreshToken
} else {
// create a new regeneration token with the expired token
regenerationToken = await Token.createNewRegenerationToken(token).catch((error) => {
// in case of error, reject
reject(error.message)
// if cannot verify token, start regeneration process
if (err) {
// first check if token is only expired, if is corrupted, reject
if (err.name !== "TokenExpiredError") {
return reject("Invalid token, cannot regenerate")
}
return null
let regenerationToken = null
// check if this expired token has a regeneration token associated
const associatedRegenerationToken = await Token.getRegenerationToken(token)
if (associatedRegenerationToken) {
regenerationToken = associatedRegenerationToken.refreshToken
} else {
// create a new regeneration token with the expired token
regenerationToken = await Token.createNewRegenerationToken(token).catch((error) => {
// in case of error, reject
reject(error.message)
return null
})
}
if (!regenerationToken) return
// now send the regeneration token to the client (start Expired Exception Event [EEE])
return res.status(401).json({
error: "Token expired",
refreshToken: regenerationToken.refreshToken,
})
}
if (!regenerationToken) return
req.user = userData
req.jwtToken = token
req.decodedToken = decoded
req.currentSession = currentSession
// now send the regeneration token to the client (start Expired Exception Event [EEE])
return res.status(401).json({
error: "Token expired",
refreshToken: regenerationToken.refreshToken,
})
return next()
})
break
}
case "Server": {
const [client_id, token] = tokenAuthHeader[1].split(":")
if (client_id === "undefined" || token === "undefined") {
return reject("Invalid server token")
}
req.user = userData
req.jwtToken = token
req.decodedToken = decoded
req.currentSession = currentSession
const secureEntries = new SecureEntry(authorizedServerTokens)
const serverTokenEntry = await secureEntries.get(client_id, undefined, {
keyName: "client_id",
valueName: "token",
})
if (!serverTokenEntry) {
return reject("Invalid server token")
}
if (serverTokenEntry !== token) {
return reject("Missmatching server token")
}
req.user = {
__server: true,
_id: client_id,
roles: ["server"],
}
return next()
})
}
default: {
return reject("Invalid token type")
}
}
} catch (error) {
console.error(error)