import { router } from '@inertiajs/core'; import { useForm } from '@inertiajs/react'; import axios from 'axios'; import classNames from 'classnames'; import React, { useState } from 'react'; import ActionSection from '@/Components/ActionSection'; import ConfirmsPassword from '@/Components/ConfirmsPassword'; import DangerButton from '@/Components/DangerButton'; import InputError from '@/Components/InputError'; import InputLabel from '@/Components/InputLabel'; import PrimaryButton from '@/Components/PrimaryButton'; import SecondaryButton from '@/Components/SecondaryButton'; import TextInput from '@/Components/TextInput'; import useTypedPage from '@/Hooks/useTypedPage'; interface Props { requiresConfirmation: boolean; } export default function TwoFactorAuthenticationForm({ requiresConfirmation, }: Props) { const page = useTypedPage(); const [enabling, setEnabling] = useState(false); const [disabling, setDisabling] = useState(false); const [qrCode, setQrCode] = useState(null); const [recoveryCodes, setRecoveryCodes] = useState([]); const [confirming, setConfirming] = useState(false); const [setupKey, setSetupKey] = useState(null); const confirmationForm = useForm({ code: '', }); const twoFactorEnabled = !enabling && page.props?.auth?.user?.two_factor_enabled; function enableTwoFactorAuthentication() { setEnabling(true); router.post( '/user/two-factor-authentication', {}, { preserveScroll: true, onSuccess() { return Promise.all([ showQrCode(), showSetupKey(), showRecoveryCodes(), ]); }, onFinish() { setEnabling(false); setConfirming(requiresConfirmation); }, }, ); } function showSetupKey() { return axios.get('/user/two-factor-secret-key').then(response => { setSetupKey(response.data.secretKey); }); } function confirmTwoFactorAuthentication() { confirmationForm.post('/user/confirmed-two-factor-authentication', { preserveScroll: true, preserveState: true, errorBag: 'confirmTwoFactorAuthentication', onSuccess: () => { setConfirming(false); setQrCode(null); setSetupKey(null); }, }); } function showQrCode() { return axios.get('/user/two-factor-qr-code').then(response => { setQrCode(response.data.svg); }); } function showRecoveryCodes() { return axios.get('/user/two-factor-recovery-codes').then(response => { setRecoveryCodes(response.data); }); } function regenerateRecoveryCodes() { axios.post('/user/two-factor-recovery-codes').then(() => { showRecoveryCodes(); }); } function disableTwoFactorAuthentication() { setDisabling(true); router.delete('/user/two-factor-authentication', { preserveScroll: true, onSuccess() { setDisabling(false); setConfirming(false); }, }); } return ( {(() => { if (twoFactorEnabled && !confirming) { return (

You have enabled two factor authentication.

); } if (confirming) { return (

Finish enabling two factor authentication.

); } return (

You have not enabled two factor authentication.

); })()}

When two factor authentication is enabled, you will be prompted for a secure, random token during authentication. You may retrieve this token from your phone's Google Authenticator application.

{twoFactorEnabled || confirming ? (
{qrCode ? (
{confirming ? (

To finish enabling two factor authentication, scan the following QR code using your phone's authenticator application or enter the setup key and provide the generated OTP code.

) : (

Two factor authentication is now enabled. Scan the following QR code using your phone's authenticator application or enter the setup key.

)}
{setupKey && (

Setup Key:{' '}

)} {confirming && (
confirmationForm.setData('code', e.currentTarget.value) } />
)}
) : null} {recoveryCodes.length > 0 && !confirming ? (

Store these recovery codes in a secure password manager. They can be used to recover access to your account if your two factor authentication device is lost.

{recoveryCodes.map(code => (
{code}
))}
) : null}
) : null}
{twoFactorEnabled || confirming ? (
{confirming ? ( Confirm ) : null} {recoveryCodes.length > 0 && !confirming ? ( Regenerate Recovery Codes ) : null} {recoveryCodes.length === 0 && !confirming ? ( Show Recovery Codes ) : null} {confirming ? ( Cancel ) : ( Disable )}
) : (
Enable
)}
); }