/* eslint-disable no-nested-ternary */ /* eslint-disable @typescript-eslint/no-unused-vars */ import crypto from 'crypto'; import { useState } from 'react'; import Head from 'next/head'; import Image from 'next/image'; import Link from 'next/link'; import { useRouter } from 'next/router'; import { faCheck, faWarning, faX } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import jsrp from 'jsrp'; import queryString from 'query-string'; import nacl from 'tweetnacl'; import { encodeBase64 } from 'tweetnacl-util'; import Button from '@app/components/basic/buttons/Button'; import InputField from '@app/components/basic/InputField'; import attemptLogin from '@app/components/utilities/attemptLogin'; import passwordCheck from '@app/components/utilities/checks/PasswordCheck'; import Aes256Gcm from '@app/components/utilities/cryptography/aes-256-gcm'; import { deriveArgonKey } from '@app/components/utilities/cryptography/crypto'; import issueBackupKey from '@app/components/utilities/cryptography/issueBackupKey'; import { saveTokenToLocalStorage } from '@app/components/utilities/saveTokenToLocalStorage'; import SecurityClient from '@app/components/utilities/SecurityClient'; import getOrganizations from '@app/pages/api/organization/getOrgs'; import getOrganizationUserProjects from '@app/pages/api/organization/GetOrgUserProjects'; import completeAccountInformationSignupInvite from './api/auth/CompleteAccountInformationSignupInvite'; import verifySignupInvite from './api/auth/VerifySignupInvite'; // eslint-disable-next-line new-cap const client = new jsrp.client(); export default function SignupInvite() { const [password, setPassword] = useState(''); const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const [firstNameError, setFirstNameError] = useState(false); const [lastNameError, setLastNameError] = useState(false); const [passwordErrorLength, setPasswordErrorLength] = useState(false); const [passwordErrorNumber, setPasswordErrorNumber] = useState(false); const [passwordErrorLowerCase, setPasswordErrorLowerCase] = useState(false); const [errorLogin, setErrorLogin] = useState(false); const [isLoading, setIsLoading] = useState(false); const [step, setStep] = useState(1); const [backupKeyError, setBackupKeyError] = useState(false); const [verificationToken, setVerificationToken] = useState(''); const [backupKeyIssued, setBackupKeyIssued] = useState(false); const router = useRouter(); const parsedUrl = queryString.parse(router.asPath.split('?')[1]); const token = parsedUrl.token as string; const email = (parsedUrl.to as string)?.replace(' ', '+').trim(); // Verifies if the information that the users entered (name, workspace) is there, and if the password matched the criteria. const signupErrorCheck = async () => { setIsLoading(true); let errorCheck = false; if (!firstName) { setFirstNameError(true); errorCheck = true; } else { setFirstNameError(false); } if (!lastName) { setLastNameError(true); errorCheck = true; } else { setLastNameError(false); } errorCheck = passwordCheck({ password, setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, errorCheck }); if (!errorCheck) { // Generate a random pair of a public and a private key const pair = nacl.box.keyPair(); const secretKeyUint8Array = pair.secretKey; const publicKeyUint8Array = pair.publicKey; const privateKey = encodeBase64(secretKeyUint8Array); const publicKey = encodeBase64(publicKeyUint8Array); localStorage.setItem('PRIVATE_KEY', privateKey); client.init( { username: email, password }, async () => { client.createVerifier(async (err, result) => { try { const derivedKey = await deriveArgonKey({ password, 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: privateKey, 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) }); const { token: jwtToken } = await completeAccountInformationSignupInvite({ email, firstName, lastName, protectedKey, protectedKeyIV, protectedKeyTag, publicKey, encryptedPrivateKey, encryptedPrivateKeyIV, encryptedPrivateKeyTag, salt: result.salt, verifier: result.verifier }); // unset temporary signup JWT token and set JWT token SecurityClient.setSignupToken(''); SecurityClient.setToken(jwtToken); saveTokenToLocalStorage({ publicKey, encryptedPrivateKey, iv: encryptedPrivateKeyIV, tag: encryptedPrivateKeyTag, privateKey }); const userOrgs = await getOrganizations(); const orgId = userOrgs[0]._id; localStorage.setItem('orgData.id', orgId); setStep(3); } catch (error) { setIsLoading(false); console.error(error); } }); } ); } else { setIsLoading(false); } }; // Step 4 of the sign up process (download the emergency kit pdf) const stepConfirmEmail = (

Confirm your email

verify email
); // Because this is the invite signup - we directly go to the last step of signup (email is already verified) const main = (

Almost there!

{ setPassword(pass); passwordCheck({ password: pass, setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, errorCheck: false }); }} type="password" value={password} isRequired error={passwordErrorLength && passwordErrorNumber && passwordErrorLowerCase} autoComplete="new-password" id="new-password" /> {passwordErrorLength || passwordErrorLowerCase || passwordErrorNumber ? (
Password should contain at least:
{passwordErrorLength ? ( ) : ( )}
14 characters
{passwordErrorLowerCase ? ( ) : ( )}
1 lowercase character
{passwordErrorNumber ? ( ) : ( )}
1 number
) : (
)}
); // Step 4 of the sign up process (download the emergency kit pdf) const step4 = (

Save your Emergency Kit

If you get locked out of your account, your Emergency Kit is the only way to sign in.
We recommend you download it and keep it somewhere safe.
It contains your Secret Key which we cannot access or recover for you if you lose it.
); return (
Sign Up
Infisical Wide Logo
{step === 1 ? stepConfirmEmail : step === 2 ? main : step4}
); }