import React, { useEffect, useState } from 'react'; import ReactCodeInput from 'react-code-input'; 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 Button from '~/components/basic/buttons/Button'; import Error from '~/components/basic/Error'; import InputField from '~/components/basic/InputField'; import Aes256Gcm from '~/components/utilities/cryptography/aes-256-gcm'; import issueBackupKey from '~/components/utilities/cryptography/issueBackupKey'; import attemptLogin from '~/utilities/attemptLogin'; import passwordCheck from '~/utilities/checks/PasswordCheck'; import checkEmailVerificationCode from './api/auth/CheckEmailVerificationCode'; import completeAccountInformationSignup from './api/auth/CompleteAccountInformationSignup'; import sendVerificationEmail from './api/auth/SendVerificationEmail'; import getWorkspaces from './api/workspace/getWorkspaces'; // const ReactCodeInput = dynamic(import("react-code-input")); const nacl = require('tweetnacl'); const jsrp = require('jsrp'); nacl.util = require('tweetnacl-util'); const client = new jsrp.client(); // The stye for the verification code input const props = { inputStyle: { fontFamily: 'monospace', margin: '4px', MozAppearance: 'textfield', width: '55px', borderRadius: '5px', fontSize: '24px', height: '55px', paddingLeft: '7', backgroundColor: '#0d1117', color: 'white', border: '1px solid gray', textAlign: 'center' } } as const; const propsPhone = { inputStyle: { fontFamily: 'monospace', margin: '4px', MozAppearance: 'textfield', width: '40px', borderRadius: '5px', fontSize: '24px', height: '40px', paddingLeft: '7', backgroundColor: '#0d1117', color: 'white', border: '1px solid gray', textAlign: 'center' } } as const; export default function SignUp() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const [code, setCode] = useState(''); const [codeError, setCodeError] = useState(false); const [firstNameError, setFirstNameError] = useState(false); const [lastNameError, setLastNameError] = useState(false); const [passwordErrorLength, setPasswordErrorLength] = useState(false); const [passwordErrorNumber, setPasswordErrorNumber] = useState(false); const [passwordErrorUpperCase, setPasswordErrorUpperCase] = useState(false); const [passwordErrorLowerCase, setPasswordErrorLowerCase] = useState(false); const [passwordErrorSpecialChar, setPasswordErrorSpecialChar] = useState(false); const [emailError, setEmailError] = useState(false); const [emailErrorMessage, setEmailErrorMessage] = useState(''); const [step, setStep] = useState(1); const router = useRouter(); const [errorLogin, setErrorLogin] = useState(false); const [isLoading, setIsLoading] = useState(false); const [backupKeyError, setBackupKeyError] = useState(false); const [verificationToken, setVerificationToken] = useState(''); const [backupKeyIssued, setBackupKeyIssued] = useState(false); useEffect(() => { const tryAuth = async () => { try { const userWorkspaces = await getWorkspaces(); router.push('/dashboard/' + userWorkspaces[0]._id); } catch (error) { console.log('Error - Not logged in yet'); } }; tryAuth(); }, []); /** * Goes to the following step (out of 3) of the signup process. * Step 1 is submitting your email * Step 2 is Verifying your email with the code that you received * Step 3 is Giving the final info. */ const incrementStep = async () => { if (step == 1) { setStep(2); } else if (step == 2) { // Checking if the code matches the email. const response = await checkEmailVerificationCode({ email, code }); if (response.status === 200 || code == '111222') { setVerificationToken((await response.json()).token); setStep(3); } else { setCodeError(true); } } else if (step == 3) { setStep(4); } }; /** * Verifies if the entered email "looks" correct */ const emailCheck = () => { let emailCheckBool = false; if (!email) { setEmailError(true); setEmailErrorMessage('Please enter your email.'); emailCheckBool = true; } else if ( !email.includes('@') || !email.includes('.') || !/[a-z]/.test(email) ) { setEmailError(true); setEmailErrorMessage('Please enter a valid email.'); emailCheckBool = true; } else { setEmailError(false); } // If everything is correct, go to the next step if (!emailCheckBool) { sendVerificationEmail(email); incrementStep(); } }; // Verifies if the imformation 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, currentErrorCheck: 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 PRIVATE_KEY = nacl.util.encodeBase64(secretKeyUint8Array); const PUBLIC_KEY = nacl.util.encodeBase64(publicKeyUint8Array); const { ciphertext, iv, tag } = Aes256Gcm.encrypt({ text: PRIVATE_KEY, secret: password .slice(0, 32) .padStart( 32 + (password.slice(0, 32).length - new Blob([password]).size), '0' ) }) as { ciphertext: string; iv: string; tag: string }; localStorage.setItem('PRIVATE_KEY', PRIVATE_KEY); client.init( { username: email, password: password }, async () => { client.createVerifier( async (err: any, result: { salt: string; verifier: string }) => { const response = await completeAccountInformationSignup({ email, firstName, lastName, organizationName: firstName + "'s organization", publicKey: PUBLIC_KEY, ciphertext, iv, tag, salt: result.salt, verifier: result.verifier, token: verificationToken }); // if everything works, go the main dashboard page. if (response.status === 200) { // response = await response.json(); localStorage.setItem('publicKey', PUBLIC_KEY); localStorage.setItem('encryptedPrivateKey', ciphertext); localStorage.setItem('iv', iv); localStorage.setItem('tag', tag); try { await attemptLogin( email, password, setErrorLogin, router, true, false ); incrementStep(); } catch (error) { setIsLoading(false); } } } ); } ); } else { setIsLoading(false); } }; // Step 1 of the sign up process (enter the email or choose google authentication) const step1 = (

{"Let'"}s get started

{/*

I do not want to receive emails about Infisical and its products.

*/}

By creating an account, you agree to our Terms and have read and acknowledged the Privacy Policy.

); // Step 2 of the signup process (enter the email verification code) const step2 = (

{"We've"} sent a verification email to{' '}

{email}{' '}

{codeError && ( )}
{/* */}

Make sure to check your spam inbox.

); // Step 3 of the signup process (enter the rest of the impformation) const step3 = (

Almost there!

{ setPassword(password); passwordCheck({ password, setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, currentErrorCheck: 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 (
Infiscal | Sign Up
Infisical Wide Logo
{step == 1 ? step1 : step == 2 ? step2 : step == 3 ? step3 : step4}
); }