@stackframe/tanstack-start 2.8.93 → 2.8.95
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/esm/generated/quetzal-translations.d.ts +2 -2
- package/dist/esm/lib/auth.d.ts +3 -1
- package/dist/esm/lib/auth.d.ts.map +1 -1
- package/dist/esm/lib/auth.js +4 -4
- package/dist/esm/lib/auth.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.d.ts +30 -3
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.d.ts.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js +197 -31
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.js +1 -1
- package/dist/esm/lib/stack-app/url-targets.d.ts +1 -2
- package/dist/esm/lib/stack-app/url-targets.d.ts.map +1 -1
- package/dist/esm/lib/stack-app/url-targets.js +19 -31
- package/dist/esm/lib/stack-app/url-targets.js.map +1 -1
- package/dist/esm/lib/stack-app/url-targets.test.js +46 -3
- package/dist/esm/lib/stack-app/url-targets.test.js.map +1 -1
- package/dist/generated/quetzal-translations.d.ts +2 -2
- package/dist/lib/auth.d.ts +3 -1
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +4 -4
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.d.ts +30 -3
- package/dist/lib/stack-app/apps/implementations/client-app-impl.d.ts.map +1 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js +194 -28
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/common.js +1 -1
- package/dist/lib/stack-app/url-targets.d.ts +1 -2
- package/dist/lib/stack-app/url-targets.d.ts.map +1 -1
- package/dist/lib/stack-app/url-targets.js +18 -31
- package/dist/lib/stack-app/url-targets.js.map +1 -1
- package/dist/lib/stack-app/url-targets.test.js +46 -3
- package/dist/lib/stack-app/url-targets.test.js.map +1 -1
- package/package.json +3 -3
|
@@ -14,6 +14,7 @@ let _stackframe_stack_shared_dist_utils_env = require("@stackframe/stack-shared/
|
|
|
14
14
|
let _stackframe_tanstack_start_tanstack_start_server_context = require("@stackframe/tanstack-start/tanstack-start-server-context");
|
|
15
15
|
_stackframe_tanstack_start_tanstack_start_server_context = require_chunk.__toESM(_stackframe_tanstack_start_tanstack_start_server_context);
|
|
16
16
|
let __common_js = require("./common.js");
|
|
17
|
+
let _stackframe_stack_shared_dist_utils_redirect_urls = require("@stackframe/stack-shared/dist/utils/redirect-urls");
|
|
17
18
|
let _stackframe_stack_shared_dist_utils_bytes = require("@stackframe/stack-shared/dist/utils/bytes");
|
|
18
19
|
let ______common_js = require("../../common.js");
|
|
19
20
|
let ______projects_index_js = require("../../projects/index.js");
|
|
@@ -45,6 +46,24 @@ let ____________dev_tool_index_js = require("../../../../dev-tool/index.js");
|
|
|
45
46
|
|
|
46
47
|
//#region src/lib/stack-app/apps/implementations/client-app-impl.ts
|
|
47
48
|
const prefetchedCrossDomainHandoffTtlMs = 3300 * 1e3;
|
|
49
|
+
const nestedCrossDomainAuthQueryParams = {
|
|
50
|
+
refreshTokenId: "stack_nested_cross_domain_auth_refresh_token_id",
|
|
51
|
+
callbackUrl: "stack_nested_cross_domain_auth_callback_url",
|
|
52
|
+
redirectUri: "redirect_uri",
|
|
53
|
+
state: "state",
|
|
54
|
+
codeChallenge: "code_challenge",
|
|
55
|
+
codeChallengeMethod: "code_challenge_method",
|
|
56
|
+
afterCallbackRedirectUrl: "after_callback_redirect_url"
|
|
57
|
+
};
|
|
58
|
+
const oauthCallbackResponseQueryParams = [
|
|
59
|
+
"code",
|
|
60
|
+
"state",
|
|
61
|
+
"error",
|
|
62
|
+
"error_description",
|
|
63
|
+
"errorCode",
|
|
64
|
+
"message",
|
|
65
|
+
"details"
|
|
66
|
+
];
|
|
48
67
|
const allClientApps = /* @__PURE__ */ new Map();
|
|
49
68
|
const STACK_AUTHORIZATION_VALUE_PREFIX = "stackauth_";
|
|
50
69
|
function getAuthorizationHeaderValueFromAuthJson(authJson) {
|
|
@@ -112,7 +131,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
112
131
|
`);
|
|
113
132
|
const location = await (0, _________auth_js.getNewOAuthProviderOrScopeUrl)(this._interface, {
|
|
114
133
|
provider: options.providerId,
|
|
115
|
-
redirectUrl: this.
|
|
134
|
+
redirectUrl: this._getOAuthCallbackRedirectUri(),
|
|
116
135
|
errorRedirectUrl: this.urls.error,
|
|
117
136
|
providerScope: (0, _stackframe_stack_shared_dist_utils_strings.mergeScopeStrings)(options.scope || "", (this._oauthScopesOnSignIn[options.providerId] ?? []).join(" "))
|
|
118
137
|
}, options.session);
|
|
@@ -247,7 +266,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
247
266
|
for (const account of matchingAccounts) if ((await account.getAccessToken({ scopes })).status === "ok") return account;
|
|
248
267
|
const location = await (0, _________auth_js.getNewOAuthProviderOrScopeUrl)(this._interface, {
|
|
249
268
|
provider,
|
|
250
|
-
redirectUrl: this.
|
|
269
|
+
redirectUrl: this._getOAuthCallbackRedirectUri(),
|
|
251
270
|
errorRedirectUrl: this.urls.error,
|
|
252
271
|
providerScope: (0, _stackframe_stack_shared_dist_utils_strings.mergeScopeStrings)(scopeString, (this._oauthScopesOnSignIn[provider] ?? []).join(" "))
|
|
253
272
|
}, session);
|
|
@@ -351,6 +370,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
351
370
|
this._prefetchedCrossDomainHandoffParams = null;
|
|
352
371
|
this._prefetchedCrossDomainHandoffParamsFetchedAt = 0;
|
|
353
372
|
this._isPrefetchingCrossDomainHandoffParams = false;
|
|
373
|
+
this._pendingAuthResolutionPromises = [];
|
|
354
374
|
this._memoryTokenStore = (0, __common_js.createEmptyTokenStore)();
|
|
355
375
|
this._nextServerCookiesTokenStores = /* @__PURE__ */ new WeakMap();
|
|
356
376
|
this._requestTokenStores = /* @__PURE__ */ new WeakMap();
|
|
@@ -420,6 +440,12 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
420
440
|
});
|
|
421
441
|
this._eventTracker.start();
|
|
422
442
|
}
|
|
443
|
+
if ((0, _stackframe_stack_shared_dist_utils_env.isBrowserLike)() && this._isOAuthCallbackUrlHosted() && this._currentUrlLooksLikeStackOAuthCallback()) this._trackPendingAuthResolution(async () => {
|
|
444
|
+
if ((0, _stackframe_stack_shared_dist_utils_env.isBrowserLike)()) await this.callOAuthCallback({ dontWarnAboutMissingQueryParams: true });
|
|
445
|
+
});
|
|
446
|
+
if ((0, _stackframe_stack_shared_dist_utils_env.isBrowserLike)()) this._trackPendingAuthResolution(async () => {
|
|
447
|
+
await this._maybeHandleNestedCrossDomainAuth();
|
|
448
|
+
});
|
|
423
449
|
if ((0, _stackframe_stack_shared_dist_utils_env.isBrowserLike)() && resolvedOptions.devTool !== false) (0, ____________dev_tool_index_js.mountDevTool)(this);
|
|
424
450
|
}
|
|
425
451
|
_initUniqueIdentifier() {
|
|
@@ -427,6 +453,126 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
427
453
|
if (allClientApps.has(this._uniqueIdentifier)) throw new _stackframe_stack_shared_dist_utils_errors.StackAssertionError("A Stack client app with the same unique identifier already exists");
|
|
428
454
|
allClientApps.set(this._uniqueIdentifier, [this._extraOptions?.checkString ?? void 0, this]);
|
|
429
455
|
}
|
|
456
|
+
_trackPendingAuthResolution(callback) {
|
|
457
|
+
const promise = (async () => {
|
|
458
|
+
await Promise.resolve();
|
|
459
|
+
try {
|
|
460
|
+
await callback();
|
|
461
|
+
} catch (error) {
|
|
462
|
+
(0, _stackframe_stack_shared_dist_utils_errors.captureError)("pending-auth-resolution-failed", error);
|
|
463
|
+
}
|
|
464
|
+
})();
|
|
465
|
+
this._pendingAuthResolutionPromises.push(promise);
|
|
466
|
+
(0, _stackframe_stack_shared_dist_utils_promises.runAsynchronously)(async () => {
|
|
467
|
+
try {
|
|
468
|
+
await promise;
|
|
469
|
+
} finally {
|
|
470
|
+
this._pendingAuthResolutionPromises = this._pendingAuthResolutionPromises.filter((p) => p !== promise);
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
async _awaitPendingAuthResolutions(overrideTokenStoreInit, options) {
|
|
475
|
+
if (options?.awaitPendingAuthResolutions === false || overrideTokenStoreInit !== void 0 || !this._hasPersistentTokenStore() || this._pendingAuthResolutionPromises.length === 0) return;
|
|
476
|
+
await Promise.all(this._pendingAuthResolutionPromises);
|
|
477
|
+
}
|
|
478
|
+
_usePendingAuthResolutions(overrideTokenStoreInit) {
|
|
479
|
+
if (overrideTokenStoreInit !== void 0 || !this._hasPersistentTokenStore() || this._pendingAuthResolutionPromises.length === 0) return;
|
|
480
|
+
(0, _stackframe_stack_shared_dist_utils_react.use)(Promise.all(this._pendingAuthResolutionPromises));
|
|
481
|
+
}
|
|
482
|
+
_isOAuthCallbackUrlHosted() {
|
|
483
|
+
const oauthCallbackTarget = this._urlOptions.oauthCallback ?? this._urlOptions.default;
|
|
484
|
+
return typeof oauthCallbackTarget !== "string" && oauthCallbackTarget?.type === "hosted";
|
|
485
|
+
}
|
|
486
|
+
_currentUrlLooksLikeOAuthCallback() {
|
|
487
|
+
if (typeof window === "undefined") return false;
|
|
488
|
+
const currentUrl = new URL(window.location.href);
|
|
489
|
+
return currentUrl.searchParams.has("code") && currentUrl.searchParams.has("state") || currentUrl.searchParams.has("errorCode") && currentUrl.searchParams.has("message");
|
|
490
|
+
}
|
|
491
|
+
_currentUrlLooksLikeStackOAuthCallback() {
|
|
492
|
+
if (typeof window === "undefined") return false;
|
|
493
|
+
const currentUrl = new URL(window.location.href);
|
|
494
|
+
const state = currentUrl.searchParams.get("state");
|
|
495
|
+
if (!currentUrl.searchParams.has("code") || state == null) return false;
|
|
496
|
+
return (0, _________cookie_js.getCookieClient)(`stack-oauth-outer-${state}`) != null;
|
|
497
|
+
}
|
|
498
|
+
_getOAuthCallbackRedirectUri() {
|
|
499
|
+
if (!this._isOAuthCallbackUrlHosted()) return this.urls.oauthCallback;
|
|
500
|
+
if (typeof window === "undefined") throw new _stackframe_stack_shared_dist_utils_errors.StackAssertionError("Hosted OAuth callback URLs require a browser environment to use the current URL as the redirect URI");
|
|
501
|
+
const currentUrl = new URL(window.location.href);
|
|
502
|
+
for (const param of oauthCallbackResponseQueryParams) currentUrl.searchParams.delete(param);
|
|
503
|
+
return currentUrl.toString();
|
|
504
|
+
}
|
|
505
|
+
async _getCurrentRefreshTokenIdIfSignedIn(options) {
|
|
506
|
+
const tokens = await (await this._getSession(void 0, options)).getOrFetchLikelyValidTokens(0, null);
|
|
507
|
+
if (tokens?.refreshToken == null) return null;
|
|
508
|
+
return tokens.accessToken.payload.refresh_token_id;
|
|
509
|
+
}
|
|
510
|
+
async _addNestedCrossDomainAuthParamsToRedirectUrl(options) {
|
|
511
|
+
const targetUrl = new URL(options.url, options.currentUrl);
|
|
512
|
+
if (targetUrl.origin === options.currentUrl.origin) return options.url;
|
|
513
|
+
const refreshTokenId = await this._getCurrentRefreshTokenIdIfSignedIn({ awaitPendingAuthResolutions: options.awaitPendingAuthResolutions });
|
|
514
|
+
if (refreshTokenId == null) return options.url;
|
|
515
|
+
targetUrl.searchParams.set(nestedCrossDomainAuthQueryParams.refreshTokenId, refreshTokenId);
|
|
516
|
+
targetUrl.searchParams.set(nestedCrossDomainAuthQueryParams.callbackUrl, new URL(this._getOAuthCallbackRedirectUri(), options.currentUrl).toString());
|
|
517
|
+
return targetUrl.toString();
|
|
518
|
+
}
|
|
519
|
+
async _maybeHandleNestedCrossDomainAuth() {
|
|
520
|
+
if (typeof window === "undefined") return false;
|
|
521
|
+
const currentUrl = new URL(window.location.href);
|
|
522
|
+
if (currentUrl.searchParams.has("code") && currentUrl.searchParams.has("state")) return false;
|
|
523
|
+
const refreshTokenId = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.refreshTokenId);
|
|
524
|
+
if (refreshTokenId == null) return false;
|
|
525
|
+
const redirectUri = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.redirectUri);
|
|
526
|
+
const state = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.state);
|
|
527
|
+
const codeChallenge = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.codeChallenge);
|
|
528
|
+
if (redirectUri != null || state != null || codeChallenge != null) {
|
|
529
|
+
if (redirectUri == null || state == null || codeChallenge == null) throw new _stackframe_stack_shared_dist_utils_errors.StackAssertionError("Nested cross-domain auth callback URL is missing OAuth request parameters", {
|
|
530
|
+
redirectUri,
|
|
531
|
+
state,
|
|
532
|
+
codeChallenge
|
|
533
|
+
});
|
|
534
|
+
if ((currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.codeChallengeMethod) ?? "S256") !== "S256") throw new _stackframe_stack_shared_dist_utils_errors.StackAssertionError("Nested cross-domain auth only supports S256 PKCE");
|
|
535
|
+
if ((0, _stackframe_stack_shared_dist_utils_urls.isRelative)(redirectUri)) throw new Error("Nested cross-domain auth redirect URI must be absolute.");
|
|
536
|
+
const redirectUriUrl = new URL(redirectUri);
|
|
537
|
+
if (!await this._isTrusted(redirectUriUrl.toString())) throw new Error(`Nested cross-domain auth redirect URI ${redirectUri} is not trusted.`);
|
|
538
|
+
const afterCallbackRedirectUrlString = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.afterCallbackRedirectUrl);
|
|
539
|
+
const afterCallbackRedirectUrl = afterCallbackRedirectUrlString == null ? redirectUriUrl : new URL(afterCallbackRedirectUrlString, redirectUriUrl);
|
|
540
|
+
if (!await this._isTrusted(afterCallbackRedirectUrl.toString())) throw new Error(`Nested cross-domain auth after-callback redirect URL ${afterCallbackRedirectUrlString} is not trusted.`);
|
|
541
|
+
if (await this._getCurrentRefreshTokenIdIfSignedIn({ awaitPendingAuthResolutions: false }) !== refreshTokenId) throw new Error("Nested cross-domain auth source session does not match the requested refresh token ID.");
|
|
542
|
+
await this._redirectTo({
|
|
543
|
+
url: await this._createCrossDomainAuthRedirectUrl({
|
|
544
|
+
redirectUri: redirectUriUrl.toString(),
|
|
545
|
+
state,
|
|
546
|
+
codeChallenge,
|
|
547
|
+
afterCallbackRedirectUrl: afterCallbackRedirectUrl.toString(),
|
|
548
|
+
awaitPendingAuthResolutions: false
|
|
549
|
+
}),
|
|
550
|
+
replace: true
|
|
551
|
+
});
|
|
552
|
+
return true;
|
|
553
|
+
}
|
|
554
|
+
if (await this._getCurrentRefreshTokenIdIfSignedIn({ awaitPendingAuthResolutions: false }) === refreshTokenId) return false;
|
|
555
|
+
const callbackUrlString = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.callbackUrl);
|
|
556
|
+
if (callbackUrlString == null) throw new _stackframe_stack_shared_dist_utils_errors.StackAssertionError("Nested cross-domain auth URL is missing callback URL");
|
|
557
|
+
if ((0, _stackframe_stack_shared_dist_utils_urls.isRelative)(callbackUrlString)) throw new Error("Nested cross-domain auth callback URL must be absolute.");
|
|
558
|
+
const callbackUrl = new URL(callbackUrlString);
|
|
559
|
+
if (!await this._isTrusted(callbackUrl.toString())) throw new Error(`Nested cross-domain auth callback URL ${callbackUrlString} is not trusted.`);
|
|
560
|
+
const afterCallbackRedirectUrl = new URL(currentUrl);
|
|
561
|
+
afterCallbackRedirectUrl.searchParams.delete(nestedCrossDomainAuthQueryParams.refreshTokenId);
|
|
562
|
+
afterCallbackRedirectUrl.searchParams.delete(nestedCrossDomainAuthQueryParams.callbackUrl);
|
|
563
|
+
const { state: newState, codeChallenge: newCodeChallenge } = await this._getCrossDomainHandoffParamsForRedirect(currentUrl);
|
|
564
|
+
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.refreshTokenId, refreshTokenId);
|
|
565
|
+
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.redirectUri, new URL(this._getOAuthCallbackRedirectUri(), currentUrl).toString());
|
|
566
|
+
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.state, newState);
|
|
567
|
+
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.codeChallenge, newCodeChallenge);
|
|
568
|
+
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.codeChallengeMethod, "S256");
|
|
569
|
+
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.afterCallbackRedirectUrl, afterCallbackRedirectUrl.toString());
|
|
570
|
+
await this._redirectTo({
|
|
571
|
+
url: callbackUrl,
|
|
572
|
+
replace: true
|
|
573
|
+
});
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
430
576
|
/**
|
|
431
577
|
* Cloudflare workers does not allow use of randomness on the global scope (on which the Stack app is probably
|
|
432
578
|
* initialized). For that reason, we generate the unique identifier lazily when it is first needed instead of in the
|
|
@@ -619,15 +765,18 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
619
765
|
await (0, _________cookie_js.setOrDeleteCookie)(this._getRefreshTokenDefaultCookieNameForSecure(isSecure), null, cookieOptions);
|
|
620
766
|
});
|
|
621
767
|
}
|
|
768
|
+
async _getTrustedRedirectConfig() {
|
|
769
|
+
const project = _stackframe_stack_shared_dist_utils_results.Result.orThrow(await this._currentProjectCache.getOrWait([], "write-only"));
|
|
770
|
+
return {
|
|
771
|
+
allowLocalhost: project.config.allow_localhost,
|
|
772
|
+
trustedDomains: [...project.config.domains.map((d) => d.domain), new URL((0, ______url_targets_js.getHostedHandlerUrl)({
|
|
773
|
+
projectId: this.projectId,
|
|
774
|
+
pagePath: ""
|
|
775
|
+
})).origin]
|
|
776
|
+
};
|
|
777
|
+
}
|
|
622
778
|
async _getTrustedParentDomain(currentDomain) {
|
|
623
|
-
|
|
624
|
-
const trustedWildcards = domains.filter((d) => d.startsWith("**."));
|
|
625
|
-
const parts = currentDomain.split(".");
|
|
626
|
-
for (let i = parts.length - 2; i >= 0; i--) {
|
|
627
|
-
const parentDomain = parts.slice(i).join(".");
|
|
628
|
-
if (domains.includes(parentDomain) && trustedWildcards.includes("**." + parentDomain)) return parentDomain;
|
|
629
|
-
}
|
|
630
|
-
return null;
|
|
779
|
+
return (0, _stackframe_stack_shared_dist_utils_redirect_urls.getTrustedParentDomain)(currentDomain, (await this._getTrustedRedirectConfig()).trustedDomains);
|
|
631
780
|
}
|
|
632
781
|
_getBrowserCookieTokenStore() {
|
|
633
782
|
if (!(0, _stackframe_stack_shared_dist_utils_env.isBrowserLike)()) throw new Error("Cannot use cookie token store on the server!");
|
|
@@ -784,11 +933,13 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
784
933
|
sessionsBySessionKey.set(sessionKey, session);
|
|
785
934
|
return session;
|
|
786
935
|
}
|
|
787
|
-
async _getSession(overrideTokenStoreInit) {
|
|
936
|
+
async _getSession(overrideTokenStoreInit, options) {
|
|
937
|
+
await this._awaitPendingAuthResolutions(overrideTokenStoreInit, options);
|
|
788
938
|
const tokenStore = this._getOrCreateTokenStore(await this._createCookieHelper(overrideTokenStoreInit), overrideTokenStoreInit);
|
|
789
939
|
return this._getSessionFromTokenStore(tokenStore);
|
|
790
940
|
}
|
|
791
941
|
_useSession(overrideTokenStoreInit) {
|
|
942
|
+
this._usePendingAuthResolutions(overrideTokenStoreInit);
|
|
792
943
|
const tokenStore = this._useTokenStore(overrideTokenStoreInit);
|
|
793
944
|
const subscribe = (0, react.useCallback)((cb) => {
|
|
794
945
|
return (0, __session_refresh_subscription_js.subscribeSessionRefresh)({
|
|
@@ -1244,7 +1395,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1244
1395
|
const scopeString = options?.scopes?.join(" ") ?? "";
|
|
1245
1396
|
const location = await (0, _________auth_js.getNewOAuthProviderOrScopeUrl)(app._interface, {
|
|
1246
1397
|
provider,
|
|
1247
|
-
redirectUrl: app.
|
|
1398
|
+
redirectUrl: app._getOAuthCallbackRedirectUri(),
|
|
1248
1399
|
errorRedirectUrl: app.urls.error,
|
|
1249
1400
|
providerScope: (0, _stackframe_stack_shared_dist_utils_strings.mergeScopeStrings)(scopeString, (app._oauthScopesOnSignIn[provider] ?? []).join(" "))
|
|
1250
1401
|
}, session);
|
|
@@ -1778,10 +1929,17 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1778
1929
|
}
|
|
1779
1930
|
async _isTrusted(url) {
|
|
1780
1931
|
if ((0, _stackframe_stack_shared_dist_utils_urls.isRelative)(url)) return true;
|
|
1781
|
-
|
|
1782
|
-
|
|
1932
|
+
const parsedUrl = (0, _stackframe_stack_shared_dist_utils_urls.createUrlIfValid)(url);
|
|
1933
|
+
if (parsedUrl == null) return false;
|
|
1934
|
+
if (typeof window !== "undefined" && window.location.origin === parsedUrl.origin) return true;
|
|
1935
|
+
if ((0, ______url_targets_js.isHostedHandlerUrlForProject)({
|
|
1783
1936
|
url,
|
|
1784
1937
|
projectId: this.projectId
|
|
1938
|
+
})) return true;
|
|
1939
|
+
const trustedRedirectConfig = await this._getTrustedRedirectConfig();
|
|
1940
|
+
return (0, _stackframe_stack_shared_dist_utils_redirect_urls.validateRedirectUrl)(parsedUrl, {
|
|
1941
|
+
allowLocalhost: trustedRedirectConfig.allowLocalhost,
|
|
1942
|
+
trustedDomains: trustedRedirectConfig.trustedDomains
|
|
1785
1943
|
});
|
|
1786
1944
|
}
|
|
1787
1945
|
get urls() {
|
|
@@ -1830,6 +1988,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1830
1988
|
};
|
|
1831
1989
|
}
|
|
1832
1990
|
_getLocalOAuthCallbackHandlerUrl() {
|
|
1991
|
+
if (this._isOAuthCallbackUrlHosted()) return this._getOAuthCallbackRedirectUri();
|
|
1833
1992
|
return (0, ______url_targets_js.resolveHandlerUrls)({
|
|
1834
1993
|
urls: {
|
|
1835
1994
|
...this._urlOptions,
|
|
@@ -1840,7 +1999,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1840
1999
|
}).oauthCallback;
|
|
1841
2000
|
}
|
|
1842
2001
|
async _createCrossDomainAuthRedirectUrl(options) {
|
|
1843
|
-
const session = await this._getSession();
|
|
2002
|
+
const session = await this._getSession(void 0, { awaitPendingAuthResolutions: options.awaitPendingAuthResolutions });
|
|
1844
2003
|
const response = await this._interface.sendClientRequest("/auth/oauth/cross-domain/authorize", {
|
|
1845
2004
|
method: "POST",
|
|
1846
2005
|
headers: { "Content-Type": "application/json" },
|
|
@@ -1894,7 +2053,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1894
2053
|
...options
|
|
1895
2054
|
});
|
|
1896
2055
|
}
|
|
1897
|
-
async _redirectToHandler(handlerName, options) {
|
|
2056
|
+
async _redirectToHandler(handlerName, options, internalOptions) {
|
|
1898
2057
|
const rawHandlerUrl = (0, __common_js.getUrls)(this._urlOptions, { projectId: this.projectId })[handlerName];
|
|
1899
2058
|
if (!rawHandlerUrl) throw new Error(`No URL for handler name ${handlerName}`);
|
|
1900
2059
|
const currentUrl = typeof window === "undefined" ? null : new URL(window.location.href);
|
|
@@ -1911,7 +2070,8 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1911
2070
|
redirectUri: plan.redirectUri,
|
|
1912
2071
|
state: plan.state,
|
|
1913
2072
|
codeChallenge: plan.codeChallenge,
|
|
1914
|
-
afterCallbackRedirectUrl: plan.afterCallbackRedirectUrl
|
|
2073
|
+
afterCallbackRedirectUrl: plan.afterCallbackRedirectUrl,
|
|
2074
|
+
awaitPendingAuthResolutions: internalOptions?.awaitPendingAuthResolutions
|
|
1915
2075
|
});
|
|
1916
2076
|
await this._redirectTo({
|
|
1917
2077
|
url: crossDomainRedirectUrl,
|
|
@@ -1919,7 +2079,12 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1919
2079
|
});
|
|
1920
2080
|
return;
|
|
1921
2081
|
}
|
|
1922
|
-
await this.
|
|
2082
|
+
const redirectUrl = currentUrl != null && handlerName !== "signOut" && handlerName !== "afterSignOut" && handlerName !== "oauthCallback" ? await this._addNestedCrossDomainAuthParamsToRedirectUrl({
|
|
2083
|
+
url: plan.url,
|
|
2084
|
+
currentUrl,
|
|
2085
|
+
awaitPendingAuthResolutions: internalOptions?.awaitPendingAuthResolutions
|
|
2086
|
+
}) : plan.url;
|
|
2087
|
+
await this._redirectIfTrusted(redirectUrl, options);
|
|
1923
2088
|
}
|
|
1924
2089
|
_redirectToHandlerDuringRender(handlerName, options) {
|
|
1925
2090
|
if (this._redirectMethod === "tanstack-start" && !(0, _stackframe_stack_shared_dist_utils_env.isBrowserLike)()) {
|
|
@@ -2176,7 +2341,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2176
2341
|
const executeOAuth = async (challenge) => {
|
|
2177
2342
|
return await this._interface.authorizeOAuth({
|
|
2178
2343
|
provider,
|
|
2179
|
-
redirectUrl: (0, ____________utils_url_js.constructRedirectUrl)(this.
|
|
2344
|
+
redirectUrl: (0, ____________utils_url_js.constructRedirectUrl)(this._getOAuthCallbackRedirectUri(), "redirectUrl"),
|
|
2180
2345
|
errorRedirectUrl: (0, ____________utils_url_js.constructRedirectUrl)(this.urls.error, "errorRedirectUrl"),
|
|
2181
2346
|
afterCallbackRedirectUrl,
|
|
2182
2347
|
type: "authenticate",
|
|
@@ -2224,7 +2389,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2224
2389
|
try {
|
|
2225
2390
|
return await callback();
|
|
2226
2391
|
} catch (e) {
|
|
2227
|
-
if (_stackframe_stack_shared.KnownErrors.MultiFactorAuthenticationRequired.isInstance(e)) return _stackframe_stack_shared_dist_utils_results.Result.ok(await this._experimentalMfa(e, await this._getSession()));
|
|
2392
|
+
if (_stackframe_stack_shared.KnownErrors.MultiFactorAuthenticationRequired.isInstance(e)) return _stackframe_stack_shared_dist_utils_results.Result.ok(await this._experimentalMfa(e, await this._getSession(void 0, { awaitPendingAuthResolutions: false })));
|
|
2228
2393
|
throw e;
|
|
2229
2394
|
}
|
|
2230
2395
|
}
|
|
@@ -2299,8 +2464,8 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2299
2464
|
}
|
|
2300
2465
|
if (result.status === "ok") {
|
|
2301
2466
|
await this._signInToAccountWithTokens(result.data);
|
|
2302
|
-
if (!options?.noRedirect) if (result.data.newUser) await this.
|
|
2303
|
-
else await this.
|
|
2467
|
+
if (!options?.noRedirect) if (result.data.newUser) await this._redirectToHandler("afterSignUp", { replace: true }, { awaitPendingAuthResolutions: false });
|
|
2468
|
+
else await this._redirectToHandler("afterSignIn", { replace: true }, { awaitPendingAuthResolutions: false });
|
|
2304
2469
|
return _stackframe_stack_shared_dist_utils_results.Result.ok(void 0);
|
|
2305
2470
|
} else return _stackframe_stack_shared_dist_utils_results.Result.error(result.error);
|
|
2306
2471
|
}
|
|
@@ -2415,10 +2580,10 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2415
2580
|
return _stackframe_stack_shared_dist_utils_results.Result.ok(void 0);
|
|
2416
2581
|
} else return _stackframe_stack_shared_dist_utils_results.Result.error(result.error);
|
|
2417
2582
|
}
|
|
2418
|
-
async callOAuthCallback() {
|
|
2583
|
+
async callOAuthCallback(options) {
|
|
2419
2584
|
if (typeof window === "undefined") throw new Error("callOAuthCallback can currently only be called in a browser environment");
|
|
2420
|
-
this._ensurePersistentTokenStore();
|
|
2421
|
-
let oauthCallbackRedirectUri = this.
|
|
2585
|
+
if (this._currentUrlLooksLikeOAuthCallback()) this._ensurePersistentTokenStore();
|
|
2586
|
+
let oauthCallbackRedirectUri = this._getOAuthCallbackRedirectUri();
|
|
2422
2587
|
const currentUrl = new URL(window.location.href);
|
|
2423
2588
|
if (currentUrl.searchParams.get(__redirect_page_urls_js.crossDomainAuthQueryParams.marker) === "1") {
|
|
2424
2589
|
currentUrl.searchParams.delete("code");
|
|
@@ -2428,7 +2593,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2428
2593
|
let result;
|
|
2429
2594
|
try {
|
|
2430
2595
|
result = await this._catchMfaRequiredError(async () => {
|
|
2431
|
-
return await (0, _________auth_js.callOAuthCallback)(this._interface, oauthCallbackRedirectUri);
|
|
2596
|
+
return await (0, _________auth_js.callOAuthCallback)(this._interface, oauthCallbackRedirectUri, options);
|
|
2432
2597
|
});
|
|
2433
2598
|
} catch (e) {
|
|
2434
2599
|
if (_stackframe_stack_shared.KnownErrors.InvalidTotpCode.isInstance(e)) {
|
|
@@ -2437,6 +2602,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2437
2602
|
} else throw e;
|
|
2438
2603
|
}
|
|
2439
2604
|
if (result.status === "ok" && result.data) {
|
|
2605
|
+
this._ensurePersistentTokenStore();
|
|
2440
2606
|
await this._signInToAccountWithTokens(result.data);
|
|
2441
2607
|
if ("afterCallbackRedirectUrl" in result.data && result.data.afterCallbackRedirectUrl) {
|
|
2442
2608
|
await this._redirectTo({
|
|
@@ -2445,10 +2611,10 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2445
2611
|
});
|
|
2446
2612
|
return true;
|
|
2447
2613
|
} else if (result.data.newUser) {
|
|
2448
|
-
await this.
|
|
2614
|
+
await this._redirectToHandler("afterSignUp", { replace: true }, { awaitPendingAuthResolutions: false });
|
|
2449
2615
|
return true;
|
|
2450
2616
|
} else {
|
|
2451
|
-
await this.
|
|
2617
|
+
await this._redirectToHandler("afterSignIn", { replace: true }, { awaitPendingAuthResolutions: false });
|
|
2452
2618
|
return true;
|
|
2453
2619
|
}
|
|
2454
2620
|
}
|