@stackframe/stack 2.4.18 → 2.4.20
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/CHANGELOG.md +18 -0
- package/dist/components-core/index.d.mts +4 -4
- package/dist/components-core/index.d.ts +4 -4
- package/dist/esm/lib/stack-app.js +118 -55
- package/dist/esm/lib/stack-app.js.map +1 -1
- package/dist/lib/stack-app.d.mts +78 -5
- package/dist/lib/stack-app.d.ts +78 -5
- package/dist/lib/stack-app.js +116 -53
- package/dist/lib/stack-app.js.map +1 -1
- package/dist/providers/component-provider.d.mts +6 -6
- package/dist/providers/component-provider.d.ts +6 -6
- package/package.json +3 -3
package/dist/lib/stack-app.d.mts
CHANGED
|
@@ -4,7 +4,7 @@ import { ReadonlyJson } from '@stackframe/stack-shared/dist/utils/json';
|
|
|
4
4
|
import { ProjectUpdateOptions, ApiKeySetCreateOptions } from '@stackframe/stack-shared/dist/interface/adminInterface';
|
|
5
5
|
import { ServerUserUpdateJson, ServerTeamCustomizableJson, ServerPermissionDefinitionCustomizableJson, ServerPermissionDefinitionJson, EmailTemplateType } from '@stackframe/stack-shared/dist/interface/serverInterface';
|
|
6
6
|
import { ListEmailTemplatesCrud, EmailTemplateCrud } from '@stackframe/stack-shared/dist/interface/crud/email-templates';
|
|
7
|
-
import {
|
|
7
|
+
import { InternalSession } from '@stackframe/stack-shared/dist/sessions';
|
|
8
8
|
|
|
9
9
|
type RequestLike = {
|
|
10
10
|
headers: {
|
|
@@ -45,7 +45,7 @@ type StackServerAppConstructorOptions<HasTokenStore extends boolean, ProjectId e
|
|
|
45
45
|
type StackAdminAppConstructorOptions<HasTokenStore extends boolean, ProjectId extends string> = ((StackServerAppConstructorOptions<HasTokenStore, ProjectId> & {
|
|
46
46
|
superSecretAdminKey?: string;
|
|
47
47
|
}) | (Omit<StackServerAppConstructorOptions<HasTokenStore, ProjectId>, "publishableClientKey" | "secretServerKey"> & {
|
|
48
|
-
projectOwnerSession:
|
|
48
|
+
projectOwnerSession: InternalSession;
|
|
49
49
|
}));
|
|
50
50
|
type StackClientAppJson<HasTokenStore extends boolean, ProjectId extends string> = StackClientAppConstructorOptions<HasTokenStore, ProjectId> & {
|
|
51
51
|
uniqueIdentifier: string;
|
|
@@ -54,11 +54,21 @@ declare const stackAppInternalsSymbol: unique symbol;
|
|
|
54
54
|
type RedirectToOptions = {
|
|
55
55
|
replace?: boolean;
|
|
56
56
|
};
|
|
57
|
+
type Session = {
|
|
58
|
+
getTokens(): Promise<{
|
|
59
|
+
accessToken: string | null;
|
|
60
|
+
refreshToken: string | null;
|
|
61
|
+
}>;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Contains everything related to the current user session.
|
|
65
|
+
*/
|
|
57
66
|
type Auth<T, C> = {
|
|
58
|
-
readonly
|
|
59
|
-
|
|
60
|
-
update(this: T, user: C): Promise<void>;
|
|
67
|
+
readonly _internalSession: InternalSession;
|
|
68
|
+
readonly currentSession: Session;
|
|
61
69
|
signOut(this: T): Promise<void>;
|
|
70
|
+
update(this: T, user: C): Promise<void>;
|
|
71
|
+
updateSelectedTeam(this: T, team: Team | null): Promise<void>;
|
|
62
72
|
sendVerificationEmail(this: T): Promise<KnownErrors["EmailAlreadyVerified"] | void>;
|
|
63
73
|
updatePassword(this: T, options: {
|
|
64
74
|
oldPassword: string;
|
|
@@ -252,6 +262,69 @@ type StackClientApp<HasTokenStore extends boolean = boolean, ProjectId extends s
|
|
|
252
262
|
verifyPasswordResetCode(code: string): Promise<KnownErrors["PasswordResetCodeError"] | void>;
|
|
253
263
|
verifyEmail(code: string): Promise<KnownErrors["EmailVerificationError"] | void>;
|
|
254
264
|
signInWithMagicLink(code: string): Promise<KnownErrors["MagicLinkError"] | void>;
|
|
265
|
+
/**
|
|
266
|
+
* With most browsers now disabling third-party cookies by default, the best way to send authenticated requests
|
|
267
|
+
* across different origins is to pass the tokens in a header.
|
|
268
|
+
*
|
|
269
|
+
* This function returns a header object that can be used with `fetch` or other HTTP request libraries to send
|
|
270
|
+
* authenticated requests.
|
|
271
|
+
*
|
|
272
|
+
* On the server, you can then pass in the `Request` object to the `tokenStore` option
|
|
273
|
+
* on your Stack app to fetch user details. Please note that CORS by default does not allow custom headers, so you
|
|
274
|
+
* must set the [`Access-Control-Allow-Headers` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers)
|
|
275
|
+
* to include `x-stack-auth` in the CORS preflight response.
|
|
276
|
+
*
|
|
277
|
+
* Example:
|
|
278
|
+
*
|
|
279
|
+
* ```ts
|
|
280
|
+
* // client
|
|
281
|
+
* const res = await fetch("https://api.example.com", {
|
|
282
|
+
* headers: {
|
|
283
|
+
* ...await stackApp.getCrossOriginHeaders()
|
|
284
|
+
* // you can also add your own headers here
|
|
285
|
+
* },
|
|
286
|
+
* });
|
|
287
|
+
*
|
|
288
|
+
* // server
|
|
289
|
+
* function handleRequest(req: Request) {
|
|
290
|
+
* const user = await stackServerApp.getUser({ tokenStore: req });
|
|
291
|
+
* return new Response("Welcome, " + user.displayName);
|
|
292
|
+
* }
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
getCrossOriginHeaders(): Promise<{
|
|
296
|
+
"x-stack-auth": string;
|
|
297
|
+
}>;
|
|
298
|
+
/**
|
|
299
|
+
* With most browsers now disabling third-party cookies by default, there need to be new ways to send authenticated
|
|
300
|
+
* requests across different origins. While `getCrossOriginHeaders` is the recommended way to do this, there
|
|
301
|
+
* are some cases where you might want to send the tokens differently, for example when you are using WebSockets
|
|
302
|
+
* or non-HTTP protocols.
|
|
303
|
+
*
|
|
304
|
+
* This function returns a token object that can be JSON-serialized and sent to the server in any way you like.
|
|
305
|
+
* There, you can use the `tokenStore` option on your Stack app to fetch user details.
|
|
306
|
+
*
|
|
307
|
+
* Example:
|
|
308
|
+
*
|
|
309
|
+
* ```ts
|
|
310
|
+
* // client
|
|
311
|
+
* const res = await rpcCall(rpcEndpoint, {
|
|
312
|
+
* data: {
|
|
313
|
+
* auth: await stackApp.getCrossOriginTokenObject(),
|
|
314
|
+
* },
|
|
315
|
+
* });
|
|
316
|
+
*
|
|
317
|
+
* // server
|
|
318
|
+
* function handleRequest(data) {
|
|
319
|
+
* const user = await stackServerApp.getUser({ tokenStore: data.auth });
|
|
320
|
+
* return new Response("Welcome, " + user.displayName);
|
|
321
|
+
* }
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
getCrossOriginTokenObject(): Promise<{
|
|
325
|
+
accessToken: string | null;
|
|
326
|
+
refreshToken: string | null;
|
|
327
|
+
}>;
|
|
255
328
|
[stackAppInternalsSymbol]: {
|
|
256
329
|
toClientJson(): StackClientAppJson<HasTokenStore, ProjectId>;
|
|
257
330
|
setCurrentUser(userJsonPromise: Promise<UserJson | null>): void;
|
package/dist/lib/stack-app.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { ReadonlyJson } from '@stackframe/stack-shared/dist/utils/json';
|
|
|
4
4
|
import { ProjectUpdateOptions, ApiKeySetCreateOptions } from '@stackframe/stack-shared/dist/interface/adminInterface';
|
|
5
5
|
import { ServerUserUpdateJson, ServerTeamCustomizableJson, ServerPermissionDefinitionCustomizableJson, ServerPermissionDefinitionJson, EmailTemplateType } from '@stackframe/stack-shared/dist/interface/serverInterface';
|
|
6
6
|
import { ListEmailTemplatesCrud, EmailTemplateCrud } from '@stackframe/stack-shared/dist/interface/crud/email-templates';
|
|
7
|
-
import {
|
|
7
|
+
import { InternalSession } from '@stackframe/stack-shared/dist/sessions';
|
|
8
8
|
|
|
9
9
|
type RequestLike = {
|
|
10
10
|
headers: {
|
|
@@ -45,7 +45,7 @@ type StackServerAppConstructorOptions<HasTokenStore extends boolean, ProjectId e
|
|
|
45
45
|
type StackAdminAppConstructorOptions<HasTokenStore extends boolean, ProjectId extends string> = ((StackServerAppConstructorOptions<HasTokenStore, ProjectId> & {
|
|
46
46
|
superSecretAdminKey?: string;
|
|
47
47
|
}) | (Omit<StackServerAppConstructorOptions<HasTokenStore, ProjectId>, "publishableClientKey" | "secretServerKey"> & {
|
|
48
|
-
projectOwnerSession:
|
|
48
|
+
projectOwnerSession: InternalSession;
|
|
49
49
|
}));
|
|
50
50
|
type StackClientAppJson<HasTokenStore extends boolean, ProjectId extends string> = StackClientAppConstructorOptions<HasTokenStore, ProjectId> & {
|
|
51
51
|
uniqueIdentifier: string;
|
|
@@ -54,11 +54,21 @@ declare const stackAppInternalsSymbol: unique symbol;
|
|
|
54
54
|
type RedirectToOptions = {
|
|
55
55
|
replace?: boolean;
|
|
56
56
|
};
|
|
57
|
+
type Session = {
|
|
58
|
+
getTokens(): Promise<{
|
|
59
|
+
accessToken: string | null;
|
|
60
|
+
refreshToken: string | null;
|
|
61
|
+
}>;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Contains everything related to the current user session.
|
|
65
|
+
*/
|
|
57
66
|
type Auth<T, C> = {
|
|
58
|
-
readonly
|
|
59
|
-
|
|
60
|
-
update(this: T, user: C): Promise<void>;
|
|
67
|
+
readonly _internalSession: InternalSession;
|
|
68
|
+
readonly currentSession: Session;
|
|
61
69
|
signOut(this: T): Promise<void>;
|
|
70
|
+
update(this: T, user: C): Promise<void>;
|
|
71
|
+
updateSelectedTeam(this: T, team: Team | null): Promise<void>;
|
|
62
72
|
sendVerificationEmail(this: T): Promise<KnownErrors["EmailAlreadyVerified"] | void>;
|
|
63
73
|
updatePassword(this: T, options: {
|
|
64
74
|
oldPassword: string;
|
|
@@ -252,6 +262,69 @@ type StackClientApp<HasTokenStore extends boolean = boolean, ProjectId extends s
|
|
|
252
262
|
verifyPasswordResetCode(code: string): Promise<KnownErrors["PasswordResetCodeError"] | void>;
|
|
253
263
|
verifyEmail(code: string): Promise<KnownErrors["EmailVerificationError"] | void>;
|
|
254
264
|
signInWithMagicLink(code: string): Promise<KnownErrors["MagicLinkError"] | void>;
|
|
265
|
+
/**
|
|
266
|
+
* With most browsers now disabling third-party cookies by default, the best way to send authenticated requests
|
|
267
|
+
* across different origins is to pass the tokens in a header.
|
|
268
|
+
*
|
|
269
|
+
* This function returns a header object that can be used with `fetch` or other HTTP request libraries to send
|
|
270
|
+
* authenticated requests.
|
|
271
|
+
*
|
|
272
|
+
* On the server, you can then pass in the `Request` object to the `tokenStore` option
|
|
273
|
+
* on your Stack app to fetch user details. Please note that CORS by default does not allow custom headers, so you
|
|
274
|
+
* must set the [`Access-Control-Allow-Headers` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers)
|
|
275
|
+
* to include `x-stack-auth` in the CORS preflight response.
|
|
276
|
+
*
|
|
277
|
+
* Example:
|
|
278
|
+
*
|
|
279
|
+
* ```ts
|
|
280
|
+
* // client
|
|
281
|
+
* const res = await fetch("https://api.example.com", {
|
|
282
|
+
* headers: {
|
|
283
|
+
* ...await stackApp.getCrossOriginHeaders()
|
|
284
|
+
* // you can also add your own headers here
|
|
285
|
+
* },
|
|
286
|
+
* });
|
|
287
|
+
*
|
|
288
|
+
* // server
|
|
289
|
+
* function handleRequest(req: Request) {
|
|
290
|
+
* const user = await stackServerApp.getUser({ tokenStore: req });
|
|
291
|
+
* return new Response("Welcome, " + user.displayName);
|
|
292
|
+
* }
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
getCrossOriginHeaders(): Promise<{
|
|
296
|
+
"x-stack-auth": string;
|
|
297
|
+
}>;
|
|
298
|
+
/**
|
|
299
|
+
* With most browsers now disabling third-party cookies by default, there need to be new ways to send authenticated
|
|
300
|
+
* requests across different origins. While `getCrossOriginHeaders` is the recommended way to do this, there
|
|
301
|
+
* are some cases where you might want to send the tokens differently, for example when you are using WebSockets
|
|
302
|
+
* or non-HTTP protocols.
|
|
303
|
+
*
|
|
304
|
+
* This function returns a token object that can be JSON-serialized and sent to the server in any way you like.
|
|
305
|
+
* There, you can use the `tokenStore` option on your Stack app to fetch user details.
|
|
306
|
+
*
|
|
307
|
+
* Example:
|
|
308
|
+
*
|
|
309
|
+
* ```ts
|
|
310
|
+
* // client
|
|
311
|
+
* const res = await rpcCall(rpcEndpoint, {
|
|
312
|
+
* data: {
|
|
313
|
+
* auth: await stackApp.getCrossOriginTokenObject(),
|
|
314
|
+
* },
|
|
315
|
+
* });
|
|
316
|
+
*
|
|
317
|
+
* // server
|
|
318
|
+
* function handleRequest(data) {
|
|
319
|
+
* const user = await stackServerApp.getUser({ tokenStore: data.auth });
|
|
320
|
+
* return new Response("Welcome, " + user.displayName);
|
|
321
|
+
* }
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
getCrossOriginTokenObject(): Promise<{
|
|
325
|
+
accessToken: string | null;
|
|
326
|
+
refreshToken: string | null;
|
|
327
|
+
}>;
|
|
255
328
|
[stackAppInternalsSymbol]: {
|
|
256
329
|
toClientJson(): StackClientAppJson<HasTokenStore, ProjectId>;
|
|
257
330
|
setCurrentUser(userJsonPromise: Promise<UserJson | null>): void;
|
package/dist/lib/stack-app.js
CHANGED
|
@@ -59,7 +59,7 @@ var cookie = __toESM(require("cookie"));
|
|
|
59
59
|
var import_sessions = require("@stackframe/stack-shared/dist/sessions");
|
|
60
60
|
var import_use_trigger = require("@stackframe/stack-shared/dist/hooks/use-trigger");
|
|
61
61
|
var NextNavigation = (0, import_compile_time.scrambleDuringCompileTime)(NextNavigationUnscrambled);
|
|
62
|
-
var clientVersion = "js @stackframe/stack@2.4.
|
|
62
|
+
var clientVersion = "js @stackframe/stack@2.4.20";
|
|
63
63
|
function permissionDefinitionScopeToType(scope) {
|
|
64
64
|
return { "any-team": "team", "specific-team": "team", "global": "global" }[scope.type];
|
|
65
65
|
}
|
|
@@ -105,43 +105,6 @@ function createEmptyTokenStore() {
|
|
|
105
105
|
accessToken: null
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
|
-
var storedCookieTokenStore = null;
|
|
109
|
-
var getCookieTokenStore = () => {
|
|
110
|
-
if (!(0, import_env.isBrowserLike)()) {
|
|
111
|
-
throw new Error("Cannot use cookie token store on the server!");
|
|
112
|
-
}
|
|
113
|
-
if (storedCookieTokenStore === null) {
|
|
114
|
-
const getCurrentValue = () => ({
|
|
115
|
-
refreshToken: (0, import_cookie.getCookie)("stack-refresh"),
|
|
116
|
-
accessToken: (0, import_cookie.getCookie)("stack-access")
|
|
117
|
-
});
|
|
118
|
-
storedCookieTokenStore = new import_stores.Store(getCurrentValue());
|
|
119
|
-
let hasSucceededInWriting = true;
|
|
120
|
-
setInterval(() => {
|
|
121
|
-
if (hasSucceededInWriting) {
|
|
122
|
-
const currentValue = getCurrentValue();
|
|
123
|
-
const oldValue = storedCookieTokenStore.get();
|
|
124
|
-
if (JSON.stringify(currentValue) !== JSON.stringify(oldValue)) {
|
|
125
|
-
storedCookieTokenStore.set(currentValue);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}, 100);
|
|
129
|
-
storedCookieTokenStore.onChange((value) => {
|
|
130
|
-
try {
|
|
131
|
-
(0, import_cookie.setOrDeleteCookie)("stack-refresh", value.refreshToken, { maxAge: 60 * 60 * 24 * 365 });
|
|
132
|
-
(0, import_cookie.setOrDeleteCookie)("stack-access", value.accessToken, { maxAge: 60 * 60 * 24 });
|
|
133
|
-
hasSucceededInWriting = true;
|
|
134
|
-
} catch (e) {
|
|
135
|
-
if (!(0, import_env.isBrowserLike)()) {
|
|
136
|
-
hasSucceededInWriting = false;
|
|
137
|
-
} else {
|
|
138
|
-
throw e;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
return storedCookieTokenStore;
|
|
144
|
-
};
|
|
145
108
|
var loadingSentinel = Symbol("stackAppCacheLoadingSentinel");
|
|
146
109
|
function useAsyncCache(cache, dependencies, caller) {
|
|
147
110
|
(0, import_react2.suspendIfSsr)(caller);
|
|
@@ -249,24 +212,72 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
249
212
|
}
|
|
250
213
|
_memoryTokenStore = createEmptyTokenStore();
|
|
251
214
|
_requestTokenStores = /* @__PURE__ */ new WeakMap();
|
|
215
|
+
_storedCookieTokenStore = null;
|
|
216
|
+
get _refreshTokenCookieName() {
|
|
217
|
+
return `stack-refresh-${this.projectId}`;
|
|
218
|
+
}
|
|
219
|
+
get _accessTokenCookieName() {
|
|
220
|
+
return `stack-access`;
|
|
221
|
+
}
|
|
222
|
+
_getCookieTokenStore() {
|
|
223
|
+
if (!(0, import_env.isBrowserLike)()) {
|
|
224
|
+
throw new Error("Cannot use cookie token store on the server!");
|
|
225
|
+
}
|
|
226
|
+
if (this._storedCookieTokenStore === null) {
|
|
227
|
+
const getCurrentValue = (old) => ({
|
|
228
|
+
refreshToken: (0, import_cookie.getCookie)(this._refreshTokenCookieName) ?? (0, import_cookie.getCookie)("stack-refresh"),
|
|
229
|
+
// keep old cookie name for backwards-compatibility
|
|
230
|
+
// if there is an access token in memory already, don't update the access token based on cookies (access token
|
|
231
|
+
// cookies may be set by another project on the same domain)
|
|
232
|
+
// see the comment in _accessTokenCookieName for more information
|
|
233
|
+
accessToken: old === null ? (0, import_cookie.getCookie)(this._accessTokenCookieName) : old.accessToken
|
|
234
|
+
});
|
|
235
|
+
this._storedCookieTokenStore = new import_stores.Store(getCurrentValue(null));
|
|
236
|
+
let hasSucceededInWriting = true;
|
|
237
|
+
setInterval(() => {
|
|
238
|
+
if (hasSucceededInWriting) {
|
|
239
|
+
const oldValue = this._storedCookieTokenStore.get();
|
|
240
|
+
const currentValue = getCurrentValue(oldValue);
|
|
241
|
+
if (!(0, import_objects.deepPlainEquals)(currentValue, oldValue)) {
|
|
242
|
+
this._storedCookieTokenStore.set(currentValue);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}, 100);
|
|
246
|
+
this._storedCookieTokenStore.onChange((value) => {
|
|
247
|
+
try {
|
|
248
|
+
(0, import_cookie.setOrDeleteCookie)(this._refreshTokenCookieName, value.refreshToken, { maxAge: 60 * 60 * 24 * 365 });
|
|
249
|
+
(0, import_cookie.setOrDeleteCookie)(this._accessTokenCookieName, value.accessToken, { maxAge: 60 * 60 * 24 });
|
|
250
|
+
hasSucceededInWriting = true;
|
|
251
|
+
} catch (e) {
|
|
252
|
+
if (!(0, import_env.isBrowserLike)()) {
|
|
253
|
+
hasSucceededInWriting = false;
|
|
254
|
+
} else {
|
|
255
|
+
throw e;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
return this._storedCookieTokenStore;
|
|
261
|
+
}
|
|
252
262
|
_getOrCreateTokenStore(overrideTokenStoreInit) {
|
|
253
263
|
const tokenStoreInit = overrideTokenStoreInit === void 0 ? this._tokenStoreInit : overrideTokenStoreInit;
|
|
254
264
|
switch (tokenStoreInit) {
|
|
255
265
|
case "cookie": {
|
|
256
|
-
return
|
|
266
|
+
return this._getCookieTokenStore();
|
|
257
267
|
}
|
|
258
268
|
case "nextjs-cookie": {
|
|
259
269
|
if ((0, import_env.isBrowserLike)()) {
|
|
260
|
-
return
|
|
270
|
+
return this._getCookieTokenStore();
|
|
261
271
|
} else {
|
|
262
272
|
const store = new import_stores.Store({
|
|
263
|
-
refreshToken: (0, import_cookie.getCookie)("stack-refresh"),
|
|
264
|
-
|
|
273
|
+
refreshToken: (0, import_cookie.getCookie)(this._refreshTokenCookieName) ?? (0, import_cookie.getCookie)("stack-refresh"),
|
|
274
|
+
// keep old cookie name for backwards-compatibility
|
|
275
|
+
accessToken: (0, import_cookie.getCookie)(this._accessTokenCookieName)
|
|
265
276
|
});
|
|
266
277
|
store.onChange((value) => {
|
|
267
278
|
try {
|
|
268
|
-
(0, import_cookie.setOrDeleteCookie)(
|
|
269
|
-
(0, import_cookie.setOrDeleteCookie)(
|
|
279
|
+
(0, import_cookie.setOrDeleteCookie)(this._refreshTokenCookieName, value.refreshToken, { maxAge: 60 * 60 * 24 * 365 });
|
|
280
|
+
(0, import_cookie.setOrDeleteCookie)(this._accessTokenCookieName, value.accessToken, { maxAge: 60 * 60 * 24 });
|
|
270
281
|
} catch (e) {
|
|
271
282
|
}
|
|
272
283
|
});
|
|
@@ -276,21 +287,43 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
276
287
|
case "memory": {
|
|
277
288
|
return this._memoryTokenStore;
|
|
278
289
|
}
|
|
279
|
-
case null: {
|
|
280
|
-
return createEmptyTokenStore();
|
|
281
|
-
}
|
|
282
290
|
default: {
|
|
283
|
-
if (tokenStoreInit
|
|
291
|
+
if (tokenStoreInit === null) {
|
|
292
|
+
return createEmptyTokenStore();
|
|
293
|
+
} else if (typeof tokenStoreInit === "object" && "headers" in tokenStoreInit) {
|
|
284
294
|
if (this._requestTokenStores.has(tokenStoreInit))
|
|
285
295
|
return this._requestTokenStores.get(tokenStoreInit);
|
|
296
|
+
const stackAuthHeader = tokenStoreInit.headers.get("x-stack-auth");
|
|
297
|
+
if (stackAuthHeader) {
|
|
298
|
+
let parsed2;
|
|
299
|
+
try {
|
|
300
|
+
parsed2 = JSON.parse(stackAuthHeader);
|
|
301
|
+
if (typeof parsed2 !== "object")
|
|
302
|
+
throw new Error("x-stack-auth header must be a JSON object");
|
|
303
|
+
if (parsed2 === null)
|
|
304
|
+
throw new Error("x-stack-auth header must not be null");
|
|
305
|
+
} catch (e) {
|
|
306
|
+
throw new Error(`Invalid x-stack-auth header: ${stackAuthHeader}`, { cause: e });
|
|
307
|
+
}
|
|
308
|
+
return this._getOrCreateTokenStore({
|
|
309
|
+
accessToken: parsed2.accessToken ?? null,
|
|
310
|
+
refreshToken: parsed2.refreshToken ?? null
|
|
311
|
+
});
|
|
312
|
+
}
|
|
286
313
|
const cookieHeader = tokenStoreInit.headers.get("cookie");
|
|
287
314
|
const parsed = cookie.parse(cookieHeader || "");
|
|
288
315
|
const res = new import_stores.Store({
|
|
289
|
-
refreshToken: parsed["stack-refresh"] || null,
|
|
290
|
-
|
|
316
|
+
refreshToken: parsed[this._refreshTokenCookieName] || parsed["stack-refresh"] || null,
|
|
317
|
+
// keep old cookie name for backwards-compatibility
|
|
318
|
+
accessToken: parsed[this._accessTokenCookieName] || null
|
|
291
319
|
});
|
|
292
320
|
this._requestTokenStores.set(tokenStoreInit, res);
|
|
293
321
|
return res;
|
|
322
|
+
} else if ("accessToken" in tokenStoreInit || "refreshToken" in tokenStoreInit) {
|
|
323
|
+
return new import_stores.Store({
|
|
324
|
+
refreshToken: tokenStoreInit.refreshToken,
|
|
325
|
+
accessToken: tokenStoreInit.accessToken
|
|
326
|
+
});
|
|
294
327
|
}
|
|
295
328
|
throw new Error(`Invalid token store ${tokenStoreInit}`);
|
|
296
329
|
}
|
|
@@ -307,7 +340,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
307
340
|
_sessionsByTokenStoreAndSessionKey = /* @__PURE__ */ new WeakMap();
|
|
308
341
|
_getSessionFromTokenStore(tokenStore) {
|
|
309
342
|
const tokenObj = tokenStore.get();
|
|
310
|
-
const sessionKey = import_sessions.
|
|
343
|
+
const sessionKey = import_sessions.InternalSession.calculateSessionKey(tokenObj);
|
|
311
344
|
const existing = sessionKey ? this._sessionsByTokenStoreAndSessionKey.get(tokenStore)?.get(sessionKey) : null;
|
|
312
345
|
if (existing)
|
|
313
346
|
return existing;
|
|
@@ -481,7 +514,16 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
481
514
|
const app = this;
|
|
482
515
|
const currentUser = {
|
|
483
516
|
...this._userFromJson(json),
|
|
484
|
-
session,
|
|
517
|
+
_internalSession: session,
|
|
518
|
+
currentSession: {
|
|
519
|
+
async getTokens() {
|
|
520
|
+
const tokens = await session.getPotentiallyExpiredTokens();
|
|
521
|
+
return {
|
|
522
|
+
accessToken: tokens?.accessToken.token ?? null,
|
|
523
|
+
refreshToken: tokens?.refreshToken?.token ?? null
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
},
|
|
485
527
|
async updateSelectedTeam(team) {
|
|
486
528
|
await app._updateUser({ selectedTeamId: team?.id ?? null }, session);
|
|
487
529
|
},
|
|
@@ -568,6 +610,18 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
568
610
|
get urls() {
|
|
569
611
|
return getUrls(this._urlOptions);
|
|
570
612
|
}
|
|
613
|
+
async getCrossOriginHeaders() {
|
|
614
|
+
return {
|
|
615
|
+
"x-stack-auth": JSON.stringify(await this.getCrossOriginTokenObject())
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
async getCrossOriginTokenObject() {
|
|
619
|
+
const user = await this.getUser();
|
|
620
|
+
if (!user)
|
|
621
|
+
return { accessToken: null, refreshToken: null };
|
|
622
|
+
const tokens = await user.currentSession.getTokens();
|
|
623
|
+
return tokens;
|
|
624
|
+
}
|
|
571
625
|
async _redirectTo(handlerName, options) {
|
|
572
626
|
const url = this.urls[handlerName];
|
|
573
627
|
if (!url) {
|
|
@@ -1019,7 +1073,16 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
|
|
|
1019
1073
|
const nonCurrentServerUser = this._serverUserFromJson(json);
|
|
1020
1074
|
const currentUser = {
|
|
1021
1075
|
...nonCurrentServerUser,
|
|
1022
|
-
session,
|
|
1076
|
+
_internalSession: session,
|
|
1077
|
+
currentSession: {
|
|
1078
|
+
async getTokens() {
|
|
1079
|
+
const tokens = await session.getPotentiallyExpiredTokens();
|
|
1080
|
+
return {
|
|
1081
|
+
accessToken: tokens?.accessToken.token ?? null,
|
|
1082
|
+
refreshToken: tokens?.refreshToken?.token ?? null
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
},
|
|
1023
1086
|
async delete() {
|
|
1024
1087
|
const res = await nonCurrentServerUser.delete();
|
|
1025
1088
|
await app._refreshUser(session);
|