import { useMutation, useQuery, useLazyQuery, gql } from '@apollo/client' import { Form, Formik } from 'formik' import { QRCodeSVG as QRCode } from 'qrcode.react' import React, { useContext, useState } from 'react' import { useHistory } from 'react-router-dom' import { Label3, P } from 'src/components/typography' import AppContext from 'src/AppContext' import { ActionButton, Button } from 'src/components/buttons' import { CodeInput } from 'src/components/inputs/base' import { primaryColor } from 'src/styling/variables' import classes from './Authentication.module.css' const SETUP_2FA = gql` mutation setup2FA( $username: String! $password: String! $rememberMe: Boolean! $codeConfirmation: String! ) { setup2FA( username: $username password: $password rememberMe: $rememberMe codeConfirmation: $codeConfirmation ) } ` const GET_2FA_SECRET = gql` query get2FASecret($username: String!, $password: String!) { get2FASecret(username: $username, password: $password) { secret otpauth } } ` const GET_USER_DATA = gql` { userData { id username role } } ` const Setup2FAState = ({ state }) => { const history = useHistory() const { setUserData } = useContext(AppContext) const [secret, setSecret] = useState(null) const [otpauth, setOtpauth] = useState(null) const [isShowing, setShowing] = useState(false) const [invalidToken, setInvalidToken] = useState(false) const [twoFAConfirmation, setTwoFAConfirmation] = useState('') const handle2FAChange = value => { setTwoFAConfirmation(value) setInvalidToken(false) } const queryOptions = { variables: { username: state.clientField, password: state.passwordField }, onCompleted: ({ get2FASecret }) => { setSecret(get2FASecret.secret) setOtpauth(get2FASecret.otpauth) }, } const mutationOptions = { variables: { username: state.clientField, password: state.passwordField, rememberMe: state.rememberMeField, codeConfirmation: twoFAConfirmation, }, } const { error: queryError } = useQuery(GET_2FA_SECRET, queryOptions) const [getUserData] = useLazyQuery(GET_USER_DATA, { onCompleted: ({ userData }) => { setUserData(userData) history.push('/') }, }) const [setup2FA, { error: mutationError }] = useMutation(SETUP_2FA, { onCompleted: ({ setup2FA: success }) => { success ? getUserData() : setInvalidToken(true) }, }) const getErrorMsg = () => { if (mutationError || queryError) return 'Internal server error.' if (twoFAConfirmation.length !== 6 && invalidToken) return 'The code should have 6 characters!' if (invalidToken) return 'Code is invalid. Please try again.' return null } const handleSubmit = () => { if (twoFAConfirmation.length !== 6) { setInvalidToken(true) return } setup2FA(mutationOptions) } return ( secret && otpauth && ( <>
This account does not yet have two-factor authentication enabled. To secure the admin, two-factor authentication is required. To complete the registration process, scan the following QR code or insert the secret below on a 2FA app, such as Google Authenticator or AndOTP.
Your secret: {secret} { setShowing(!isShowing) }}> {isShowing ? 'Hide' : 'Show'}
{/* TODO: refactor the 2FA CodeInput to properly use Formik */} {}} initialValues={{}}>
{getErrorMsg() && (

{getErrorMsg()}

)}
) ) } export default Setup2FAState