@passflow/react 0.6.0 → 0.7.0

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.es.js CHANGED
@@ -5,8 +5,8 @@ import 'dayjs';
5
5
  import clsx from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
7
7
  import * as React from 'react';
8
- import { useState, useEffect, forwardRef, createContext, useCallback, useContext, useRef, useLayoutEffect, useMemo, useReducer } from 'react';
9
- import { PassflowEvent, parseToken, Passflow } from '@passflow/core';
8
+ import React__default, { useState, useEffect, forwardRef, createContext, useCallback, useContext, useRef, useLayoutEffect, useMemo, useReducer } from 'react';
9
+ import { PassflowEvent, Passflow, parseToken } from '@passflow/core';
10
10
  export * from '@passflow/core';
11
11
  import queryString from 'query-string';
12
12
  import { getCountryForTimezone } from 'countries-and-timezones';
@@ -20,7 +20,7 @@ import { phone as phone$1 } from 'phone';
20
20
  import { useForm, Controller } from 'react-hook-form';
21
21
  import 'react-dom';
22
22
 
23
- const version = "0.6.0";
23
+ const version = "0.7.0";
24
24
 
25
25
  window.passflowReactAppVersion = () => {
26
26
  console.log(`App Version: ${version}`);
@@ -3111,6 +3111,323 @@ const ErrorComponent = ({ error = defaultErrorMessage, goBackRedirectTo }) => {
3111
3111
  );
3112
3112
  };
3113
3113
 
3114
+ const AUTH_ENDPOINT_PATTERN = /\/auth\/(login|passwordless|passkey|2fa|session\/exchange)\b|\/auth\/federated\/start\b/;
3115
+ const readParentChallengeIdFromURL = () => {
3116
+ if (typeof window === "undefined") return void 0;
3117
+ const raw = new URLSearchParams(window.location.search);
3118
+ const lower = new URLSearchParams(Array.from(raw, ([key, value2]) => [key.toLowerCase(), value2]));
3119
+ const value = lower.get("parent_challenge_id");
3120
+ return value || void 0;
3121
+ };
3122
+ const bootParentChallengeId = readParentChallengeIdFromURL();
3123
+ const useOIDCInterceptor = (parentChallengeId) => {
3124
+ useEffect(() => {
3125
+ if (!parentChallengeId || typeof window === "undefined") {
3126
+ return;
3127
+ }
3128
+ const isAuthURL = (url) => AUTH_ENDPOINT_PATTERN.test(url);
3129
+ const injectParentChallenge = (raw) => {
3130
+ if (!raw) return void 0;
3131
+ try {
3132
+ const obj = JSON.parse(raw);
3133
+ if ("parent_challenge_id" in obj) return void 0;
3134
+ obj.parent_challenge_id = parentChallengeId;
3135
+ return JSON.stringify(obj);
3136
+ } catch {
3137
+ return void 0;
3138
+ }
3139
+ };
3140
+ const followRedirectURL = (raw) => {
3141
+ if (!raw) return;
3142
+ try {
3143
+ const obj = JSON.parse(raw);
3144
+ if (typeof obj.redirect_url === "string" && obj.redirect_url) {
3145
+ window.location.assign(obj.redirect_url);
3146
+ }
3147
+ } catch {
3148
+ }
3149
+ };
3150
+ const originalFetch = window.fetch;
3151
+ window.fetch = async (input, init) => {
3152
+ let url = "";
3153
+ if (typeof input === "string") url = input;
3154
+ else if (input instanceof URL) url = input.toString();
3155
+ else if (input instanceof Request) url = input.url;
3156
+ const method = init?.method?.toUpperCase() ?? "GET";
3157
+ let outInit = init;
3158
+ if (method === "POST" && isAuthURL(url) && typeof init?.body === "string") {
3159
+ const rewritten = injectParentChallenge(init.body);
3160
+ if (rewritten !== void 0) outInit = { ...init, body: rewritten };
3161
+ }
3162
+ const response = await originalFetch(input, outInit);
3163
+ if (response.ok && isAuthURL(url)) {
3164
+ try {
3165
+ const cloned = response.clone();
3166
+ const text = await cloned.text();
3167
+ followRedirectURL(text);
3168
+ } catch {
3169
+ }
3170
+ }
3171
+ return response;
3172
+ };
3173
+ const OriginalXHROpen = XMLHttpRequest.prototype.open;
3174
+ const OriginalXHRSend = XMLHttpRequest.prototype.send;
3175
+ const tracker = /* @__PURE__ */ new WeakMap();
3176
+ XMLHttpRequest.prototype.open = function(method, url, ...rest) {
3177
+ const urlStr = typeof url === "string" ? url : url.toString();
3178
+ tracker.set(this, {
3179
+ method: method?.toUpperCase(),
3180
+ url: urlStr,
3181
+ isAuth: isAuthURL(urlStr)
3182
+ });
3183
+ this.addEventListener("load", () => {
3184
+ const meta = tracker.get(this);
3185
+ if (!meta?.isAuth) return;
3186
+ if (this.status >= 200 && this.status < 300) {
3187
+ followRedirectURL(typeof this.responseText === "string" ? this.responseText : null);
3188
+ }
3189
+ });
3190
+ OriginalXHROpen.call(this, method, url, ...rest);
3191
+ };
3192
+ XMLHttpRequest.prototype.send = function(body) {
3193
+ const meta = tracker.get(this);
3194
+ let outBody = body;
3195
+ if (meta?.isAuth && meta.method === "POST" && typeof body === "string") {
3196
+ const rewritten = injectParentChallenge(body);
3197
+ if (rewritten !== void 0) outBody = rewritten;
3198
+ }
3199
+ OriginalXHRSend.call(this, outBody);
3200
+ };
3201
+ return () => {
3202
+ window.fetch = originalFetch;
3203
+ XMLHttpRequest.prototype.open = OriginalXHROpen;
3204
+ XMLHttpRequest.prototype.send = OriginalXHRSend;
3205
+ };
3206
+ }, [parentChallengeId]);
3207
+ };
3208
+ const useSessionExchangeOnMount = (parentChallengeId, passflow, baseUrl, appId) => {
3209
+ const [exchangeState, setExchangeState] = useState("idle");
3210
+ const [parentMeta, setParentMeta] = useState(void 0);
3211
+ const attemptedRef = useRef(false);
3212
+ useEffect(() => {
3213
+ if (!parentChallengeId || attemptedRef.current) {
3214
+ return;
3215
+ }
3216
+ if (!appId) {
3217
+ return;
3218
+ }
3219
+ attemptedRef.current = true;
3220
+ const run = async () => {
3221
+ let meta;
3222
+ try {
3223
+ const base = baseUrl ?? "";
3224
+ const url = `${base}/oidc/requests/${encodeURIComponent(parentChallengeId)}`;
3225
+ const res = await fetch(url);
3226
+ if (res.ok) {
3227
+ meta = await res.json();
3228
+ setParentMeta(meta);
3229
+ }
3230
+ } catch {
3231
+ }
3232
+ if (meta?.oidc_prompt_login) {
3233
+ setExchangeState("fallback_to_login");
3234
+ return;
3235
+ }
3236
+ if (meta?.max_age && meta.max_age > 0) {
3237
+ const parsed = passflow.getParsedTokens?.();
3238
+ const accessPayload = parsed?.access_token?.payload;
3239
+ const idPayload = parsed?.id_token?.payload;
3240
+ const authTime = accessPayload?.auth_time ?? idPayload?.auth_time;
3241
+ if (authTime && typeof authTime === "number") {
3242
+ const ageSeconds = Math.floor(Date.now() / 1e3) - authTime;
3243
+ if (ageSeconds > meta.max_age) {
3244
+ setExchangeState("fallback_to_login");
3245
+ return;
3246
+ }
3247
+ }
3248
+ }
3249
+ setExchangeState("exchanging");
3250
+ try {
3251
+ let accessToken;
3252
+ try {
3253
+ const tokens = await passflow.getTokens(false);
3254
+ accessToken = tokens?.access_token;
3255
+ } catch {
3256
+ }
3257
+ const base = baseUrl ?? "";
3258
+ const headers = {
3259
+ "Content-Type": "application/json"
3260
+ };
3261
+ if (accessToken) {
3262
+ headers.Authorization = `Bearer ${accessToken}`;
3263
+ }
3264
+ if (appId) {
3265
+ headers["X-Passflow-ClientID"] = appId;
3266
+ }
3267
+ const res = await fetch(`${base}/auth/session/exchange`, {
3268
+ method: "POST",
3269
+ credentials: "include",
3270
+ headers,
3271
+ body: JSON.stringify({ parent_challenge_id: parentChallengeId })
3272
+ });
3273
+ if (res.ok) {
3274
+ try {
3275
+ const body = await res.json();
3276
+ if (body.redirect_url) {
3277
+ return;
3278
+ }
3279
+ } catch {
3280
+ }
3281
+ setExchangeState("fallback_to_login");
3282
+ return;
3283
+ }
3284
+ if (res.status === 403) {
3285
+ setExchangeState("fallback_to_login");
3286
+ return;
3287
+ }
3288
+ if (res.status === 401 || res.status === 400) {
3289
+ if (meta?.oidc_prompt_none && meta.redirect_uri) {
3290
+ const dest = new URL(meta.redirect_uri);
3291
+ dest.searchParams.set("error", "login_required");
3292
+ dest.searchParams.set("error_description", "user is not authenticated");
3293
+ if (meta.state) dest.searchParams.set("state", meta.state);
3294
+ window.location.assign(dest.toString());
3295
+ return;
3296
+ }
3297
+ setExchangeState("fallback_to_login");
3298
+ return;
3299
+ }
3300
+ setExchangeState("fallback_to_login");
3301
+ } catch {
3302
+ setExchangeState("fallback_to_login");
3303
+ }
3304
+ };
3305
+ void run();
3306
+ }, [parentChallengeId, passflow, baseUrl, appId]);
3307
+ return { exchangeState, parentMeta };
3308
+ };
3309
+ const DefaultContinuingPlaceholder = ({ appName }) => /* @__PURE__ */ jsx(
3310
+ "div",
3311
+ {
3312
+ style: {
3313
+ display: "flex",
3314
+ alignItems: "center",
3315
+ justifyContent: "center",
3316
+ minHeight: "100vh",
3317
+ fontFamily: "system-ui, sans-serif",
3318
+ fontSize: "1rem",
3319
+ color: "#444"
3320
+ },
3321
+ children: appName ? `Continuing to ${appName}…` : "Continuing…"
3322
+ }
3323
+ );
3324
+ const DefaultUpgradeRequiredPlaceholder = () => /* @__PURE__ */ jsx(
3325
+ "div",
3326
+ {
3327
+ style: {
3328
+ display: "flex",
3329
+ alignItems: "center",
3330
+ justifyContent: "center",
3331
+ padding: "1rem",
3332
+ fontFamily: "system-ui, sans-serif",
3333
+ fontSize: "0.95rem",
3334
+ color: "#666"
3335
+ },
3336
+ children: "Additional authentication required (not yet implemented — please log in again)."
3337
+ }
3338
+ );
3339
+ const OIDCExchangeContext = React__default.createContext({
3340
+ exchangeState: "idle"
3341
+ });
3342
+ const PassflowProvider = ({
3343
+ children,
3344
+ navigate: initialNavigate,
3345
+ router = "default",
3346
+ ...config
3347
+ }) => {
3348
+ const needsDiscovery = !config.appId;
3349
+ const [state, dispatch] = useReducer(passflowReducer, {
3350
+ ...initialState,
3351
+ ...config,
3352
+ isDiscoveringAppId: needsDiscovery
3353
+ });
3354
+ const [navigate, setNavigate] = useState(() => {
3355
+ if (initialNavigate) {
3356
+ return initialNavigate;
3357
+ }
3358
+ return defaultNavigate;
3359
+ });
3360
+ const passflow = useMemo(() => new Passflow(state), [state]);
3361
+ const parentChallengeId = useMemo(() => readParentChallengeIdFromURL() ?? bootParentChallengeId, []);
3362
+ useOIDCInterceptor(parentChallengeId);
3363
+ const { exchangeState, parentMeta } = useSessionExchangeOnMount(parentChallengeId, passflow, config.url, state.appId);
3364
+ const discoveryAttemptedRef = useRef(false);
3365
+ useEffect(() => {
3366
+ if (needsDiscovery && !discoveryAttemptedRef.current && state.isDiscoveringAppId) {
3367
+ discoveryAttemptedRef.current = true;
3368
+ const discoverAppId = async () => {
3369
+ const urlsToTry = ["/settings"];
3370
+ if (config.url) {
3371
+ urlsToTry.push(`${config.url}/settings`);
3372
+ }
3373
+ for (const url of urlsToTry) {
3374
+ try {
3375
+ const response = await fetch(url);
3376
+ if (response.ok) {
3377
+ const settings = await response.json();
3378
+ const discoveredAppId = settings.login_app?.app_id || settings.appId;
3379
+ if (discoveredAppId) {
3380
+ passflow.setAppId(discoveredAppId);
3381
+ dispatch({
3382
+ type: "SET_PASSFLOW_STATE",
3383
+ payload: {
3384
+ ...state,
3385
+ appId: discoveredAppId,
3386
+ scopes: settings.login_app?.scopes || settings.scopes || state.scopes,
3387
+ createTenantForNewUser: settings.login_app?.create_tenant_for_new_user ?? settings.createTenantForNewUser ?? state.createTenantForNewUser,
3388
+ isDiscoveringAppId: false
3389
+ }
3390
+ });
3391
+ return;
3392
+ }
3393
+ }
3394
+ } catch (error) {
3395
+ }
3396
+ }
3397
+ console.warn("Failed to discover appId from /settings");
3398
+ dispatch({
3399
+ type: "SET_PASSFLOW_STATE",
3400
+ payload: {
3401
+ ...state,
3402
+ isDiscoveringAppId: false
3403
+ }
3404
+ });
3405
+ };
3406
+ void discoverAppId();
3407
+ }
3408
+ }, [needsDiscovery, state.isDiscoveringAppId, config.url, passflow, state]);
3409
+ const passflowValue = useMemo(() => ({ state, dispatch, passflow }), [state, passflow]);
3410
+ const handleSetNavigate = useCallback((newNavigate) => {
3411
+ setNavigate(() => newNavigate || defaultNavigate);
3412
+ }, []);
3413
+ const navigationValue = useMemo(
3414
+ () => ({
3415
+ navigate,
3416
+ setNavigate: handleSetNavigate,
3417
+ router
3418
+ }),
3419
+ [navigate, handleSetNavigate, router]
3420
+ );
3421
+ const oidcExchangeValue = useMemo(
3422
+ () => ({ parentChallengeId, parentMeta, exchangeState }),
3423
+ [parentChallengeId, parentMeta, exchangeState]
3424
+ );
3425
+ return /* @__PURE__ */ jsx(PassflowContext.Provider, { value: passflowValue, children: /* @__PURE__ */ jsx(NavigationContext$1.Provider, { value: navigationValue, children: /* @__PURE__ */ jsx(OIDCExchangeContext.Provider, { value: oidcExchangeValue, children: /* @__PURE__ */ jsx(AuthProvider, { children: exchangeState === "exchanging" ? /* @__PURE__ */ jsx(DefaultContinuingPlaceholder, { appName: parentMeta?.app_name }) : exchangeState === "upgrade_required" ? /* @__PURE__ */ jsxs(Fragment, { children: [
3426
+ /* @__PURE__ */ jsx(DefaultUpgradeRequiredPlaceholder, {}),
3427
+ children
3428
+ ] }) : children }) }) }) });
3429
+ };
3430
+
3114
3431
  const excludeRoutes = ["verify-challenge-otp", "password/reset", "two-factor-verify", "two-factor-recovery"];
3115
3432
  const withError = (Component, ErrorComponent) => (props) => {
3116
3433
  const context = useContext(PassflowContext);
@@ -3223,6 +3540,13 @@ const SignInForm = ({
3223
3540
  setForcePasswordless(checked);
3224
3541
  resetFormStates();
3225
3542
  };
3543
+ const warnIfOIDCFlowLeaked = () => {
3544
+ if (readParentChallengeIdFromURL()) {
3545
+ console.error(
3546
+ "[passflow] login took the legacy token path while parent_challenge_id is present on the URL — the OIDC interceptor did not engage and the RP redirect will not happen"
3547
+ );
3548
+ }
3549
+ };
3226
3550
  const onSubmitPasswordHandler = async (userPayload) => {
3227
3551
  const payload = {
3228
3552
  ...userPayload,
@@ -3234,7 +3558,8 @@ const SignInForm = ({
3234
3558
  navigate({ to: twoFactorVerifyPath ?? routes.two_factor_verify.path });
3235
3559
  return;
3236
3560
  }
3237
- const redirectUrl = successAuthRedirect ?? appSettings?.defaults.redirect ?? "";
3561
+ warnIfOIDCFlowLeaked();
3562
+ const redirectUrl = successAuthRedirect ?? appSettings?.defaults?.redirect ?? "";
3238
3563
  if (!isValidUrl(redirectUrl)) navigate({ to: redirectUrl });
3239
3564
  else window.location.href = await getUrlWithTokens(passflow, redirectUrl);
3240
3565
  }
@@ -3250,7 +3575,8 @@ const SignInForm = ({
3250
3575
  navigate({ to: twoFactorVerifyPath ?? routes.two_factor_verify.path });
3251
3576
  return;
3252
3577
  }
3253
- const redirectUrl = successAuthRedirect ?? appSettings?.defaults.redirect ?? "";
3578
+ warnIfOIDCFlowLeaked();
3579
+ const redirectUrl = successAuthRedirect ?? appSettings?.defaults?.redirect ?? "";
3254
3580
  if (!isValidUrl(redirectUrl)) navigate({ to: redirectUrl });
3255
3581
  else window.location.href = await getUrlWithTokens(passflow, redirectUrl);
3256
3582
  }
@@ -3261,7 +3587,7 @@ const SignInForm = ({
3261
3587
  ...userPayload,
3262
3588
  challenge_type: getPasswordlessData(authMethods, defaultMethod)?.challengeType,
3263
3589
  create_tenant: createTenantForNewUser,
3264
- redirect_url: successAuthRedirect ?? appSettings?.defaults.redirect,
3590
+ redirect_url: successAuthRedirect ?? appSettings?.defaults?.redirect,
3265
3591
  ...!isEmpty(inviteToken) && { invite_token: inviteToken }
3266
3592
  };
3267
3593
  const response = await fetch(payload, "passwordless");
@@ -3692,13 +4018,13 @@ const SignUpForm = ({
3692
4018
  };
3693
4019
  const status = await fetch(payload, "password");
3694
4020
  if (status) {
3695
- const redirectUrl = successAuthRedirect ?? appSettings?.defaults.redirect ?? "";
4021
+ const redirectUrl = successAuthRedirect ?? appSettings?.defaults?.redirect ?? "";
3696
4022
  if (!isValidUrl(redirectUrl)) navigate({ to: redirectUrl });
3697
4023
  else window.location.href = await getUrlWithTokens(passflow, redirectUrl);
3698
4024
  }
3699
4025
  };
3700
4026
  const onSubmitPasskeyHandler = async () => {
3701
- const redirectUrl = successAuthRedirect ?? appSettings?.defaults.redirect ?? "";
4027
+ const redirectUrl = successAuthRedirect ?? appSettings?.defaults?.redirect ?? "";
3702
4028
  const payload = {
3703
4029
  relying_party_id: relyingPartyId,
3704
4030
  create_tenant: createTenantForNewUser,
@@ -3718,7 +4044,7 @@ const SignUpForm = ({
3718
4044
  ...userPayload,
3719
4045
  challenge_type: currentChallegeType,
3720
4046
  create_tenant: createTenantForNewUser,
3721
- redirect_url: successAuthRedirect ?? appSettings?.defaults.redirect,
4047
+ redirect_url: successAuthRedirect ?? appSettings?.defaults?.redirect,
3722
4048
  ...!isEmpty(inviteToken) && { invite_token: inviteToken }
3723
4049
  };
3724
4050
  const response = await fetch(payload, "passwordless");
@@ -4204,7 +4530,7 @@ const VerifyChallengeOTPManual = ({
4204
4530
  const payload = {
4205
4531
  create_tenant: createTenantForNewUser,
4206
4532
  challenge_type: challengeType,
4207
- redirect_url: successAuthRedirect ?? appSettings?.defaults.redirect ?? "",
4533
+ redirect_url: successAuthRedirect ?? appSettings?.defaults?.redirect ?? "",
4208
4534
  ...identity === "email" ? { email: identityValue } : { phone: identityValue }
4209
4535
  };
4210
4536
  const refetchResponse = await refetch(payload, type);
@@ -4457,7 +4783,7 @@ const ForgotPassword = ({
4457
4783
  ...isEmail && { email: values.email_or_username },
4458
4784
  ...isUsername && { username: values.email_or_username },
4459
4785
  ...isPhone && { phone: validatedPhone.phoneNumber },
4460
- redirect_url: successResetRedirect ?? appSettings?.defaults.redirect
4786
+ redirect_url: successResetRedirect ?? appSettings?.defaults?.redirect
4461
4787
  };
4462
4788
  const status = await fetch(payload);
4463
4789
  if (status) {
@@ -4675,12 +5001,12 @@ const ResetPassword = ({ successAuthRedirect }) => {
4675
5001
  const resetTokenType = resetTokenData;
4676
5002
  const status = await fetch(values.password);
4677
5003
  if (status) {
4678
- if (!isValidUrl(resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults.redirect))
4679
- navigate({ to: resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults.redirect });
5004
+ if (!isValidUrl(resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults?.redirect))
5005
+ navigate({ to: resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults?.redirect });
4680
5006
  else
4681
5007
  window.location.href = await getUrlWithTokens(
4682
5008
  passflow,
4683
- resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults.redirect
5009
+ resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults?.redirect
4684
5010
  );
4685
5011
  }
4686
5012
  };
@@ -4843,7 +5169,7 @@ const InvitationJoinFlow = ({
4843
5169
  type: "button",
4844
5170
  variant: "primary",
4845
5171
  className: "passflow-button-invitation-join",
4846
- onClick: () => void onClickAcceptInvitationHandler(redirectUrl ?? successAuthRedirect ?? appSettings?.defaults.redirect),
5172
+ onClick: () => void onClickAcceptInvitationHandler(redirectUrl ?? successAuthRedirect ?? appSettings?.defaults?.redirect),
4847
5173
  disabled: isInvitationJoinLoading,
4848
5174
  children: "Accept invitation"
4849
5175
  }
@@ -6978,84 +7304,5 @@ function formatCountdown(seconds) {
6978
7304
  return `${mins}:${secs.toString().padStart(2, "0")}`;
6979
7305
  }
6980
7306
 
6981
- const PassflowProvider = ({
6982
- children,
6983
- navigate: initialNavigate,
6984
- router = "default",
6985
- ...config
6986
- }) => {
6987
- const needsDiscovery = !config.appId;
6988
- const [state, dispatch] = useReducer(passflowReducer, {
6989
- ...initialState,
6990
- ...config,
6991
- isDiscoveringAppId: needsDiscovery
6992
- });
6993
- const [navigate, setNavigate] = useState(() => {
6994
- if (initialNavigate) {
6995
- return initialNavigate;
6996
- }
6997
- return defaultNavigate;
6998
- });
6999
- const passflow = useMemo(() => new Passflow(state), [state]);
7000
- const discoveryAttemptedRef = useRef(false);
7001
- useEffect(() => {
7002
- if (needsDiscovery && !discoveryAttemptedRef.current && state.isDiscoveringAppId) {
7003
- discoveryAttemptedRef.current = true;
7004
- const discoverAppId = async () => {
7005
- const urlsToTry = ["/settings"];
7006
- if (config.url) {
7007
- urlsToTry.push(`${config.url}/settings`);
7008
- }
7009
- for (const url of urlsToTry) {
7010
- try {
7011
- const response = await fetch(url);
7012
- if (response.ok) {
7013
- const settings = await response.json();
7014
- const discoveredAppId = settings.login_app?.app_id || settings.appId;
7015
- if (discoveredAppId) {
7016
- passflow.setAppId(discoveredAppId);
7017
- dispatch({
7018
- type: "SET_PASSFLOW_STATE",
7019
- payload: {
7020
- ...state,
7021
- appId: discoveredAppId,
7022
- scopes: settings.login_app?.scopes || settings.scopes || state.scopes,
7023
- createTenantForNewUser: settings.login_app?.create_tenant_for_new_user ?? settings.createTenantForNewUser ?? state.createTenantForNewUser,
7024
- isDiscoveringAppId: false
7025
- }
7026
- });
7027
- return;
7028
- }
7029
- }
7030
- } catch (error) {
7031
- }
7032
- }
7033
- console.warn("Failed to discover appId from /settings");
7034
- dispatch({
7035
- type: "SET_PASSFLOW_STATE",
7036
- payload: {
7037
- ...state,
7038
- isDiscoveringAppId: false
7039
- }
7040
- });
7041
- };
7042
- void discoverAppId();
7043
- }
7044
- }, [needsDiscovery, state.isDiscoveringAppId, config.url, passflow, state]);
7045
- const passflowValue = useMemo(() => ({ state, dispatch, passflow }), [state, passflow]);
7046
- const handleSetNavigate = useCallback((newNavigate) => {
7047
- setNavigate(() => newNavigate || defaultNavigate);
7048
- }, []);
7049
- const navigationValue = useMemo(
7050
- () => ({
7051
- navigate,
7052
- setNavigate: handleSetNavigate,
7053
- router
7054
- }),
7055
- [navigate, handleSetNavigate, router]
7056
- );
7057
- return /* @__PURE__ */ jsx(PassflowContext.Provider, { value: passflowValue, children: /* @__PURE__ */ jsx(NavigationContext$1.Provider, { value: navigationValue, children: /* @__PURE__ */ jsx(AuthProvider, { children }) }) });
7058
- };
7059
-
7060
7307
  export { Button, CLIBrowserAuth, CLIQRAuth, 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, useCLIAuth, useForgotPassword, useJoinInvite, useLogout, useNavigation, useOutsideClick, usePassflow, usePasswordlessComplete, useProvider, useResetPassword, useSessionExpired, useSignIn, useSignUp, useTwoFactorChallenge, useTwoFactorManage, useTwoFactorMethods, useTwoFactorSetup, useTwoFactorSetupMagicLink, useTwoFactorStatus, useTwoFactorVerify, useUserPasskeys };
7061
7308
  //# sourceMappingURL=index.es.js.map