This commit is contained in:
Vladyslav Matsiiako
2023-01-29 15:55:22 -08:00
@@ -9,8 +9,8 @@ import { checkEmailVerification } from '../../helpers/signup';
import { createToken } from '../../helpers/auth'; import { createToken } from '../../helpers/auth';
import { sendMail } from '../../helpers/nodemailer'; import { sendMail } from '../../helpers/nodemailer';
import { JWT_SIGNUP_LIFETIME, JWT_SIGNUP_SECRET, SITE_URL } from '../../config'; import { JWT_SIGNUP_LIFETIME, JWT_SIGNUP_SECRET, SITE_URL } from '../../config';
import LoginSRPDetail from '../../models/LoginSRPDetail';
const clientPublicKeys: any = {}; import { BadRequestError } from '../../utils/errors';
/** /**
* Password reset step 1: Send email verification link to email [email] * Password reset step 1: Send email verification link to email [email]
@@ -32,7 +32,7 @@ export const emailPasswordReset = async (req: Request, res: Response) => {
error: 'Failed to send email verification for password reset' error: 'Failed to send email verification for password reset'
}); });
} }
const token = crypto.randomBytes(16).toString('hex'); const token = crypto.randomBytes(16).toString('hex');
await Token.findOneAndUpdate( await Token.findOneAndUpdate(
@@ -44,7 +44,7 @@ export const emailPasswordReset = async (req: Request, res: Response) => {
}, },
{ upsert: true, new: true } { upsert: true, new: true }
); );
await sendMail({ await sendMail({
template: 'passwordReset.handlebars', template: 'passwordReset.handlebars',
subjectLine: 'Infisical password reset', subjectLine: 'Infisical password reset',
@@ -55,15 +55,15 @@ export const emailPasswordReset = async (req: Request, res: Response) => {
callback_url: SITE_URL + '/password-reset' callback_url: SITE_URL + '/password-reset'
} }
}); });
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
return res.status(400).send({ return res.status(400).send({
message: 'Failed to send email for account recovery' message: 'Failed to send email for account recovery'
}); });
} }
return res.status(200).send({ return res.status(200).send({
message: `Sent an email for account recovery to ${email}` message: `Sent an email for account recovery to ${email}`
}); });
@@ -79,7 +79,7 @@ export const emailPasswordResetVerify = async (req: Request, res: Response) => {
let user, token; let user, token;
try { try {
const { email, code } = req.body; const { email, code } = req.body;
user = await User.findOne({ email }).select('+publicKey'); user = await User.findOne({ email }).select('+publicKey');
if (!user || !user?.publicKey) { if (!user || !user?.publicKey) {
// case: user doesn't exist with email [email] or // case: user doesn't exist with email [email] or
@@ -93,7 +93,7 @@ export const emailPasswordResetVerify = async (req: Request, res: Response) => {
email, email,
code code
}); });
// generate temporary password-reset token // generate temporary password-reset token
token = createToken({ token = createToken({
payload: { payload: {
@@ -107,7 +107,7 @@ export const emailPasswordResetVerify = async (req: Request, res: Response) => {
Sentry.captureException(err); Sentry.captureException(err);
return res.status(400).send({ return res.status(400).send({
message: 'Failed email verification for password reset' message: 'Failed email verification for password reset'
}); });
} }
return res.status(200).send({ return res.status(200).send({
@@ -130,7 +130,7 @@ export const srp1 = async (req: Request, res: Response) => {
const user = await User.findOne({ const user = await User.findOne({
email: req.user.email email: req.user.email
}).select('+salt +verifier'); }).select('+salt +verifier');
if (!user) throw new Error('Failed to find user'); if (!user) throw new Error('Failed to find user');
const server = new jsrp.server(); const server = new jsrp.server();
@@ -139,13 +139,15 @@ export const srp1 = async (req: Request, res: Response) => {
salt: user.salt, salt: user.salt,
verifier: user.verifier verifier: user.verifier
}, },
() => { async () => {
// generate server-side public key // generate server-side public key
const serverPublicKey = server.getPublicKey(); const serverPublicKey = server.getPublicKey();
clientPublicKeys[req.user.email] = {
clientPublicKey, await LoginSRPDetail.findOneAndReplace({ email: req.user.email }, {
serverBInt: bigintConversion.bigintToBuf(server.bInt) email: req.user.email,
}; clientPublicKey: clientPublicKey,
serverBInt: bigintConversion.bigintToBuf(server.bInt),
}, { upsert: true, returnNewDocument: false })
return res.status(200).send({ return res.status(200).send({
serverPublicKey, serverPublicKey,
@@ -180,17 +182,21 @@ export const changePassword = async (req: Request, res: Response) => {
if (!user) throw new Error('Failed to find user'); if (!user) throw new Error('Failed to find user');
const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email })
if (!loginSRPDetailFromDB) {
return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again"))
}
const server = new jsrp.server(); const server = new jsrp.server();
server.init( server.init(
{ {
salt: user.salt, salt: user.salt,
verifier: user.verifier, verifier: user.verifier,
b: clientPublicKeys[req.user.email].serverBInt b: loginSRPDetailFromDB.serverBInt
}, },
async () => { async () => {
server.setClientPublicKey( server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey);
clientPublicKeys[req.user.email].clientPublicKey
);
// compare server and client shared keys // compare server and client shared keys
if (server.checkClientProof(clientProof)) { if (server.checkClientProof(clientProof)) {
@@ -249,16 +255,22 @@ export const createBackupPrivateKey = async (req: Request, res: Response) => {
if (!user) throw new Error('Failed to find user'); if (!user) throw new Error('Failed to find user');
const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email })
if (!loginSRPDetailFromDB) {
return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again"))
}
const server = new jsrp.server(); const server = new jsrp.server();
server.init( server.init(
{ {
salt: user.salt, salt: user.salt,
verifier: user.verifier, verifier: user.verifier,
b: clientPublicKeys[req.user.email].serverBInt b: loginSRPDetailFromDB.serverBInt
}, },
async () => { async () => {
server.setClientPublicKey( server.setClientPublicKey(
clientPublicKeys[req.user.email].clientPublicKey loginSRPDetailFromDB.clientPublicKey
); );
// compare server and client shared keys // compare server and client shared keys
@@ -311,16 +323,16 @@ export const getBackupPrivateKey = async (req: Request, res: Response) => {
backupPrivateKey = await BackupPrivateKey.findOne({ backupPrivateKey = await BackupPrivateKey.findOne({
user: req.user._id user: req.user._id
}).select('+encryptedPrivateKey +iv +tag'); }).select('+encryptedPrivateKey +iv +tag');
if (!backupPrivateKey) throw new Error('Failed to find backup private key'); if (!backupPrivateKey) throw new Error('Failed to find backup private key');
} catch (err) { } catch (err) {
Sentry.setUser({ email: req.user.email}); Sentry.setUser({ email: req.user.email });
Sentry.captureException(err); Sentry.captureException(err);
return res.status(400).send({ return res.status(400).send({
message: 'Failed to get backup private key' message: 'Failed to get backup private key'
}); });
} }
return res.status(200).send({ return res.status(200).send({
backupPrivateKey backupPrivateKey
}); });
@@ -348,15 +360,15 @@ export const resetPassword = async (req: Request, res: Response) => {
{ {
new: true new: true
} }
); );
} catch (err) { } catch (err) {
Sentry.setUser({ email: req.user.email}); Sentry.setUser({ email: req.user.email });
Sentry.captureException(err); Sentry.captureException(err);
return res.status(400).send({ return res.status(400).send({
message: 'Failed to get backup private key' message: 'Failed to get backup private key'
}); });
} }
return res.status(200).send({ return res.status(200).send({
message: 'Successfully reset password' message: 'Successfully reset password'
}); });