add create user and login user parts
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
// app/utils/refreshSession.util.js
|
||||
|
||||
const crypto = require("crypto");
|
||||
|
||||
const {
|
||||
generateRefreshToken,
|
||||
verifyRefreshToken,
|
||||
} = require("./jwt.util");
|
||||
|
||||
const refreshSessions = new Map();
|
||||
|
||||
|
||||
// Default = 7 days
|
||||
const REFRESH_SESSION_TTL =
|
||||
7 * 24 * 60 * 60 * 1000;
|
||||
|
||||
|
||||
const hashRefreshToken = (token) => {
|
||||
return crypto
|
||||
.createHash("sha256")
|
||||
.update(token)
|
||||
.digest("hex");
|
||||
};
|
||||
|
||||
const createRefreshSession = (userId) => {
|
||||
|
||||
// Unique session ID
|
||||
const sessionId =
|
||||
crypto.randomUUID();
|
||||
|
||||
|
||||
// Create raw Refresh JWT
|
||||
const refreshToken =
|
||||
generateRefreshToken({
|
||||
sub: userId,
|
||||
sid: sessionId,
|
||||
});
|
||||
|
||||
|
||||
// Hash raw refresh token
|
||||
const tokenHash =
|
||||
hashRefreshToken(
|
||||
refreshToken
|
||||
);
|
||||
|
||||
|
||||
// Expiration time
|
||||
const expiresAt =
|
||||
Date.now() +
|
||||
REFRESH_SESSION_TTL;
|
||||
|
||||
|
||||
// Save only HASH in RAM
|
||||
refreshSessions.set(
|
||||
sessionId,
|
||||
{
|
||||
userId,
|
||||
tokenHash,
|
||||
expiresAt,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
return {
|
||||
refreshToken,
|
||||
sessionId,
|
||||
};
|
||||
};
|
||||
|
||||
const validateRefreshSession = (
|
||||
refreshToken
|
||||
) => {
|
||||
|
||||
if (!refreshToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
let decoded;
|
||||
|
||||
try {
|
||||
|
||||
decoded =
|
||||
verifyRefreshToken(
|
||||
refreshToken
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
const sessionId =
|
||||
decoded.sid;
|
||||
|
||||
const userId =
|
||||
decoded.sub;
|
||||
|
||||
|
||||
if (!sessionId || !userId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Get session from RAM
|
||||
const session =
|
||||
refreshSessions.get(
|
||||
sessionId
|
||||
);
|
||||
|
||||
|
||||
if (!session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Check session expiration
|
||||
if (
|
||||
Date.now() >
|
||||
session.expiresAt
|
||||
) {
|
||||
|
||||
refreshSessions.delete(
|
||||
sessionId
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Hash received refresh token
|
||||
const receivedHash =
|
||||
hashRefreshToken(
|
||||
refreshToken
|
||||
);
|
||||
|
||||
|
||||
// Compare stored hash
|
||||
if (
|
||||
receivedHash !==
|
||||
session.tokenHash
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Extra user check
|
||||
if (
|
||||
session.userId !==
|
||||
userId
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
userId,
|
||||
sessionId,
|
||||
};
|
||||
};
|
||||
|
||||
const deleteRefreshSession = (
|
||||
sessionId
|
||||
) => {
|
||||
|
||||
refreshSessions.delete(
|
||||
sessionId
|
||||
);
|
||||
};
|
||||
|
||||
const deleteAllUserSessions = (
|
||||
userId
|
||||
) => {
|
||||
|
||||
for (
|
||||
const [sessionId, session]
|
||||
of refreshSessions.entries()
|
||||
) {
|
||||
|
||||
if (
|
||||
session.userId === userId
|
||||
) {
|
||||
|
||||
refreshSessions.delete(
|
||||
sessionId
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
createRefreshSession,
|
||||
validateRefreshSession,
|
||||
deleteRefreshSession,
|
||||
deleteAllUserSessions,
|
||||
};
|
||||
Reference in New Issue
Block a user