feat(auth): add 2FA setup UI and login challenge step
This commit is contained in:
@@ -5,6 +5,7 @@ import { PublicClientApplication } from "@azure/msal-browser";
|
||||
|
||||
import { api, getApiErrorMessage } from "../api";
|
||||
import { clearAuthClientState, getAuthPersistencePreference } from "../auth";
|
||||
import TwoFactorChallenge from "./TwoFactorChallenge";
|
||||
import { useToast } from "../toast";
|
||||
import { useI18n } from "../i18n/I18nProvider";
|
||||
|
||||
@@ -35,6 +36,7 @@ export default function MicrosoftAuthCard({ onSignedIn }: { onSignedIn?: () => v
|
||||
const { t } = useI18n();
|
||||
const [me, setMe] = useState<MeResponse | null>(null);
|
||||
const [working, setWorking] = useState(false);
|
||||
const [pendingToken, setPendingToken] = useState<string | null>(null);
|
||||
|
||||
const clientId = (process.env.REACT_APP_MICROSOFT_CLIENT_ID || "").trim();
|
||||
const signedIn = Boolean(me?.provider);
|
||||
@@ -78,10 +80,14 @@ export default function MicrosoftAuthCard({ onSignedIn }: { onSignedIn?: () => v
|
||||
toast(res.data?.email ? t("microsoftLinkedSuccessWithEmail", { email: res.data.email }) : t("microsoftLinkedSuccess"), "success");
|
||||
await refreshMe();
|
||||
} else {
|
||||
await api.post("/auth/microsoft/exchange", { token: idToken, rememberMe: getAuthPersistencePreference() === "local" });
|
||||
window.dispatchEvent(new Event("auth-changed"));
|
||||
toast(t("microsoftSignedIn"), "success");
|
||||
onSignedIn?.();
|
||||
const res = await api.post<{ requiresTwoFactor?: boolean; pendingToken?: string }>("/auth/microsoft/exchange", { token: idToken, rememberMe: getAuthPersistencePreference() === "local" });
|
||||
if (res.data?.requiresTwoFactor && res.data.pendingToken) {
|
||||
setPendingToken(res.data.pendingToken);
|
||||
} else {
|
||||
window.dispatchEvent(new Event("auth-changed"));
|
||||
toast(t("microsoftSignedIn"), "success");
|
||||
onSignedIn?.();
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
toast(getApiErrorMessage(e, t("microsoftAuthFailed")), "error");
|
||||
@@ -104,7 +110,20 @@ export default function MicrosoftAuthCard({ onSignedIn }: { onSignedIn?: () => v
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
{clientId && (
|
||||
{clientId && pendingToken && (
|
||||
<TwoFactorChallenge
|
||||
pendingToken={pendingToken}
|
||||
onCancel={() => setPendingToken(null)}
|
||||
onSuccess={() => {
|
||||
setPendingToken(null);
|
||||
window.dispatchEvent(new Event("auth-changed"));
|
||||
toast(t("microsoftSignedIn"), "success");
|
||||
onSignedIn?.();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{clientId && !pendingToken && (
|
||||
<Box sx={{ display: "flex", flexDirection: "column", gap: 1.25 }}>
|
||||
<Box sx={{ display: "flex", gap: 1, flexWrap: "wrap" }}>
|
||||
<Chip size="small" label={me?.microsoftLink?.linked ? t("microsoftLinked") : t("microsoftAvailableToLink")} color={me?.microsoftLink?.linked ? "success" : "default"} variant={me?.microsoftLink?.linked ? "filled" : "outlined"} />
|
||||
|
||||
Reference in New Issue
Block a user