Remove remaining SecurityClient auth calls in favor of hooks, keep RouteGuard

This commit is contained in:
Tuan Dang
2023-08-11 11:27:33 +07:00
parent 2dba7847b6
commit a4edf6bd0c
40 changed files with 443 additions and 910 deletions
@@ -3,7 +3,9 @@ import React, { useState } from "react";
import ReactCodeInput from "react-code-input";
import { useTranslation } from "react-i18next";
import sendVerificationEmail from "@app/pages/api/auth/SendVerificationEmail";
import {
useSendVerificationEmail
} from "@app/hooks/api";
import Error from "../basic/Error";
import { Button } from "../v2";
@@ -70,6 +72,7 @@ export default function CodeInputStep({
codeError,
isCodeInputCheckLoading
}: CodeInputStepProps): JSX.Element {
const { mutateAsync } = useSendVerificationEmail();
const [isLoading, setIsLoading] = useState(false);
const [isResendingVerificationEmail, setIsResendingVerificationEmail] = useState(false);
const { t } = useTranslation();
@@ -77,7 +80,7 @@ export default function CodeInputStep({
const resendVerificationEmail = async () => {
setIsResendingVerificationEmail(true);
setIsLoading(true);
sendVerificationEmail(email);
await mutateAsync({ email });
setTimeout(() => {
setIsLoading(false);
setIsResendingVerificationEmail(false);
@@ -2,7 +2,7 @@ import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import Link from "next/link";
import sendVerificationEmail from "@app/pages/api/auth/SendVerificationEmail";
import { useSendVerificationEmail } from "@app/hooks/api";
import { Button, Input } from "../v2";
@@ -25,13 +25,14 @@ export default function EnterEmailStep({
setEmail,
incrementStep
}: DownloadBackupPDFStepProps): JSX.Element {
const { mutateAsync } = useSendVerificationEmail();
const [emailError, setEmailError] = useState(false);
const { t } = useTranslation();
/**
* Verifies if the entered email "looks" correct
*/
const emailCheck = () => {
const emailCheck = async () => {
let emailCheckBool = false;
if (!email) {
setEmailError(true);
@@ -45,7 +46,7 @@ export default function EnterEmailStep({
// If everything is correct, go to the next step
if (!emailCheckBool) {
sendVerificationEmail(email);
await mutateAsync({ email });
incrementStep();
}
};
@@ -9,8 +9,8 @@ import nacl from "tweetnacl";
import { encodeBase64 } from "tweetnacl-util";
import { useGetCommonPasswords } from "@app/hooks/api";
import { completeAccountSignup } from "@app/hooks/api/auth/queries";
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
import completeAccountInformationSignup from "@app/pages/api/auth/CompleteAccountInformationSignup";
import ProjectService from "@app/services/ProjectService";
import InputField from "../basic/InputField";
@@ -159,7 +159,7 @@ export default function UserInfoStep({
secret: Buffer.from(derivedKey.hash)
});
const response = await completeAccountInformationSignup({
const response = await completeAccountSignup({
email,
firstName: name.split(" ")[0],
lastName: name.split(" ").slice(1).join(" "),
@@ -3,8 +3,9 @@ import crypto from "crypto";
import jsrp from "jsrp";
import changePassword2 from "@app/pages/api/auth/ChangePassword2";
import SRP1 from "@app/pages/api/auth/SRP1";
import {
changePassword,
srp1} from "@app/hooks/api/auth/queries";
import Aes256Gcm from "./cryptography/aes-256-gcm";
import { deriveArgonKey } from "./cryptography/crypto";
@@ -27,7 +28,7 @@ const attemptChangePassword = ({ email, currentPassword, newPassword }: Params):
try {
const clientPublicKey = clientOldPassword.getPublicKey();
const res = await SRP1({ clientPublicKey });
const res = await srp1({ clientPublicKey });
serverPublicKey = res.serverPublicKey;
salt = res.salt;
@@ -71,7 +72,7 @@ const attemptChangePassword = ({ email, currentPassword, newPassword }: Params):
secret: Buffer.from(derivedKey.hash)
});
await changePassword2({
await changePassword({
clientProof,
protectedKey,
protectedKeyIV,
@@ -1,10 +1,9 @@
/* eslint-disable prefer-destructuring */
import jsrp from "jsrp";
import { login1, login2 } from "@app/hooks/api/auth/queries";
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
import { fetchMyOrganizationProjects } from "@app/hooks/api/users/queries";
import login1 from "@app/pages/api/auth/Login1";
import login2 from "@app/pages/api/auth/Login2";
import KeyService from "@app/services/KeyService";
import Telemetry from "./telemetry/Telemetry";
@@ -1,10 +1,10 @@
/* eslint-disable prefer-destructuring */
import jsrp from "jsrp";
import { login1 , verifyMfaToken } from "@app/hooks/api/auth/queries";
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
import { fetchMyOrganizationProjects } from "@app/hooks/api/users/queries";
import login1 from "@app/pages/api/auth/Login1";
import verifyMfaToken from "@app/pages/api/auth/verifyMfaToken";
// import verifyMfaToken from "@app/pages/api/auth/verifyMfaToken";
import KeyService from "@app/services/KeyService";
import { saveTokenToLocalStorage } from "./saveTokenToLocalStorage";
@@ -65,7 +65,7 @@ const attemptLoginMfa = async ({
tag
} = await verifyMfaToken({
email,
mfaToken
mfaCode: mfaToken
});
// unset temporary (MFA) JWT token and set JWT token
@@ -1,10 +1,9 @@
/* eslint-disable prefer-destructuring */
import jsrp from "jsrp";
import { login1, login2 } from "@app/hooks/api/auth/queries";
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
import { fetchMyOrganizationProjects } from "@app/hooks/api/users/queries";
import login1 from "@app/pages/api/auth/Login1";
import login2 from "@app/pages/api/auth/Login2";
import KeyService from "@app/services/KeyService";
import Telemetry from "./telemetry/Telemetry";
@@ -46,12 +45,13 @@ const attemptLogin = async (
async () => {
try {
const clientPublicKey = client.getPublicKey();
const { serverPublicKey, salt } = await login1({
email,
clientPublicKey,
providerAuthToken,
});
client.setSalt(salt);
client.setServerPublicKey(serverPublicKey);
const clientProof = client.getProof(); // called M1
@@ -1,10 +1,9 @@
/* eslint-disable prefer-destructuring */
import jsrp from "jsrp";
import { login1 , verifyMfaToken } from "@app/hooks/api/auth/queries";
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
import { fetchMyOrganizationProjects } from "@app/hooks/api/users/queries";
import login1 from "@app/pages/api/auth/Login1";
import verifyMfaToken from "@app/pages/api/auth/verifyMfaToken";
import KeyService from "@app/services/KeyService";
import { saveTokenToLocalStorage } from "./saveTokenToLocalStorage";
@@ -56,7 +55,7 @@ const attemptLoginMfa = async ({
tag
} = await verifyMfaToken({
email,
mfaToken
mfaCode: mfaToken
});
// unset temporary (MFA) JWT token and set JWT token
@@ -1,147 +0,0 @@
/* eslint-disable new-cap */
import crypto from "crypto";
import jsrp from "jsrp";
import changePassword2 from "@app/pages/api/auth/ChangePassword2";
import SRP1 from "@app/pages/api/auth/SRP1";
import { saveTokenToLocalStorage } from "../saveTokenToLocalStorage";
import Aes256Gcm from "./aes-256-gcm";
import { deriveArgonKey } from "./crypto";
const clientOldPassword = new jsrp.client();
const clientNewPassword = new jsrp.client();
/**
* This function loggs in the user (whether it's right after signup, or a normal login)
* @param {*} email
* @param {*} password
* @param {*} setErrorLogin
* @param {*} router
* @param {*} isSignUp
* @returns
*/
const changePassword = async (
email: string,
currentPassword: string,
newPassword: string,
setCurrentPasswordError: (arg: boolean) => void,
setPasswordChanged: (arg: boolean) => void,
setCurrentPassword: (arg: string) => void,
setNewPassword: (arg: string) => void
) => {
try {
setPasswordChanged(false);
setCurrentPasswordError(false);
clientOldPassword.init(
{
username: email,
password: currentPassword
},
async () => {
const clientPublicKey = clientOldPassword.getPublicKey();
let serverPublicKey;
let salt;
try {
const res = await SRP1({
clientPublicKey
});
serverPublicKey = res.serverPublicKey;
salt = res.salt;
} catch (err) {
setCurrentPasswordError(true);
console.log("Wrong current password", err, 1);
}
clientOldPassword.setSalt(salt);
clientOldPassword.setServerPublicKey(serverPublicKey);
const clientProof = clientOldPassword.getProof(); // called M1
clientNewPassword.init(
{
username: email,
password: newPassword
},
async () => {
clientNewPassword.createVerifier(async (err, result) => {
const derivedKey = await deriveArgonKey({
password: newPassword,
salt: result.salt,
mem: 65536,
time: 3,
parallelism: 1,
hashLen: 32
});
if (!derivedKey) throw new Error("Failed to derive key from password");
const key = crypto.randomBytes(32);
// create encrypted private key by encrypting the private
// key with the symmetric key [key]
const {
ciphertext: encryptedPrivateKey,
iv: encryptedPrivateKeyIV,
tag: encryptedPrivateKeyTag
} = Aes256Gcm.encrypt({
text: localStorage.getItem("PRIVATE_KEY") as string,
secret: key
});
// create the protected key by encrypting the symmetric key
// [key] with the derived key
const {
ciphertext: protectedKey,
iv: protectedKeyIV,
tag: protectedKeyTag
} = Aes256Gcm.encrypt({
text: key.toString("hex"),
secret: Buffer.from(derivedKey.hash)
});
try {
await changePassword2({
clientProof,
protectedKey,
protectedKeyIV,
protectedKeyTag,
encryptedPrivateKey,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag,
salt: result.salt,
verifier: result.verifier
});
saveTokenToLocalStorage({
encryptedPrivateKey,
iv: encryptedPrivateKeyIV,
tag: encryptedPrivateKeyTag
});
setPasswordChanged(true);
setCurrentPassword("");
setNewPassword("");
window.location.href = "/login";
// move to login page
} catch (error) {
setCurrentPasswordError(true);
console.log(error);
}
});
}
);
}
);
} catch (error) {
console.log("Something went wrong during changing the password");
}
return true;
};
export default changePassword;
@@ -3,8 +3,9 @@ import crypto from "crypto";
import jsrp from "jsrp";
import issueBackupPrivateKey from "@app/pages/api/auth/IssueBackupPrivateKey";
import SRP1 from "@app/pages/api/auth/SRP1";
import { issueBackupPrivateKey ,
srp1
} from "@app/hooks/api/auth/queries";
import generateBackupPDF from "../generateBackupPDF";
import Aes256Gcm from "./aes-256-gcm";
@@ -51,7 +52,7 @@ const issueBackupKey = async ({
let serverPublicKey;
let salt;
try {
const res = await SRP1({
const res = await srp1({
clientPublicKey
});
serverPublicKey = res.serverPublicKey;
@@ -61,8 +62,8 @@ const issueBackupKey = async ({
console.log("Wrong current password", err, 1);
}
clientPassword.setSalt(salt);
clientPassword.setServerPublicKey(serverPublicKey);
clientPassword.setSalt(salt as string);
clientPassword.setServerPublicKey(serverPublicKey as string);
const clientProof = clientPassword.getProof(); // called M1
const generatedKey = crypto.randomBytes(16).toString("hex");
@@ -80,24 +81,25 @@ const issueBackupKey = async ({
secret: generatedKey
});
const res = await issueBackupPrivateKey({
encryptedPrivateKey: ciphertext,
iv,
tag,
salt: result.salt,
verifier: result.verifier,
clientProof
});
try {
await issueBackupPrivateKey({
encryptedPrivateKey: ciphertext,
iv,
tag,
salt: result.salt,
verifier: result.verifier,
clientProof
});
if (res?.status === 400) {
setBackupKeyError(true);
} else if (res?.status === 200) {
generateBackupPDF({
personalName,
personalEmail: email,
generatedKey
});
setBackupKeyIssued(true);
} catch {
setBackupKeyError(true);
}
}
);