@passflow/react 0.2.8 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +4 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +440 -6
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/flow/two-factor-verify/index.d.ts +1 -0
- package/dist/src/components/flow/two-factor-verify/index.d.ts.map +1 -1
- package/dist/src/components/form/index.d.ts +1 -0
- package/dist/src/components/form/index.d.ts.map +1 -1
- package/dist/src/components/form/two-factor-challenge/index.d.ts +10 -0
- package/dist/src/components/form/two-factor-challenge/index.d.ts.map +1 -0
- package/dist/src/components/form/two-factor-challenge/method-selector.d.ts +12 -0
- package/dist/src/components/form/two-factor-challenge/method-selector.d.ts.map +1 -0
- package/dist/src/components/form/two-factor-challenge/otp-input.d.ts +12 -0
- package/dist/src/components/form/two-factor-challenge/otp-input.d.ts.map +1 -0
- package/dist/src/context/auth-context.d.ts +10 -1
- package/dist/src/context/auth-context.d.ts.map +1 -1
- package/dist/src/hooks/index.d.ts +3 -0
- package/dist/src/hooks/index.d.ts.map +1 -1
- package/dist/src/hooks/use-session-expired.d.ts +49 -0
- package/dist/src/hooks/use-session-expired.d.ts.map +1 -0
- package/dist/src/hooks/use-two-factor-challenge.d.ts +16 -0
- package/dist/src/hooks/use-two-factor-challenge.d.ts.map +1 -0
- package/dist/src/hooks/use-two-factor-methods.d.ts +14 -0
- package/dist/src/hooks/use-two-factor-methods.d.ts.map +1 -0
- package/dist/src/types/index.d.ts +18 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.es.js
CHANGED
|
@@ -6,6 +6,8 @@ import clsx from 'clsx';
|
|
|
6
6
|
import { twMerge } from 'tailwind-merge';
|
|
7
7
|
import * as React from 'react';
|
|
8
8
|
import { useState, useEffect, forwardRef, createContext, useCallback, useContext, useRef, useLayoutEffect, useMemo, useReducer } from 'react';
|
|
9
|
+
import { PassflowEvent, parseToken, Passflow } from '@passflow/core';
|
|
10
|
+
export * from '@passflow/core';
|
|
9
11
|
import queryString from 'query-string';
|
|
10
12
|
import { getCountryForTimezone } from 'countries-and-timezones';
|
|
11
13
|
import { usePhoneInput, defaultCountries, parseCountry, FlagImage } from 'react-international-phone';
|
|
@@ -16,11 +18,9 @@ import { HelmetProvider, Helmet } from 'react-helmet-async';
|
|
|
16
18
|
import { ErrorBoundary } from 'react-error-boundary';
|
|
17
19
|
import { phone as phone$1 } from 'phone';
|
|
18
20
|
import { useForm, Controller } from 'react-hook-form';
|
|
19
|
-
import { parseToken, Passflow } from '@passflow/core';
|
|
20
|
-
export * from '@passflow/core';
|
|
21
21
|
import 'react-dom';
|
|
22
22
|
|
|
23
|
-
const version = "0.2.
|
|
23
|
+
const version = "0.2.10";
|
|
24
24
|
|
|
25
25
|
window.passflowReactAppVersion = () => {
|
|
26
26
|
console.log(`App Version: ${version}`);
|
|
@@ -787,9 +787,27 @@ const NavigationContext$1 = createContext({
|
|
|
787
787
|
});
|
|
788
788
|
|
|
789
789
|
const AuthContext = createContext(void 0);
|
|
790
|
-
const AuthProvider = ({ children }) => {
|
|
790
|
+
const AuthProvider = ({ children, onSessionExpired }) => {
|
|
791
791
|
const passflow = usePassflow();
|
|
792
792
|
const [isLoading, setIsLoading] = useState(false);
|
|
793
|
+
const [isSessionExpired, setIsSessionExpired] = useState(false);
|
|
794
|
+
useEffect(() => {
|
|
795
|
+
const subscriber = {
|
|
796
|
+
onAuthChange: (eventType, payload) => {
|
|
797
|
+
if (eventType === PassflowEvent.SessionExpired) {
|
|
798
|
+
const reason = payload?.reason ?? "refresh_failed";
|
|
799
|
+
setIsSessionExpired(true);
|
|
800
|
+
onSessionExpired?.(reason);
|
|
801
|
+
} else if (eventType === PassflowEvent.SignIn || eventType === PassflowEvent.Register) {
|
|
802
|
+
setIsSessionExpired(false);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
};
|
|
806
|
+
passflow.subscribe(subscriber, [PassflowEvent.SessionExpired, PassflowEvent.SignIn, PassflowEvent.Register]);
|
|
807
|
+
return () => {
|
|
808
|
+
passflow.unsubscribe(subscriber);
|
|
809
|
+
};
|
|
810
|
+
}, [passflow, onSessionExpired]);
|
|
793
811
|
const isAuthenticated = useCallback(() => passflow.isAuthenticated(), [passflow]);
|
|
794
812
|
const getTokens = useCallback(
|
|
795
813
|
async (doRefresh) => {
|
|
@@ -819,6 +837,7 @@ const AuthProvider = ({ children }) => {
|
|
|
819
837
|
isAuthenticated,
|
|
820
838
|
logout,
|
|
821
839
|
isLoading,
|
|
840
|
+
isSessionExpired,
|
|
822
841
|
getTokens
|
|
823
842
|
};
|
|
824
843
|
return /* @__PURE__ */ jsx(AuthContext.Provider, { value, children });
|
|
@@ -1789,6 +1808,178 @@ const useTwoFactorSetupMagicLink = (token) => {
|
|
|
1789
1808
|
};
|
|
1790
1809
|
};
|
|
1791
1810
|
|
|
1811
|
+
const useTwoFactorChallenge = () => {
|
|
1812
|
+
const passflow = usePassflow();
|
|
1813
|
+
const [challenge, setChallenge] = useState(null);
|
|
1814
|
+
const [selectedMethod, setSelectedMethod] = useState(null);
|
|
1815
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
1816
|
+
const [error, setError] = useState(null);
|
|
1817
|
+
const requestChallenge = useCallback(
|
|
1818
|
+
async (firstFactorMethod) => {
|
|
1819
|
+
setIsLoading(true);
|
|
1820
|
+
setError(null);
|
|
1821
|
+
try {
|
|
1822
|
+
const response = await passflow.twoFactor.requestChallenge({
|
|
1823
|
+
first_factor_method: firstFactorMethod
|
|
1824
|
+
});
|
|
1825
|
+
setChallenge(response);
|
|
1826
|
+
setSelectedMethod(response.method);
|
|
1827
|
+
} catch (e) {
|
|
1828
|
+
setError(e);
|
|
1829
|
+
setChallenge(null);
|
|
1830
|
+
} finally {
|
|
1831
|
+
setIsLoading(false);
|
|
1832
|
+
}
|
|
1833
|
+
},
|
|
1834
|
+
[passflow]
|
|
1835
|
+
);
|
|
1836
|
+
const verify = useCallback(
|
|
1837
|
+
async (response, trustDevice = false) => {
|
|
1838
|
+
if (!challenge?.challenge_id) {
|
|
1839
|
+
setError(new Error("No active challenge session"));
|
|
1840
|
+
return null;
|
|
1841
|
+
}
|
|
1842
|
+
setIsLoading(true);
|
|
1843
|
+
setError(null);
|
|
1844
|
+
try {
|
|
1845
|
+
const result = await passflow.twoFactor.verifyV2({
|
|
1846
|
+
challenge_id: challenge.challenge_id,
|
|
1847
|
+
method: selectedMethod || challenge.method,
|
|
1848
|
+
response,
|
|
1849
|
+
trust_device: trustDevice
|
|
1850
|
+
});
|
|
1851
|
+
return result;
|
|
1852
|
+
} catch (e) {
|
|
1853
|
+
setError(e);
|
|
1854
|
+
return null;
|
|
1855
|
+
} finally {
|
|
1856
|
+
setIsLoading(false);
|
|
1857
|
+
}
|
|
1858
|
+
},
|
|
1859
|
+
[passflow, challenge, selectedMethod]
|
|
1860
|
+
);
|
|
1861
|
+
const switchMethod = useCallback(
|
|
1862
|
+
async (method) => {
|
|
1863
|
+
if (!challenge?.challenge_id) {
|
|
1864
|
+
setError(new Error("No active challenge session"));
|
|
1865
|
+
return;
|
|
1866
|
+
}
|
|
1867
|
+
setIsLoading(true);
|
|
1868
|
+
setError(null);
|
|
1869
|
+
try {
|
|
1870
|
+
const response = await passflow.twoFactor.switchToAlternative({
|
|
1871
|
+
challenge_id: challenge.challenge_id,
|
|
1872
|
+
method
|
|
1873
|
+
});
|
|
1874
|
+
setChallenge(response);
|
|
1875
|
+
setSelectedMethod(method);
|
|
1876
|
+
} catch (e) {
|
|
1877
|
+
setError(e);
|
|
1878
|
+
} finally {
|
|
1879
|
+
setIsLoading(false);
|
|
1880
|
+
}
|
|
1881
|
+
},
|
|
1882
|
+
[passflow, challenge]
|
|
1883
|
+
);
|
|
1884
|
+
const reset = useCallback(() => {
|
|
1885
|
+
setChallenge(null);
|
|
1886
|
+
setSelectedMethod(null);
|
|
1887
|
+
setError(null);
|
|
1888
|
+
setIsLoading(false);
|
|
1889
|
+
}, []);
|
|
1890
|
+
return {
|
|
1891
|
+
challenge,
|
|
1892
|
+
isLoading,
|
|
1893
|
+
error,
|
|
1894
|
+
requestChallenge,
|
|
1895
|
+
verify,
|
|
1896
|
+
switchMethod,
|
|
1897
|
+
selectedMethod,
|
|
1898
|
+
reset
|
|
1899
|
+
};
|
|
1900
|
+
};
|
|
1901
|
+
|
|
1902
|
+
const useTwoFactorMethods = () => {
|
|
1903
|
+
const passflow = usePassflow();
|
|
1904
|
+
const [availableMethods, setAvailableMethods] = useState([]);
|
|
1905
|
+
const [registeredMethods, setRegisteredMethods] = useState([]);
|
|
1906
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
1907
|
+
const [error, setError] = useState(null);
|
|
1908
|
+
const refresh = useCallback(async () => {
|
|
1909
|
+
setIsLoading(true);
|
|
1910
|
+
setError(null);
|
|
1911
|
+
try {
|
|
1912
|
+
const methods = await passflow.twoFactor.getRegisteredMethods();
|
|
1913
|
+
setRegisteredMethods(methods);
|
|
1914
|
+
const available = methods.map((m) => m.method);
|
|
1915
|
+
setAvailableMethods(available);
|
|
1916
|
+
} catch (e) {
|
|
1917
|
+
setError(e);
|
|
1918
|
+
setRegisteredMethods([]);
|
|
1919
|
+
setAvailableMethods([]);
|
|
1920
|
+
} finally {
|
|
1921
|
+
setIsLoading(false);
|
|
1922
|
+
}
|
|
1923
|
+
}, [passflow]);
|
|
1924
|
+
const removeMethod = useCallback(
|
|
1925
|
+
async (methodId) => {
|
|
1926
|
+
setIsLoading(true);
|
|
1927
|
+
setError(null);
|
|
1928
|
+
try {
|
|
1929
|
+
await passflow.twoFactor.removeMethod?.(methodId);
|
|
1930
|
+
await refresh();
|
|
1931
|
+
} catch (e) {
|
|
1932
|
+
setError(e);
|
|
1933
|
+
} finally {
|
|
1934
|
+
setIsLoading(false);
|
|
1935
|
+
}
|
|
1936
|
+
},
|
|
1937
|
+
[passflow, refresh]
|
|
1938
|
+
);
|
|
1939
|
+
return {
|
|
1940
|
+
availableMethods,
|
|
1941
|
+
registeredMethods,
|
|
1942
|
+
isLoading,
|
|
1943
|
+
error,
|
|
1944
|
+
refresh,
|
|
1945
|
+
removeMethod
|
|
1946
|
+
};
|
|
1947
|
+
};
|
|
1948
|
+
|
|
1949
|
+
function useSessionExpired(options) {
|
|
1950
|
+
const passflow = usePassflow();
|
|
1951
|
+
const [isSessionExpired, setIsSessionExpired] = useState(false);
|
|
1952
|
+
const [expiredReason, setExpiredReason] = useState(null);
|
|
1953
|
+
useEffect(() => {
|
|
1954
|
+
const subscriber = {
|
|
1955
|
+
onAuthChange: (eventType, payload) => {
|
|
1956
|
+
if (eventType === PassflowEvent.SessionExpired) {
|
|
1957
|
+
const reason = payload?.reason ?? "refresh_failed";
|
|
1958
|
+
setIsSessionExpired(true);
|
|
1959
|
+
setExpiredReason(reason);
|
|
1960
|
+
options?.onSessionExpired?.(reason);
|
|
1961
|
+
} else if (eventType === PassflowEvent.SignIn || eventType === PassflowEvent.Register) {
|
|
1962
|
+
setIsSessionExpired(false);
|
|
1963
|
+
setExpiredReason(null);
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
};
|
|
1967
|
+
passflow.subscribe(subscriber, [PassflowEvent.SessionExpired, PassflowEvent.SignIn, PassflowEvent.Register]);
|
|
1968
|
+
return () => {
|
|
1969
|
+
passflow.unsubscribe(subscriber);
|
|
1970
|
+
};
|
|
1971
|
+
}, [passflow, options?.onSessionExpired]);
|
|
1972
|
+
const resetSessionExpired = () => {
|
|
1973
|
+
setIsSessionExpired(false);
|
|
1974
|
+
setExpiredReason(null);
|
|
1975
|
+
};
|
|
1976
|
+
return {
|
|
1977
|
+
isSessionExpired,
|
|
1978
|
+
expiredReason,
|
|
1979
|
+
resetSessionExpired
|
|
1980
|
+
};
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1792
1983
|
const FieldPhone = ({ id, onChange, isError = false, className = "" }) => {
|
|
1793
1984
|
const [show, setShow] = useState(false);
|
|
1794
1985
|
const [filterValue, setFilterValue] = useState("");
|
|
@@ -2190,6 +2381,245 @@ const TwoFactorSetupFlow = ({
|
|
|
2190
2381
|
return /* @__PURE__ */ jsx(TwoFactorSetupForm, { onComplete: handleSetupComplete, onCancel: handleCancel });
|
|
2191
2382
|
};
|
|
2192
2383
|
|
|
2384
|
+
const methodLabels = {
|
|
2385
|
+
totp: "Authenticator App",
|
|
2386
|
+
email_otp: "Email Code",
|
|
2387
|
+
sms_otp: "SMS Code",
|
|
2388
|
+
passkey: "Passkey",
|
|
2389
|
+
recovery_codes: "Recovery Code",
|
|
2390
|
+
push_fcm: "Push Notification (FCM)",
|
|
2391
|
+
push_webpush: "Push Notification (Web)"
|
|
2392
|
+
};
|
|
2393
|
+
const methodIcons = {
|
|
2394
|
+
totp: "📱",
|
|
2395
|
+
email_otp: "✉️",
|
|
2396
|
+
sms_otp: "💬",
|
|
2397
|
+
passkey: "🔑",
|
|
2398
|
+
recovery_codes: "🔒",
|
|
2399
|
+
push_fcm: "🔔",
|
|
2400
|
+
push_webpush: "🔔"
|
|
2401
|
+
};
|
|
2402
|
+
const MethodSelector = ({
|
|
2403
|
+
availableMethods,
|
|
2404
|
+
currentMethod,
|
|
2405
|
+
onSelectMethod,
|
|
2406
|
+
isOpen,
|
|
2407
|
+
onClose
|
|
2408
|
+
}) => {
|
|
2409
|
+
const handleSelect = (method) => {
|
|
2410
|
+
onSelectMethod(method);
|
|
2411
|
+
onClose();
|
|
2412
|
+
};
|
|
2413
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Root, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
|
|
2414
|
+
/* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: "pf-dialog-overlay" }),
|
|
2415
|
+
/* @__PURE__ */ jsxs(DialogPrimitive.Content, { className: "pf-dialog-content pf-method-selector-dialog", children: [
|
|
2416
|
+
/* @__PURE__ */ jsx(DialogPrimitive.Title, { className: "pf-dialog-title", children: "Choose Verification Method" }),
|
|
2417
|
+
/* @__PURE__ */ jsx(DialogPrimitive.Description, { className: "pf-dialog-description", children: "Select an alternative method to verify your identity" }),
|
|
2418
|
+
/* @__PURE__ */ jsx("div", { className: "pf-method-selector-list", children: availableMethods.map((method) => /* @__PURE__ */ jsxs(
|
|
2419
|
+
"button",
|
|
2420
|
+
{
|
|
2421
|
+
type: "button",
|
|
2422
|
+
className: `pf-method-selector-item ${method === currentMethod ? "pf-method-selector-item-active" : ""}`,
|
|
2423
|
+
onClick: () => handleSelect(method),
|
|
2424
|
+
disabled: method === currentMethod,
|
|
2425
|
+
children: [
|
|
2426
|
+
/* @__PURE__ */ jsx("span", { className: "pf-method-icon", children: methodIcons[method] || "🔐" }),
|
|
2427
|
+
/* @__PURE__ */ jsx("span", { className: "pf-method-label", children: methodLabels[method] || method }),
|
|
2428
|
+
method === currentMethod && /* @__PURE__ */ jsx("span", { className: "pf-method-current-badge", children: "Current" })
|
|
2429
|
+
]
|
|
2430
|
+
},
|
|
2431
|
+
method
|
|
2432
|
+
)) }),
|
|
2433
|
+
/* @__PURE__ */ jsx(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx("button", { type: "button", className: "pf-dialog-close", "aria-label": "Close", children: "×" }) })
|
|
2434
|
+
] })
|
|
2435
|
+
] }) });
|
|
2436
|
+
};
|
|
2437
|
+
|
|
2438
|
+
const OtpInputComponent = ({
|
|
2439
|
+
value,
|
|
2440
|
+
onChange,
|
|
2441
|
+
numInputs = 6,
|
|
2442
|
+
error,
|
|
2443
|
+
disabled = false,
|
|
2444
|
+
autoFocus = true
|
|
2445
|
+
}) => {
|
|
2446
|
+
const containerRef = useRef(null);
|
|
2447
|
+
useEffect(() => {
|
|
2448
|
+
if (autoFocus && containerRef.current) {
|
|
2449
|
+
const firstInput = containerRef.current.querySelector("input");
|
|
2450
|
+
if (firstInput) {
|
|
2451
|
+
firstInput.focus();
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
}, [autoFocus]);
|
|
2455
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "pf-otp-input-container", children: [
|
|
2456
|
+
/* @__PURE__ */ jsx(
|
|
2457
|
+
OtpInput,
|
|
2458
|
+
{
|
|
2459
|
+
value,
|
|
2460
|
+
onChange,
|
|
2461
|
+
numInputs,
|
|
2462
|
+
renderSeparator: /* @__PURE__ */ jsx("span", { className: "pf-otp-separator" }),
|
|
2463
|
+
renderInput: (props) => /* @__PURE__ */ jsx(
|
|
2464
|
+
"input",
|
|
2465
|
+
{
|
|
2466
|
+
...props,
|
|
2467
|
+
className: `pf-otp-input ${error ? "pf-otp-input-error" : ""} ${disabled ? "pf-otp-input-disabled" : ""}`,
|
|
2468
|
+
disabled
|
|
2469
|
+
}
|
|
2470
|
+
),
|
|
2471
|
+
inputType: "tel",
|
|
2472
|
+
shouldAutoFocus: autoFocus
|
|
2473
|
+
}
|
|
2474
|
+
),
|
|
2475
|
+
error && /* @__PURE__ */ jsx("div", { className: "pf-otp-error", children: error })
|
|
2476
|
+
] });
|
|
2477
|
+
};
|
|
2478
|
+
|
|
2479
|
+
const TwoFactorChallenge = ({
|
|
2480
|
+
firstFactorMethod,
|
|
2481
|
+
onSuccess,
|
|
2482
|
+
onError,
|
|
2483
|
+
trustDevice = false
|
|
2484
|
+
}) => {
|
|
2485
|
+
const { challenge, isLoading, error, requestChallenge, verify, switchMethod, selectedMethod } = useTwoFactorChallenge();
|
|
2486
|
+
const [otpValue, setOtpValue] = useState("");
|
|
2487
|
+
const [isMethodSelectorOpen, setIsMethodSelectorOpen] = useState(false);
|
|
2488
|
+
useEffect(() => {
|
|
2489
|
+
requestChallenge(firstFactorMethod);
|
|
2490
|
+
}, [requestChallenge, firstFactorMethod]);
|
|
2491
|
+
useEffect(() => {
|
|
2492
|
+
if (error && onError) {
|
|
2493
|
+
onError(error);
|
|
2494
|
+
}
|
|
2495
|
+
}, [error, onError]);
|
|
2496
|
+
const handleVerify = async () => {
|
|
2497
|
+
if (!otpValue) {
|
|
2498
|
+
return;
|
|
2499
|
+
}
|
|
2500
|
+
const result = await verify(otpValue, trustDevice);
|
|
2501
|
+
if (result) {
|
|
2502
|
+
onSuccess?.();
|
|
2503
|
+
}
|
|
2504
|
+
};
|
|
2505
|
+
const handleSwitchMethod = async (method) => {
|
|
2506
|
+
setOtpValue("");
|
|
2507
|
+
await switchMethod(method);
|
|
2508
|
+
};
|
|
2509
|
+
const handleOtpChange = (value) => {
|
|
2510
|
+
setOtpValue(value);
|
|
2511
|
+
if (value.length === 6) {
|
|
2512
|
+
setTimeout(() => {
|
|
2513
|
+
verify(value, trustDevice).then((result) => {
|
|
2514
|
+
if (result) {
|
|
2515
|
+
onSuccess?.();
|
|
2516
|
+
}
|
|
2517
|
+
});
|
|
2518
|
+
}, 100);
|
|
2519
|
+
}
|
|
2520
|
+
};
|
|
2521
|
+
if (!challenge) {
|
|
2522
|
+
return /* @__PURE__ */ jsx("div", { className: "pf-two-factor-challenge pf-loading", children: /* @__PURE__ */ jsx("p", { children: "Loading challenge..." }) });
|
|
2523
|
+
}
|
|
2524
|
+
const currentMethod = selectedMethod || challenge.method;
|
|
2525
|
+
const availableMethods = [challenge.method, ...challenge.alternative_methods || []];
|
|
2526
|
+
const renderChallengeInput = () => {
|
|
2527
|
+
switch (currentMethod) {
|
|
2528
|
+
case "totp":
|
|
2529
|
+
case "email_otp":
|
|
2530
|
+
case "sms_otp":
|
|
2531
|
+
return /* @__PURE__ */ jsxs("div", { className: "pf-challenge-input-wrapper", children: [
|
|
2532
|
+
/* @__PURE__ */ jsx(
|
|
2533
|
+
OtpInputComponent,
|
|
2534
|
+
{
|
|
2535
|
+
value: otpValue,
|
|
2536
|
+
onChange: handleOtpChange,
|
|
2537
|
+
numInputs: 6,
|
|
2538
|
+
error: error?.message,
|
|
2539
|
+
disabled: isLoading,
|
|
2540
|
+
autoFocus: true
|
|
2541
|
+
}
|
|
2542
|
+
),
|
|
2543
|
+
currentMethod === "email_otp" && challenge.code_sent_to && /* @__PURE__ */ jsxs("p", { className: "pf-challenge-hint", children: [
|
|
2544
|
+
"Code sent to ",
|
|
2545
|
+
challenge.code_sent_to
|
|
2546
|
+
] }),
|
|
2547
|
+
currentMethod === "sms_otp" && challenge.code_sent_to && /* @__PURE__ */ jsxs("p", { className: "pf-challenge-hint", children: [
|
|
2548
|
+
"Code sent to ",
|
|
2549
|
+
challenge.code_sent_to
|
|
2550
|
+
] }),
|
|
2551
|
+
/* @__PURE__ */ jsx(
|
|
2552
|
+
"button",
|
|
2553
|
+
{
|
|
2554
|
+
type: "button",
|
|
2555
|
+
onClick: handleVerify,
|
|
2556
|
+
disabled: isLoading || otpValue.length !== 6,
|
|
2557
|
+
className: "pf-button pf-button-primary",
|
|
2558
|
+
children: isLoading ? "Verifying..." : "Verify"
|
|
2559
|
+
}
|
|
2560
|
+
)
|
|
2561
|
+
] });
|
|
2562
|
+
case "passkey":
|
|
2563
|
+
return /* @__PURE__ */ jsx("div", { className: "pf-challenge-input-wrapper", children: /* @__PURE__ */ jsx("button", { type: "button", onClick: handleVerify, disabled: isLoading, className: "pf-button pf-button-primary", children: isLoading ? "Verifying..." : "Use Passkey" }) });
|
|
2564
|
+
case "recovery_codes":
|
|
2565
|
+
return /* @__PURE__ */ jsxs("div", { className: "pf-challenge-input-wrapper", children: [
|
|
2566
|
+
/* @__PURE__ */ jsx(
|
|
2567
|
+
"input",
|
|
2568
|
+
{
|
|
2569
|
+
type: "text",
|
|
2570
|
+
value: otpValue,
|
|
2571
|
+
onChange: (e) => setOtpValue(e.target.value),
|
|
2572
|
+
placeholder: "Enter recovery code",
|
|
2573
|
+
disabled: isLoading,
|
|
2574
|
+
className: "pf-input"
|
|
2575
|
+
}
|
|
2576
|
+
),
|
|
2577
|
+
/* @__PURE__ */ jsx(
|
|
2578
|
+
"button",
|
|
2579
|
+
{
|
|
2580
|
+
type: "button",
|
|
2581
|
+
onClick: handleVerify,
|
|
2582
|
+
disabled: isLoading || !otpValue,
|
|
2583
|
+
className: "pf-button pf-button-primary",
|
|
2584
|
+
children: isLoading ? "Verifying..." : "Verify"
|
|
2585
|
+
}
|
|
2586
|
+
)
|
|
2587
|
+
] });
|
|
2588
|
+
default:
|
|
2589
|
+
return /* @__PURE__ */ jsxs("p", { children: [
|
|
2590
|
+
"Unsupported method: ",
|
|
2591
|
+
currentMethod
|
|
2592
|
+
] });
|
|
2593
|
+
}
|
|
2594
|
+
};
|
|
2595
|
+
return /* @__PURE__ */ jsxs("div", { className: "pf-two-factor-challenge", children: [
|
|
2596
|
+
/* @__PURE__ */ jsxs("div", { className: "pf-challenge-method-info", children: [
|
|
2597
|
+
/* @__PURE__ */ jsx("h3", { children: "Two-Factor Authentication" }),
|
|
2598
|
+
/* @__PURE__ */ jsx("p", { children: "Enter the verification code" })
|
|
2599
|
+
] }),
|
|
2600
|
+
renderChallengeInput(),
|
|
2601
|
+
availableMethods.length > 1 && /* @__PURE__ */ jsx(
|
|
2602
|
+
"button",
|
|
2603
|
+
{
|
|
2604
|
+
type: "button",
|
|
2605
|
+
onClick: () => setIsMethodSelectorOpen(true),
|
|
2606
|
+
className: "pf-button pf-button-secondary pf-button-switch-method",
|
|
2607
|
+
children: "Use different method"
|
|
2608
|
+
}
|
|
2609
|
+
),
|
|
2610
|
+
/* @__PURE__ */ jsx(
|
|
2611
|
+
MethodSelector,
|
|
2612
|
+
{
|
|
2613
|
+
availableMethods,
|
|
2614
|
+
currentMethod,
|
|
2615
|
+
onSelectMethod: handleSwitchMethod,
|
|
2616
|
+
isOpen: isMethodSelectorOpen,
|
|
2617
|
+
onClose: () => setIsMethodSelectorOpen(false)
|
|
2618
|
+
}
|
|
2619
|
+
)
|
|
2620
|
+
] });
|
|
2621
|
+
};
|
|
2622
|
+
|
|
2193
2623
|
const TwoFactorVerifyForm = ({
|
|
2194
2624
|
onSuccess,
|
|
2195
2625
|
onUseRecovery,
|
|
@@ -2477,7 +2907,8 @@ const TwoFactorRecoveryForm = ({
|
|
|
2477
2907
|
const TwoFactorVerifyFlow = ({
|
|
2478
2908
|
successAuthRedirect,
|
|
2479
2909
|
signInPath = routes.signin.path,
|
|
2480
|
-
twoFactorSetupPath = routes.two_factor_setup?.path
|
|
2910
|
+
twoFactorSetupPath = routes.two_factor_setup?.path,
|
|
2911
|
+
useV2Flow = false
|
|
2481
2912
|
}) => {
|
|
2482
2913
|
const [mode, setMode] = useState("verify");
|
|
2483
2914
|
const [shouldBlockRender, setShouldBlockRender] = useState(false);
|
|
@@ -2530,6 +2961,9 @@ const TwoFactorVerifyFlow = ({
|
|
|
2530
2961
|
if (!passflow.isTwoFactorVerificationRequired() && TwoFactorLoopPrevention.canRedirect()) {
|
|
2531
2962
|
return null;
|
|
2532
2963
|
}
|
|
2964
|
+
if (useV2Flow) {
|
|
2965
|
+
return /* @__PURE__ */ jsx(TwoFactorChallenge, { onSuccess: handleSuccess });
|
|
2966
|
+
}
|
|
2533
2967
|
return /* @__PURE__ */ jsx(Fragment, { children: mode === "verify" ? /* @__PURE__ */ jsx(
|
|
2534
2968
|
TwoFactorVerifyForm,
|
|
2535
2969
|
{
|
|
@@ -6408,5 +6842,5 @@ const PassflowProvider = ({
|
|
|
6408
6842
|
return /* @__PURE__ */ jsx(PassflowContext.Provider, { value: passflowValue, children: /* @__PURE__ */ jsx(NavigationContext$1.Provider, { value: navigationValue, children: /* @__PURE__ */ jsx(AuthProvider, { children }) }) });
|
|
6409
6843
|
};
|
|
6410
6844
|
|
|
6411
|
-
export { Button, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, FieldPassword, FieldPhone, FieldText, ForgotPassword, ForgotPasswordSuccess, Icon, InvitationJoin, Link, PassflowFlow, PassflowProvider, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProvidersBox, ResetPassword, SignIn, SignInForm, SignUp, SignUpForm, Switch, TwoFactorRecoveryForm, TwoFactorSetupForm, TwoFactorSetupMagicLinkFlow, TwoFactorVerifyForm, VerifyChallengeMagicLink, VerifyChallengeOTP, Wrapper, useAppSettings, useAuth, useAuthCloudRedirect, useForgotPassword, useJoinInvite, useLogout, useNavigation, useOutsideClick, usePassflow, usePasswordlessComplete, useProvider, useResetPassword, useSignIn, useSignUp, useTwoFactorManage, useTwoFactorSetup, useTwoFactorSetupMagicLink, useTwoFactorStatus, useTwoFactorVerify, useUserPasskeys };
|
|
6845
|
+
export { Button, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, FieldPassword, FieldPhone, FieldText, ForgotPassword, ForgotPasswordSuccess, Icon, InvitationJoin, Link, PassflowFlow, PassflowProvider, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProvidersBox, ResetPassword, SignIn, SignInForm, SignUp, SignUpForm, Switch, TwoFactorChallenge, TwoFactorRecoveryForm, TwoFactorSetupForm, TwoFactorSetupMagicLinkFlow, TwoFactorVerifyForm, VerifyChallengeMagicLink, VerifyChallengeOTP, Wrapper, useAppSettings, useAuth, useAuthCloudRedirect, useForgotPassword, useJoinInvite, useLogout, useNavigation, useOutsideClick, usePassflow, usePasswordlessComplete, useProvider, useResetPassword, useSessionExpired, useSignIn, useSignUp, useTwoFactorChallenge, useTwoFactorManage, useTwoFactorMethods, useTwoFactorSetup, useTwoFactorSetupMagicLink, useTwoFactorStatus, useTwoFactorVerify, useUserPasskeys };
|
|
6412
6846
|
//# sourceMappingURL=index.es.js.map
|