mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
refactor(experience): polish handle mfa redirection codes and add comments (#4782)
This commit is contained in:
parent
4080a2599b
commit
7029255b91
1 changed files with 39 additions and 16 deletions
|
@ -1,5 +1,6 @@
|
|||
import { MfaFactor, type RequestErrorBody } from '@logto/schemas';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { validate } from 'superstruct';
|
||||
|
||||
|
@ -22,45 +23,67 @@ export type Options = {
|
|||
|
||||
const useMfaErrorHandler = ({ replace }: Options = {}) => {
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
const { setToast } = useToast();
|
||||
const startTotpBinding = useStartTotpBinding({ replace });
|
||||
|
||||
/**
|
||||
* Redirect the user to the corresponding MFA page.
|
||||
*
|
||||
* Binding pages are hosted on following routes:
|
||||
* - /{@link UserMfaFlow.MfaBinding} List of available MFA factors for binding.
|
||||
* - /{@link UserMfaFlow.MfaBinding}/{@link MfaFactor} Binding page for the specific factor.
|
||||
*
|
||||
* Verification pages are hosted on following routes:
|
||||
* - /{@link UserMfaFlow.MfaVerification} List of available MFA factors for verification.
|
||||
* - /{@link UserMfaFlow.MfaVerification}/{@link MfaFactor} Verification page for the specific factor.
|
||||
*
|
||||
* Redirection rules:
|
||||
* - If there is only one available factor, redirect to the specific MFA factor page.
|
||||
* - If there are multiple available factors:
|
||||
* - Binding: redirect to the available factors list page.
|
||||
* - Verification: redirect to the last used specific factor page.
|
||||
*/
|
||||
const handleMfaRedirect = useCallback(
|
||||
(flow: UserMfaFlow, state: MfaFlowState) => {
|
||||
const { availableFactors } = state;
|
||||
|
||||
if (flow === UserMfaFlow.MfaVerification) {
|
||||
// In MFA verification flow, the user will be redirected to the last used factor which is the first one in the array.
|
||||
const factor = availableFactors[0];
|
||||
|
||||
if (!factor) {
|
||||
return;
|
||||
}
|
||||
|
||||
navigate({ pathname: `/${flow}/${factor}` }, { replace, state });
|
||||
return;
|
||||
}
|
||||
|
||||
// Binding flow
|
||||
if (availableFactors.length > 1) {
|
||||
if (availableFactors.length > 1 && flow === UserMfaFlow.MfaBinding) {
|
||||
/**
|
||||
* Redirect to the MFA binding page if there are multiple available factors.
|
||||
*/
|
||||
navigate({ pathname: `/${flow}` }, { replace, state });
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* For verification: the first available factor is the last used factor which is guaranteed by the backend.
|
||||
* For binding: the first available factor is the only available factor since we handle the multiple factors case above.
|
||||
*/
|
||||
const factor = availableFactors[0];
|
||||
|
||||
if (!factor) {
|
||||
/**
|
||||
* This should never happen since we check the available factors' length before handling the redirection.
|
||||
*/
|
||||
setToast(t('error.unknown'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (factor === MfaFactor.TOTP) {
|
||||
if (factor === MfaFactor.TOTP && flow === UserMfaFlow.MfaBinding) {
|
||||
/**
|
||||
* Start TOTP binding process if only TOTP is available.
|
||||
*/
|
||||
void startTotpBinding(state);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to the specific MFA factor page.
|
||||
*/
|
||||
navigate({ pathname: `/${flow}/${factor}` }, { replace, state });
|
||||
},
|
||||
[navigate, replace, startTotpBinding]
|
||||
[navigate, replace, setToast, startTotpBinding, t]
|
||||
);
|
||||
|
||||
const handleMfaError = useCallback(
|
||||
|
|
Loading…
Reference in a new issue