Skip to content

Commit

Permalink
handleLogin vulnerablity closes #23
Browse files Browse the repository at this point in the history
  • Loading branch information
Louis3797 committed Nov 8, 2024
1 parent f882b36 commit 7c05dc3
Showing 1 changed file with 74 additions and 52 deletions.
126 changes: 74 additions & 52 deletions src/controller/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,70 +132,92 @@ export const handleLogin = async (
});
}

// Generating the dummy hash dynamically may introduce a slight performance overhead, as argon2.hash()
// is a computationally expensive operation.
// However, this is generally negligible compared to the security benefits it provides
const dummyPassword = 'dummy_password';
const dummyHash = await argon2.hash(dummyPassword);

// Use the user's hash if found, otherwise use the dummy hash
const userPasswordHash = user ? user.password : dummyHash;

// check password
try {
if (await argon2.verify(user.password, password)) {
// if there is a refresh token in the req.cookie, then we need to check if this
// refresh token exists in the database and belongs to the current user than we need to delete it
// if the token does not belong to the current user, then we delete all refresh tokens
// of the user stored in the db to be on the safe site
// we also clear the cookie in both cases
if (cookies?.[config.jwt.refresh_token.cookie_name]) {
// check if the given refresh token is from the current user
const checkRefreshToken = await prismaClient.refreshToken.findUnique({
const isPasswordValid = await argon2.verify(userPasswordHash, password);

// Check if email is verified
// Check for verified email after verifying the password to prevent user enumeration attacks
if (!user.emailVerified) {
return res.status(httpStatus.UNAUTHORIZED).json({
message: 'Your email is not verified! Please confirm your email!'
});
}

// If password is invalid, return unauthorized
if (!isPasswordValid) {
return res.status(httpStatus.UNAUTHORIZED).json({
message: 'Invalid email or password!'
});
}

// if there is a refresh token in the req.cookie, then we need to check if this
// refresh token exists in the database and belongs to the current user than we need to delete it
// if the token does not belong to the current user, then we delete all refresh tokens
// of the user stored in the db to be on the safe site
// we also clear the cookie in both cases
if (cookies?.[config.jwt.refresh_token.cookie_name]) {
// check if the given refresh token is from the current user
const checkRefreshToken = await prismaClient.refreshToken.findUnique({
where: {
token: cookies[config.jwt.refresh_token.cookie_name]
}
});

// if this token does not exists int the database or belongs to another user,
// then we clear all refresh tokens from the user in the db
if (!checkRefreshToken || checkRefreshToken.userId !== user.id) {
await prismaClient.refreshToken.deleteMany({
where: {
userId: user.id
}
});
} else {
// else everything is fine and we just need to delete the one token
await prismaClient.refreshToken.delete({
where: {
token: cookies[config.jwt.refresh_token.cookie_name]
}
});

// if this token does not exists int the database or belongs to another user,
// then we clear all refresh tokens from the user in the db
if (!checkRefreshToken || checkRefreshToken.userId !== user.id) {
await prismaClient.refreshToken.deleteMany({
where: {
userId: user.id
}
});
} else {
// else everything is fine and we just need to delete the one token
await prismaClient.refreshToken.delete({
where: {
token: cookies[config.jwt.refresh_token.cookie_name]
}
});
}

// also clear the refresh token in the cookie
res.clearCookie(
config.jwt.refresh_token.cookie_name,
clearRefreshTokenCookieConfig
);
}

const accessToken = createAccessToken(user.id);
// also clear the refresh token in the cookie
res.clearCookie(
config.jwt.refresh_token.cookie_name,
clearRefreshTokenCookieConfig
);
}

const newRefreshToken = createRefreshToken(user.id);
const accessToken = createAccessToken(user.id);

// store new refresh token in db
await prismaClient.refreshToken.create({
data: {
token: newRefreshToken,
userId: user.id
}
});
const newRefreshToken = createRefreshToken(user.id);

// save refresh token in cookie
res.cookie(
config.jwt.refresh_token.cookie_name,
newRefreshToken,
refreshTokenCookieConfig
);
// store new refresh token in db
await prismaClient.refreshToken.create({
data: {
token: newRefreshToken,
userId: user.id
}
});

// send access token per json to user so it can be stored in the localStorage
return res.json({ accessToken });
} else {
return res.status(httpStatus.UNAUTHORIZED);
}
// save refresh token in cookie
res.cookie(
config.jwt.refresh_token.cookie_name,
newRefreshToken,
refreshTokenCookieConfig
);

// send access token per json to user so it can be stored in the localStorage
return res.json({ accessToken });
} catch (err) {
return res.status(httpStatus.INTERNAL_SERVER_ERROR);
}
Expand Down

0 comments on commit 7c05dc3

Please sign in to comment.