@passflow/react 0.6.1 → 0.7.1
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/README.md +42 -0
- package/dist/index.cjs.js +4 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +341 -94
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/flow/upgrade-required-placeholder.d.ts +21 -0
- package/dist/src/components/flow/upgrade-required-placeholder.d.ts.map +1 -0
- package/dist/src/components/form/signin/index.d.ts.map +1 -1
- package/dist/src/components/provider/index.d.ts +2 -1
- package/dist/src/components/provider/index.d.ts.map +1 -1
- package/dist/src/components/provider/passflow-provider.d.ts +66 -1
- package/dist/src/components/provider/passflow-provider.d.ts.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -4
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,
|
|
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.
|
|
23
|
+
const version = "0.7.1";
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
4679
|
-
navigate({ to: resetTokenType?.redirect_url ?? successAuthRedirect ?? appSettings?.defaults
|
|
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
|
|
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
|
|
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
|