diff --git a/src/frontend/src/components/forms/AuthenticationForm.tsx b/src/frontend/src/components/forms/AuthenticationForm.tsx
index f3673700a8..f9cb05da52 100644
--- a/src/frontend/src/components/forms/AuthenticationForm.tsx
+++ b/src/frontend/src/components/forms/AuthenticationForm.tsx
@@ -1,3 +1,4 @@
+import { ApiEndpoints, apiUrl } from '@lib/index';
import { t } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import {
@@ -8,16 +9,14 @@ import {
Loader,
PasswordInput,
Stack,
- TextInput
+ TextInput,
+ VisuallyHidden
} from '@mantine/core';
import { useForm } from '@mantine/form';
import { useDisclosure } from '@mantine/hooks';
+import { showNotification } from '@mantine/notifications';
import { useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
-
-import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
-import { apiUrl } from '@lib/functions/Api';
-import { showNotification } from '@mantine/notifications';
import { useShallow } from 'zustand/react/shallow';
import { api } from '../../App';
import {
@@ -33,7 +32,7 @@ import { SsoButton } from '../buttons/SSOButton';
export function AuthenticationForm() {
const classicForm = useForm({
- initialValues: { username: '', password: '' }
+ initialValues: { username: '', password: '', code: '' }
});
const simpleForm = useForm({ initialValues: { email: '' } });
const [classicLoginMode, setMode] = useDisclosure(true);
@@ -58,7 +57,9 @@ export function AuthenticationForm() {
doBasicLogin(
classicForm.values.username,
classicForm.values.password,
- navigate
+
+ navigate,
+ classicForm.values.code
)
.then((success) => {
setIsLoggingIn(false);
@@ -140,6 +141,13 @@ export function AuthenticationForm() {
placeholder={t`Your password`}
{...classicForm.getInputProps('password')}
/>
+
+
+
{password_forgotten_enabled() === true && (
{
+ navigate: NavigateFunction,
+ code?: string
+) {
const { getHost } = useLocalState.getState();
const { clearUserState, setAuthenticated, fetchUserState } =
useUserState.getState();
@@ -104,16 +105,9 @@ export const doBasicLogin = async (
success = true;
}
})
- .catch((err) => {
+ .catch(async (err) => {
if (err?.response?.status == 401) {
- setAuthContext(err.response.data?.data);
- const mfa_flow = err.response.data.data.flows.find(
- (flow: any) => flow.id == FlowEnum.MfaAuthenticate
- );
- if (mfa_flow && mfa_flow.is_pending == true) {
- success = true;
- navigate('/mfa');
- }
+ await handlePossibleMFAError(err);
} else if (err?.response?.status == 409) {
notifications.show({
title: t`Already logged in`,
@@ -133,7 +127,40 @@ export const doBasicLogin = async (
clearUserState();
}
return success;
-};
+
+ async function handlePossibleMFAError(err: any) {
+ setAuthContext(err.response.data?.data);
+ const mfa_flow = err.response.data.data.flows.find(
+ (flow: any) => flow.id == FlowEnum.MfaAuthenticate
+ );
+ if (mfa_flow?.is_pending) {
+ // MFA is required - we might already have a code
+ if (code && code.length > 0) {
+ const rslt = await handleMfaLogin(
+ navigate,
+ undefined,
+ { code: code },
+ () => {}
+ );
+ if (rslt) {
+ setAuthenticated(true);
+ loginDone = true;
+ success = true;
+ notifications.show({
+ title: t`MFA Login successful`,
+ message: t`MFA details were automatically provided in the browser`,
+ color: 'green'
+ });
+ }
+ }
+ // No code or success - off to the mfa page
+ if (!loginDone) {
+ success = true;
+ navigate('/mfa');
+ }
+ }
+ }
+}
/**
* Logout the user from the current session
@@ -259,19 +286,25 @@ export function handleReset(
});
}
-export function handleMfaLogin(
+export async function handleMfaLogin(
navigate: NavigateFunction,
- location: Location,
+ location: Location | undefined,
values: { code: string; remember?: boolean },
setError: (message: string | undefined) => void
) {
const { setAuthContext } = useServerApiState.getState();
- authApi(apiUrl(ApiEndpoints.auth_login_2fa), undefined, 'post', {
- code: values.code
- })
+ const result = await authApi(
+ apiUrl(ApiEndpoints.auth_login_2fa),
+ undefined,
+ 'post',
+ {
+ code: values.code
+ }
+ )
.then((response) => {
handleSuccessFullAuth(response, navigate, location, setError);
+ return true;
})
.catch((err) => {
// Already logged in, but with a different session
@@ -304,7 +337,9 @@ export function handleMfaLogin(
}
setError(msg);
}
+ return false;
});
+ return result;
}
/**
@@ -380,7 +415,7 @@ function handleSuccessFullAuth(
observeProfile();
fetchGlobalStates(navigate);
- if (navigate) {
+ if (navigate && location) {
followRedirect(navigate, location?.state);
}
});