import React, { useState } from 'react'; import Image from 'next/image'; import { useRouter } from 'next/router'; import { faCheck, faX } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import Button from '~/components/basic/buttons/Button'; import InputField from '~/components/basic/InputField'; import passwordCheck from '~/components/utilities/checks/PasswordCheck'; import Aes256Gcm from '~/components/utilities/cryptography/aes-256-gcm'; import EmailVerifyOnPasswordReset from './api/auth/EmailVerifyOnPasswordReset'; import getBackupEncryptedPrivateKey from './api/auth/getBackupEncryptedPrivateKey'; import resetPasswordOnAccountRecovery from './api/auth/resetPasswordOnAccountRecovery'; const queryString = require('query-string'); const nacl = require('tweetnacl'); const jsrp = require('jsrp'); nacl.util = require('tweetnacl-util'); const client = new jsrp.client(); export default function PasswordReset() { const router = useRouter(); const parsedUrl = queryString.parse(router.asPath.split('?')[1]); const token = parsedUrl.token; const email = parsedUrl.to?.replace(' ', '+').trim(); const [verificationToken, setVerificationToken] = useState(''); const [step, setStep] = useState(1); const [backupKey, setBackupKey] = useState(''); const [privateKey, setPrivateKey] = useState(''); const [newPassword, setNewPassword] = useState(''); const [backupKeyError, setBackupKeyError] = useState(false); const [passwordErrorLength, setPasswordErrorLength] = useState(false); const [passwordErrorNumber, setPasswordErrorNumber] = useState(false); const [passwordErrorLowerCase, setPasswordErrorLowerCase] = useState(false); // Unencrypt the private key with a backup key const getEncryptedKeyHandler = async () => { try { const result = await getBackupEncryptedPrivateKey({ verificationToken }); setPrivateKey( Aes256Gcm.decrypt({ ciphertext: result.encryptedPrivateKey, iv: result.iv, tag: result.tag, secret: backupKey }) ); setStep(3); } catch { setBackupKeyError(true); } }; // If everything is correct, reset the password const resetPasswordHandler = async () => { let errorCheck = false; errorCheck = passwordCheck({ password: newPassword, setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, currentErrorCheck: errorCheck }); if (!errorCheck) { // Generate a random pair of a public and a private key const { ciphertext, iv, tag } = Aes256Gcm.encrypt({ text: privateKey, secret: newPassword .slice(0, 32) .padStart( 32 + (newPassword.slice(0, 32).length - new Blob([newPassword]).size), '0' ) }) as { ciphertext: string; iv: string; tag: string }; client.init( { username: email, password: newPassword }, async () => { client.createVerifier( async (err: any, result: { salt: string; verifier: string }) => { const response = await resetPasswordOnAccountRecovery({ verificationToken, encryptedPrivateKey: ciphertext, iv, tag, salt: result.salt, verifier: result.verifier }); // if everything works, go the main dashboard page. if (response?.status === 200) { router.push('/login'); } } ); } ); } }; // Click a button to confirm email const stepConfirmEmail = (

Confirm your email

verify email
); // Input backup key const stepInputBackupKey = (

Enter your backup key

You can find it in your emrgency kit. You had to download the enrgency kit during signup.

); // Enter new password const stepEnterNewPassword = (

Enter new password

Make sure you save it somewhere save.

{ setNewPassword(password); passwordCheck({ password, setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, currentErrorCheck: false }); }} type="password" value={newPassword} isRequired error={ passwordErrorLength && passwordErrorLowerCase && passwordErrorNumber } autoComplete="new-password" id="new-password" />
{passwordErrorLength || passwordErrorLowerCase || passwordErrorNumber ? (
Password should contain at least:
{passwordErrorLength ? ( ) : ( )}
14 characters
{passwordErrorLowerCase ? ( ) : ( )}
1 lowercase character
{passwordErrorNumber ? ( ) : ( )}
1 number
) : (
)}
); return (
{step === 1 && stepConfirmEmail} {step === 2 && stepInputBackupKey} {step === 3 && stepEnterNewPassword}
); }