@every-app/sdk 0.1.1 → 0.1.3
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 +0 -1
- package/dist/core/authenticatedFetch.d.ts.map +1 -1
- package/dist/core/authenticatedFetch.js +4 -0
- package/dist/core/localDemoSessionManager.d.ts +42 -0
- package/dist/core/localDemoSessionManager.d.ts.map +1 -0
- package/dist/core/localDemoSessionManager.js +52 -0
- package/dist/core/sessionManager.d.ts +1 -0
- package/dist/core/sessionManager.d.ts.map +1 -1
- package/dist/core/sessionManager.js +41 -9
- package/dist/shared/demoModeLocalOnly.d.ts +14 -0
- package/dist/shared/demoModeLocalOnly.d.ts.map +1 -0
- package/dist/shared/demoModeLocalOnly.js +30 -0
- package/dist/shared/localOnly.d.ts +14 -0
- package/dist/shared/localOnly.d.ts.map +1 -0
- package/dist/shared/localOnly.js +30 -0
- package/dist/tanstack/EmbeddedAppProvider.js +2 -2
- package/dist/tanstack/_internal/useEveryAppSession.d.ts +4 -1
- package/dist/tanstack/_internal/useEveryAppSession.d.ts.map +1 -1
- package/dist/tanstack/_internal/useEveryAppSession.js +9 -4
- package/dist/tanstack/server/authConfig.d.ts.map +1 -1
- package/dist/tanstack/server/authConfig.js +5 -1
- package/dist/tanstack/server/authenticateRequest.d.ts.map +1 -1
- package/dist/tanstack/server/authenticateRequest.js +9 -0
- package/dist/tanstack/useSessionTokenClientMiddleware.d.ts.map +1 -1
- package/dist/tanstack/useSessionTokenClientMiddleware.js +8 -0
- package/package.json +1 -1
- package/src/core/authenticatedFetch.ts +9 -0
- package/src/core/sessionManager.ts +53 -8
- package/src/shared/demoModeLocalOnly.ts +36 -0
- package/src/tanstack/EmbeddedAppProvider.tsx +2 -2
- package/src/tanstack/_internal/useEveryAppSession.tsx +16 -9
- package/src/tanstack/server/authConfig.ts +7 -1
- package/src/tanstack/server/authenticateRequest.ts +17 -0
- package/src/tanstack/useSessionTokenClientMiddleware.ts +12 -0
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticatedFetch.d.ts","sourceRoot":"","sources":["../../src/core/authenticatedFetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"authenticatedFetch.d.ts","sourceRoot":"","sources":["../../src/core/authenticatedFetch.ts"],"names":[],"mappings":"AAaA;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC,CAmBvD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,QAAQ,CAAC,CAUnB"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { LOCAL_ONLY_TOKEN, isLocalOnlyClient, } from "../shared/demoModeLocalOnly";
|
|
1
2
|
/**
|
|
2
3
|
* Gets the current session token from the embedded session manager
|
|
3
4
|
*/
|
|
4
5
|
export async function getSessionToken() {
|
|
6
|
+
if (isLocalOnlyClient()) {
|
|
7
|
+
return LOCAL_ONLY_TOKEN;
|
|
8
|
+
}
|
|
5
9
|
const windowWithSession = window;
|
|
6
10
|
const sessionManager = windowWithSession.__embeddedSessionManager;
|
|
7
11
|
if (!sessionManager) {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface SessionManagerConfig {
|
|
2
|
+
appId: string;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* A simplified session manager for local demo mode.
|
|
6
|
+
*
|
|
7
|
+
* This manager bypasses all real authentication and returns static demo credentials.
|
|
8
|
+
* It should only be used in development when LOCAL_DEMO_ONLY_MODE is enabled.
|
|
9
|
+
*
|
|
10
|
+
* SECURITY: This class is only instantiated when isLocalDemoModeClient() returns true,
|
|
11
|
+
* which includes a production safety check.
|
|
12
|
+
*/
|
|
13
|
+
export declare class LocalDemoSessionManager {
|
|
14
|
+
readonly parentOrigin: string;
|
|
15
|
+
readonly appId: string;
|
|
16
|
+
readonly isInIframe: boolean;
|
|
17
|
+
constructor(config: SessionManagerConfig);
|
|
18
|
+
/**
|
|
19
|
+
* Returns the static demo token.
|
|
20
|
+
* No expiration logic needed since this is just for local development.
|
|
21
|
+
*/
|
|
22
|
+
getToken(): Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Always returns VALID status with the demo token.
|
|
25
|
+
*/
|
|
26
|
+
getTokenState(): {
|
|
27
|
+
status: "NO_TOKEN" | "VALID" | "EXPIRED" | "REFRESHING";
|
|
28
|
+
token: string | null;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Returns static demo user info.
|
|
32
|
+
*/
|
|
33
|
+
getUser(): {
|
|
34
|
+
userId: string;
|
|
35
|
+
email: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* No-op for demo mode - token never needs refreshing.
|
|
39
|
+
*/
|
|
40
|
+
requestNewToken(): Promise<string>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=localDemoSessionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localDemoSessionManager.d.ts","sourceRoot":"","sources":["../../src/core/localDemoSessionManager.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,qBAAa,uBAAuB;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAQ;gBAExB,MAAM,EAAE,oBAAoB;IAcxC;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IAIjC;;OAEG;IACH,aAAa,IAAI;QACf,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;QACxD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB;IAID;;OAEG;IACH,OAAO,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAO5C;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;CAGzC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { LOCAL_DEMO_TOKEN, LOCAL_DEMO_USER_ID, LOCAL_DEMO_EMAIL, } from "../shared/localOnly";
|
|
2
|
+
/**
|
|
3
|
+
* A simplified session manager for local demo mode.
|
|
4
|
+
*
|
|
5
|
+
* This manager bypasses all real authentication and returns static demo credentials.
|
|
6
|
+
* It should only be used in development when LOCAL_DEMO_ONLY_MODE is enabled.
|
|
7
|
+
*
|
|
8
|
+
* SECURITY: This class is only instantiated when isLocalDemoModeClient() returns true,
|
|
9
|
+
* which includes a production safety check.
|
|
10
|
+
*/
|
|
11
|
+
export class LocalDemoSessionManager {
|
|
12
|
+
parentOrigin;
|
|
13
|
+
appId;
|
|
14
|
+
isInIframe = true;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
if (!config.appId) {
|
|
17
|
+
throw new Error("[LocalDemoSessionManager] appId is required.");
|
|
18
|
+
}
|
|
19
|
+
this.appId = config.appId;
|
|
20
|
+
this.parentOrigin = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
21
|
+
console.warn("[LocalDemoSessionManager] Running in LOCAL DEMO MODE. " +
|
|
22
|
+
"Authentication is bypassed. Do not use in production!");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Returns the static demo token.
|
|
26
|
+
* No expiration logic needed since this is just for local development.
|
|
27
|
+
*/
|
|
28
|
+
async getToken() {
|
|
29
|
+
return LOCAL_DEMO_TOKEN;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Always returns VALID status with the demo token.
|
|
33
|
+
*/
|
|
34
|
+
getTokenState() {
|
|
35
|
+
return { status: "VALID", token: LOCAL_DEMO_TOKEN };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Returns static demo user info.
|
|
39
|
+
*/
|
|
40
|
+
getUser() {
|
|
41
|
+
return {
|
|
42
|
+
userId: LOCAL_DEMO_USER_ID,
|
|
43
|
+
email: LOCAL_DEMO_EMAIL,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* No-op for demo mode - token never needs refreshing.
|
|
48
|
+
*/
|
|
49
|
+
async requestNewToken() {
|
|
50
|
+
return LOCAL_DEMO_TOKEN;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -10,6 +10,7 @@ export declare class SessionManager {
|
|
|
10
10
|
readonly parentOrigin: string;
|
|
11
11
|
readonly appId: string;
|
|
12
12
|
readonly isInIframe: boolean;
|
|
13
|
+
readonly isDemoModeLocalOnly: boolean;
|
|
13
14
|
private token;
|
|
14
15
|
private refreshPromise;
|
|
15
16
|
constructor(config: SessionManagerConfig);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionManager.d.ts","sourceRoot":"","sources":["../../src/core/sessionManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sessionManager.d.ts","sourceRoot":"","sources":["../../src/core/sessionManager.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;CACf;AAMD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAQ3C;AAED,qBAAa,cAAc;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IAEtC,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,cAAc,CAAgC;gBAE1C,MAAM,EAAE,oBAAoB;IAoCxC,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,uBAAuB;IAuCzB,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAsDlC,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IAcjC,aAAa,IAAI;QACf,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;QACxD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;KACtB;IAgBD;;;OAGG;IACH,OAAO,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CA+BpD"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LOCAL_ONLY_EMAIL, LOCAL_ONLY_TOKEN, LOCAL_ONLY_USER_ID, isLocalOnlyClient, } from "../shared/demoModeLocalOnly";
|
|
1
2
|
const MESSAGE_TIMEOUT_MS = 5000;
|
|
2
3
|
const TOKEN_EXPIRY_BUFFER_MS = 10000;
|
|
3
4
|
const DEFAULT_TOKEN_LIFETIME_MS = 60000;
|
|
@@ -19,25 +20,37 @@ export class SessionManager {
|
|
|
19
20
|
parentOrigin;
|
|
20
21
|
appId;
|
|
21
22
|
isInIframe;
|
|
23
|
+
isDemoModeLocalOnly;
|
|
22
24
|
token = null;
|
|
23
25
|
refreshPromise = null;
|
|
24
26
|
constructor(config) {
|
|
25
27
|
if (!config.appId) {
|
|
26
28
|
throw new Error("[SessionManager] appId is required.");
|
|
27
29
|
}
|
|
30
|
+
this.isDemoModeLocalOnly = isLocalOnlyClient();
|
|
28
31
|
const gatewayUrl = import.meta.env.VITE_GATEWAY_URL;
|
|
29
|
-
if (!
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
if (!this.isDemoModeLocalOnly) {
|
|
33
|
+
if (!gatewayUrl) {
|
|
34
|
+
throw new Error("[SessionManager] VITE_GATEWAY_URL env var is required.");
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
new URL(gatewayUrl);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
throw new Error(`[SessionManager] Invalid gateway URL: ${gatewayUrl}`);
|
|
41
|
+
}
|
|
37
42
|
}
|
|
38
43
|
this.appId = config.appId;
|
|
39
|
-
this.parentOrigin =
|
|
44
|
+
this.parentOrigin = this.isDemoModeLocalOnly
|
|
45
|
+
? window.location.origin
|
|
46
|
+
: gatewayUrl;
|
|
40
47
|
this.isInIframe = isRunningInIframe();
|
|
48
|
+
if (this.isDemoModeLocalOnly) {
|
|
49
|
+
this.token = {
|
|
50
|
+
token: LOCAL_ONLY_TOKEN,
|
|
51
|
+
expiresAt: Date.now() + DEFAULT_TOKEN_LIFETIME_MS,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
41
54
|
}
|
|
42
55
|
isTokenExpiringSoon(bufferMs = TOKEN_EXPIRY_BUFFER_MS) {
|
|
43
56
|
if (!this.token)
|
|
@@ -77,6 +90,13 @@ export class SessionManager {
|
|
|
77
90
|
});
|
|
78
91
|
}
|
|
79
92
|
async requestNewToken() {
|
|
93
|
+
if (this.isDemoModeLocalOnly) {
|
|
94
|
+
this.token = {
|
|
95
|
+
token: LOCAL_ONLY_TOKEN,
|
|
96
|
+
expiresAt: Date.now() + DEFAULT_TOKEN_LIFETIME_MS,
|
|
97
|
+
};
|
|
98
|
+
return this.token.token;
|
|
99
|
+
}
|
|
80
100
|
if (this.refreshPromise) {
|
|
81
101
|
return this.refreshPromise;
|
|
82
102
|
}
|
|
@@ -112,6 +132,12 @@ export class SessionManager {
|
|
|
112
132
|
}
|
|
113
133
|
}
|
|
114
134
|
async getToken() {
|
|
135
|
+
if (this.isDemoModeLocalOnly) {
|
|
136
|
+
if (!this.token || this.isTokenExpiringSoon()) {
|
|
137
|
+
return this.requestNewToken();
|
|
138
|
+
}
|
|
139
|
+
return this.token.token;
|
|
140
|
+
}
|
|
115
141
|
if (this.isTokenExpiringSoon()) {
|
|
116
142
|
return this.requestNewToken();
|
|
117
143
|
}
|
|
@@ -134,6 +160,12 @@ export class SessionManager {
|
|
|
134
160
|
* Returns null if no valid token is available.
|
|
135
161
|
*/
|
|
136
162
|
getUser() {
|
|
163
|
+
if (this.isDemoModeLocalOnly) {
|
|
164
|
+
return {
|
|
165
|
+
userId: LOCAL_ONLY_USER_ID,
|
|
166
|
+
email: LOCAL_ONLY_EMAIL,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
137
169
|
if (!this.token) {
|
|
138
170
|
return null;
|
|
139
171
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const LOCAL_ONLY_TOKEN = "DEMO_MODE_LOCAL_ONLY";
|
|
2
|
+
export declare const LOCAL_ONLY_USER_ID = "demo-local-user";
|
|
3
|
+
export declare const LOCAL_ONLY_EMAIL = "demo-local-user@local";
|
|
4
|
+
export declare function isLocalOnlyClient(): boolean;
|
|
5
|
+
export declare function isLocalOnlyServer(): boolean;
|
|
6
|
+
export declare function createLocalOnlySessionPayload(audience: string): {
|
|
7
|
+
sub: string;
|
|
8
|
+
email: string;
|
|
9
|
+
iss: string;
|
|
10
|
+
aud: string;
|
|
11
|
+
iat: number;
|
|
12
|
+
exp: number;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=demoModeLocalOnly.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demoModeLocalOnly.d.ts","sourceRoot":"","sources":["../../src/shared/demoModeLocalOnly.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,yBAAyB,CAAC;AACvD,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AACpD,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAa3C;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,MAAM;;;;;;;EAY7D"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const LOCAL_ONLY_TOKEN = "DEMO_MODE_LOCAL_ONLY";
|
|
2
|
+
export const LOCAL_ONLY_USER_ID = "demo-local-user";
|
|
3
|
+
export const LOCAL_ONLY_EMAIL = "demo-local-user@local";
|
|
4
|
+
export function isLocalOnlyClient() {
|
|
5
|
+
return import.meta.env.VITE_LOCAL_ONLY === "true";
|
|
6
|
+
}
|
|
7
|
+
export function isLocalOnlyServer() {
|
|
8
|
+
const metaEnv = import.meta
|
|
9
|
+
.env;
|
|
10
|
+
const metaValue = metaEnv?.LOCAL_ONLY ?? metaEnv?.VITE_LOCAL_ONLY;
|
|
11
|
+
if (metaValue === "true") {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
if (typeof process !== "undefined" && process.env?.LOCAL_ONLY === "true") {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
export function createLocalOnlySessionPayload(audience) {
|
|
20
|
+
const issuedAt = Math.floor(Date.now() / 1000);
|
|
21
|
+
const expiresAt = issuedAt + 60 * 60;
|
|
22
|
+
return {
|
|
23
|
+
sub: LOCAL_ONLY_USER_ID,
|
|
24
|
+
email: LOCAL_ONLY_EMAIL,
|
|
25
|
+
iss: "local",
|
|
26
|
+
aud: audience,
|
|
27
|
+
iat: issuedAt,
|
|
28
|
+
exp: expiresAt,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const LOCAL_ONLY_TOKEN = "DEMO_MODE_LOCAL_ONLY";
|
|
2
|
+
export declare const LOCAL_ONLY_USER_ID = "demo-local-user";
|
|
3
|
+
export declare const LOCAL_ONLY_EMAIL = "demo-local-user@local";
|
|
4
|
+
export declare function isLocalOnlyClient(): boolean;
|
|
5
|
+
export declare function isLocalOnlyServer(): boolean;
|
|
6
|
+
export declare function createLocalOnlySessionPayload(audience: string): {
|
|
7
|
+
sub: string;
|
|
8
|
+
email: string;
|
|
9
|
+
iss: string;
|
|
10
|
+
aud: string;
|
|
11
|
+
iat: number;
|
|
12
|
+
exp: number;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=localOnly.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localOnly.d.ts","sourceRoot":"","sources":["../../src/shared/localOnly.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,yBAAyB,CAAC;AACvD,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AACpD,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAa3C;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,MAAM;;;;;;;EAY7D"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const LOCAL_ONLY_TOKEN = "DEMO_MODE_LOCAL_ONLY";
|
|
2
|
+
export const LOCAL_ONLY_USER_ID = "demo-local-user";
|
|
3
|
+
export const LOCAL_ONLY_EMAIL = "demo-local-user@local";
|
|
4
|
+
export function isLocalOnlyClient() {
|
|
5
|
+
return import.meta.env.VITE_LOCAL_ONLY === "true";
|
|
6
|
+
}
|
|
7
|
+
export function isLocalOnlyServer() {
|
|
8
|
+
const metaEnv = import.meta
|
|
9
|
+
.env;
|
|
10
|
+
const metaValue = metaEnv?.LOCAL_ONLY ?? metaEnv?.VITE_LOCAL_ONLY;
|
|
11
|
+
if (metaValue === "true") {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
if (typeof process !== "undefined" && process.env?.LOCAL_ONLY === "true") {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
export function createLocalOnlySessionPayload(audience) {
|
|
20
|
+
const issuedAt = Math.floor(Date.now() / 1000);
|
|
21
|
+
const expiresAt = issuedAt + 60 * 60;
|
|
22
|
+
return {
|
|
23
|
+
sub: LOCAL_ONLY_USER_ID,
|
|
24
|
+
email: LOCAL_ONLY_EMAIL,
|
|
25
|
+
iss: "local",
|
|
26
|
+
aud: audience,
|
|
27
|
+
iat: issuedAt,
|
|
28
|
+
exp: expiresAt,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -11,8 +11,8 @@ export function EmbeddedAppProvider({ children, ...config }) {
|
|
|
11
11
|
useEveryAppRouter({ sessionManager });
|
|
12
12
|
if (!sessionManager)
|
|
13
13
|
return null;
|
|
14
|
-
// Check if the app is running outside of the Gateway iframe
|
|
15
|
-
if (!sessionManager.isInIframe) {
|
|
14
|
+
// Check if the app is running outside of the Gateway iframe (skip in demo mode)
|
|
15
|
+
if (!sessionManager.isInIframe && !sessionManager.isDemoModeLocalOnly) {
|
|
16
16
|
return (_jsx(GatewayRequiredError, { gatewayOrigin: sessionManager.parentOrigin, appId: config.appId }));
|
|
17
17
|
}
|
|
18
18
|
const value = {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import { SessionManager
|
|
1
|
+
import { SessionManager } from "../../core/sessionManager";
|
|
2
|
+
interface SessionManagerConfig {
|
|
3
|
+
appId: string;
|
|
4
|
+
}
|
|
2
5
|
interface UseEveryAppSessionParams {
|
|
3
6
|
sessionManagerConfig: SessionManagerConfig;
|
|
4
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEveryAppSession.d.ts","sourceRoot":"","sources":["../../../src/tanstack/_internal/useEveryAppSession.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"useEveryAppSession.d.ts","sourceRoot":"","sources":["../../../src/tanstack/_internal/useEveryAppSession.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,UAAU,oBAAoB;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,wBAAwB;IAChC,oBAAoB,EAAE,oBAAoB,CAAC;CAC5C;AAED,wBAAgB,kBAAkB,CAAC,EACjC,oBAAoB,GACrB,EAAE,wBAAwB;;;;;;EA+C1B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from "react";
|
|
2
|
-
import { SessionManager
|
|
2
|
+
import { SessionManager } from "../../core/sessionManager";
|
|
3
3
|
export function useEveryAppSession({ sessionManagerConfig, }) {
|
|
4
4
|
const sessionManagerRef = useRef(null);
|
|
5
5
|
const [sessionTokenState, setSessionTokenState] = useState({
|
|
@@ -13,13 +13,18 @@ export function useEveryAppSession({ sessionManagerConfig, }) {
|
|
|
13
13
|
useEffect(() => {
|
|
14
14
|
if (!sessionManager)
|
|
15
15
|
return;
|
|
16
|
-
// Skip token requests when not in iframe - the app will show GatewayRequiredError instead
|
|
17
|
-
if (!sessionManager.isInIframe)
|
|
16
|
+
// Skip token requests when not in iframe (unless in demo mode) - the app will show GatewayRequiredError instead
|
|
17
|
+
if (!sessionManager.isInIframe && !sessionManager.isDemoModeLocalOnly)
|
|
18
18
|
return;
|
|
19
19
|
const interval = setInterval(() => {
|
|
20
20
|
setSessionTokenState(sessionManager.getTokenState());
|
|
21
21
|
}, 5000);
|
|
22
|
-
sessionManager
|
|
22
|
+
sessionManager
|
|
23
|
+
.getToken()
|
|
24
|
+
.then(() => {
|
|
25
|
+
setSessionTokenState(sessionManager.getTokenState());
|
|
26
|
+
})
|
|
27
|
+
.catch((err) => {
|
|
23
28
|
console.error("[EmbeddedProvider] Initial token request failed:", err);
|
|
24
29
|
});
|
|
25
30
|
return () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authConfig.d.ts","sourceRoot":"","sources":["../../../src/tanstack/server/authConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"authConfig.d.ts","sourceRoot":"","sources":["../../../src/tanstack/server/authConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAI1C,wBAAgB,aAAa,IAAI,UAAU,CAU1C"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { env } from "cloudflare:workers";
|
|
2
|
+
import { isLocalOnlyServer } from "../../shared/demoModeLocalOnly";
|
|
2
3
|
export function getAuthConfig() {
|
|
4
|
+
const demoModeLocalOnlyEnv = env.LOCAL_ONLY;
|
|
5
|
+
const isDemoModeLocalOnly = demoModeLocalOnlyEnv === "true" || isLocalOnlyServer() === true;
|
|
6
|
+
const issuer = env.GATEWAY_URL || (isDemoModeLocalOnly ? "local" : "");
|
|
3
7
|
return {
|
|
4
|
-
issuer
|
|
8
|
+
issuer,
|
|
5
9
|
audience: import.meta.env.VITE_APP_ID,
|
|
6
10
|
};
|
|
7
11
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticateRequest.d.ts","sourceRoot":"","sources":["../../../src/tanstack/server/authenticateRequest.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"authenticateRequest.d.ts","sourceRoot":"","sources":["../../../src/tanstack/server/authenticateRequest.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAQ1C;;;GAGG;AACH,UAAU,mBAAmB;IAC3B,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,GAAG,EAAE,MAAM,CAAC;IACZ,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,UAAU,EACtB,eAAe,CAAC,EAAE,OAAO,GACxB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CA2CrC;AAyCD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAK3E"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { getRequest } from "@tanstack/react-start/server";
|
|
2
2
|
import { createLocalJWKSet, jwtVerify, } from "jose";
|
|
3
3
|
import { env } from "cloudflare:workers";
|
|
4
|
+
import { LOCAL_ONLY_TOKEN, createLocalOnlySessionPayload, isLocalOnlyServer, } from "../../shared/demoModeLocalOnly";
|
|
4
5
|
export async function authenticateRequest(authConfig, providedRequest) {
|
|
5
6
|
const request = providedRequest || getRequest();
|
|
6
7
|
const authHeader = request.headers.get("authorization");
|
|
8
|
+
const demoModeLocalOnlyEnv = env.LOCAL_ONLY;
|
|
9
|
+
const isDemoModeLocalOnly = demoModeLocalOnlyEnv === "true" || isLocalOnlyServer() === true;
|
|
7
10
|
if (!authHeader) {
|
|
8
11
|
console.log("No auth header found");
|
|
9
12
|
return null;
|
|
@@ -12,6 +15,12 @@ export async function authenticateRequest(authConfig, providedRequest) {
|
|
|
12
15
|
if (!token) {
|
|
13
16
|
return null;
|
|
14
17
|
}
|
|
18
|
+
if (isDemoModeLocalOnly) {
|
|
19
|
+
if (token !== LOCAL_ONLY_TOKEN) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return createLocalOnlySessionPayload(authConfig.audience);
|
|
23
|
+
}
|
|
15
24
|
try {
|
|
16
25
|
const session = await verifySessionToken(token, authConfig);
|
|
17
26
|
return session;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSessionTokenClientMiddleware.d.ts","sourceRoot":"","sources":["../../src/tanstack/useSessionTokenClientMiddleware.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useSessionTokenClientMiddleware.d.ts","sourceRoot":"","sources":["../../src/tanstack/useSessionTokenClientMiddleware.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,+BAA+B,6GAmC1C,CAAC"}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { createMiddleware } from "@tanstack/react-start";
|
|
2
|
+
import { LOCAL_ONLY_TOKEN, isLocalOnlyClient, } from "../shared/demoModeLocalOnly";
|
|
2
3
|
export const useSessionTokenClientMiddleware = createMiddleware({
|
|
3
4
|
type: "function",
|
|
4
5
|
}).client(async ({ next }) => {
|
|
6
|
+
if (isLocalOnlyClient()) {
|
|
7
|
+
return next({
|
|
8
|
+
headers: {
|
|
9
|
+
Authorization: `Bearer ${LOCAL_ONLY_TOKEN}`,
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
}
|
|
5
13
|
// Get the global sessionManager - this MUST be available for embedded apps
|
|
6
14
|
const sessionManager = window
|
|
7
15
|
.__embeddedSessionManager;
|
package/package.json
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEMO_MODE_LOCAL_ONLY_TOKEN,
|
|
3
|
+
isDemoModeLocalOnlyClient,
|
|
4
|
+
} from "../shared/demoModeLocalOnly";
|
|
5
|
+
|
|
1
6
|
interface SessionManager {
|
|
2
7
|
getToken(): Promise<string>;
|
|
3
8
|
}
|
|
@@ -10,6 +15,10 @@ interface WindowWithSessionManager extends Window {
|
|
|
10
15
|
* Gets the current session token from the embedded session manager
|
|
11
16
|
*/
|
|
12
17
|
export async function getSessionToken(): Promise<string> {
|
|
18
|
+
if (isDemoModeLocalOnlyClient()) {
|
|
19
|
+
return DEMO_MODE_LOCAL_ONLY_TOKEN;
|
|
20
|
+
}
|
|
21
|
+
|
|
13
22
|
const windowWithSession = window as WindowWithSessionManager;
|
|
14
23
|
const sessionManager = windowWithSession.__embeddedSessionManager;
|
|
15
24
|
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEMO_MODE_LOCAL_ONLY_EMAIL,
|
|
3
|
+
DEMO_MODE_LOCAL_ONLY_TOKEN,
|
|
4
|
+
DEMO_MODE_LOCAL_ONLY_USER_ID,
|
|
5
|
+
isDemoModeLocalOnlyClient,
|
|
6
|
+
} from "../shared/demoModeLocalOnly";
|
|
7
|
+
|
|
1
8
|
interface SessionToken {
|
|
2
9
|
token: string;
|
|
3
10
|
expiresAt: number;
|
|
@@ -35,6 +42,7 @@ export class SessionManager {
|
|
|
35
42
|
readonly parentOrigin: string;
|
|
36
43
|
readonly appId: string;
|
|
37
44
|
readonly isInIframe: boolean;
|
|
45
|
+
readonly isDemoModeLocalOnly: boolean;
|
|
38
46
|
|
|
39
47
|
private token: SessionToken | null = null;
|
|
40
48
|
private refreshPromise: Promise<string> | null = null;
|
|
@@ -44,20 +52,35 @@ export class SessionManager {
|
|
|
44
52
|
throw new Error("[SessionManager] appId is required.");
|
|
45
53
|
}
|
|
46
54
|
|
|
55
|
+
this.isDemoModeLocalOnly = isDemoModeLocalOnlyClient();
|
|
56
|
+
|
|
47
57
|
const gatewayUrl = import.meta.env.VITE_GATEWAY_URL;
|
|
48
|
-
if (!
|
|
49
|
-
|
|
50
|
-
|
|
58
|
+
if (!this.isDemoModeLocalOnly) {
|
|
59
|
+
if (!gatewayUrl) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
"[SessionManager] VITE_GATEWAY_URL env var is required.",
|
|
62
|
+
);
|
|
63
|
+
}
|
|
51
64
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
65
|
+
try {
|
|
66
|
+
new URL(gatewayUrl);
|
|
67
|
+
} catch {
|
|
68
|
+
throw new Error(`[SessionManager] Invalid gateway URL: ${gatewayUrl}`);
|
|
69
|
+
}
|
|
56
70
|
}
|
|
57
71
|
|
|
58
72
|
this.appId = config.appId;
|
|
59
|
-
this.parentOrigin =
|
|
73
|
+
this.parentOrigin = this.isDemoModeLocalOnly
|
|
74
|
+
? window.location.origin
|
|
75
|
+
: gatewayUrl;
|
|
60
76
|
this.isInIframe = isRunningInIframe();
|
|
77
|
+
|
|
78
|
+
if (this.isDemoModeLocalOnly) {
|
|
79
|
+
this.token = {
|
|
80
|
+
token: DEMO_MODE_LOCAL_ONLY_TOKEN,
|
|
81
|
+
expiresAt: Date.now() + DEFAULT_TOKEN_LIFETIME_MS,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
61
84
|
}
|
|
62
85
|
|
|
63
86
|
private isTokenExpiringSoon(
|
|
@@ -107,6 +130,14 @@ export class SessionManager {
|
|
|
107
130
|
}
|
|
108
131
|
|
|
109
132
|
async requestNewToken(): Promise<string> {
|
|
133
|
+
if (this.isDemoModeLocalOnly) {
|
|
134
|
+
this.token = {
|
|
135
|
+
token: DEMO_MODE_LOCAL_ONLY_TOKEN,
|
|
136
|
+
expiresAt: Date.now() + DEFAULT_TOKEN_LIFETIME_MS,
|
|
137
|
+
};
|
|
138
|
+
return this.token.token;
|
|
139
|
+
}
|
|
140
|
+
|
|
110
141
|
if (this.refreshPromise) {
|
|
111
142
|
return this.refreshPromise;
|
|
112
143
|
}
|
|
@@ -153,6 +184,13 @@ export class SessionManager {
|
|
|
153
184
|
}
|
|
154
185
|
|
|
155
186
|
async getToken(): Promise<string> {
|
|
187
|
+
if (this.isDemoModeLocalOnly) {
|
|
188
|
+
if (!this.token || this.isTokenExpiringSoon()) {
|
|
189
|
+
return this.requestNewToken();
|
|
190
|
+
}
|
|
191
|
+
return this.token.token;
|
|
192
|
+
}
|
|
193
|
+
|
|
156
194
|
if (this.isTokenExpiringSoon()) {
|
|
157
195
|
return this.requestNewToken();
|
|
158
196
|
}
|
|
@@ -183,6 +221,13 @@ export class SessionManager {
|
|
|
183
221
|
* Returns null if no valid token is available.
|
|
184
222
|
*/
|
|
185
223
|
getUser(): { userId: string; email: string } | null {
|
|
224
|
+
if (this.isDemoModeLocalOnly) {
|
|
225
|
+
return {
|
|
226
|
+
userId: DEMO_MODE_LOCAL_ONLY_USER_ID,
|
|
227
|
+
email: DEMO_MODE_LOCAL_ONLY_EMAIL,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
186
231
|
if (!this.token) {
|
|
187
232
|
return null;
|
|
188
233
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const DEMO_MODE_LOCAL_ONLY_TOKEN = "DEMO_MODE_LOCAL_ONLY";
|
|
2
|
+
export const DEMO_MODE_LOCAL_ONLY_USER_ID = "demo-local-user";
|
|
3
|
+
export const DEMO_MODE_LOCAL_ONLY_EMAIL = "demo-local-user@local";
|
|
4
|
+
|
|
5
|
+
export function isDemoModeLocalOnlyClient(): boolean {
|
|
6
|
+
return import.meta.env.VITE_LOCAL_ONLY === "true";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function isDemoModeLocalOnlyServer(): boolean {
|
|
10
|
+
const metaEnv = (import.meta as { env?: Record<string, string | undefined> })
|
|
11
|
+
.env;
|
|
12
|
+
const metaValue = metaEnv?.LOCAL_ONLY ?? metaEnv?.VITE_LOCAL_ONLY;
|
|
13
|
+
if (metaValue === "true") {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (typeof process !== "undefined" && process.env?.LOCAL_ONLY === "true") {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function createDemoModeLocalOnlySessionPayload(audience: string) {
|
|
25
|
+
const issuedAt = Math.floor(Date.now() / 1000);
|
|
26
|
+
const expiresAt = issuedAt + 60 * 60;
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
sub: DEMO_MODE_LOCAL_ONLY_USER_ID,
|
|
30
|
+
email: DEMO_MODE_LOCAL_ONLY_EMAIL,
|
|
31
|
+
iss: "local",
|
|
32
|
+
aud: audience,
|
|
33
|
+
iat: issuedAt,
|
|
34
|
+
exp: expiresAt,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -27,8 +27,8 @@ export function EmbeddedAppProvider({
|
|
|
27
27
|
|
|
28
28
|
if (!sessionManager) return null;
|
|
29
29
|
|
|
30
|
-
// Check if the app is running outside of the Gateway iframe
|
|
31
|
-
if (!sessionManager.isInIframe) {
|
|
30
|
+
// Check if the app is running outside of the Gateway iframe (skip in demo mode)
|
|
31
|
+
if (!sessionManager.isInIframe && !sessionManager.isDemoModeLocalOnly) {
|
|
32
32
|
return (
|
|
33
33
|
<GatewayRequiredError
|
|
34
34
|
gatewayOrigin={sessionManager.parentOrigin}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from "react";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { SessionManager } from "../../core/sessionManager";
|
|
3
|
+
|
|
4
|
+
interface SessionManagerConfig {
|
|
5
|
+
appId: string;
|
|
6
|
+
}
|
|
6
7
|
|
|
7
8
|
interface UseEveryAppSessionParams {
|
|
8
9
|
sessionManagerConfig: SessionManagerConfig;
|
|
@@ -27,16 +28,22 @@ export function useEveryAppSession({
|
|
|
27
28
|
|
|
28
29
|
useEffect(() => {
|
|
29
30
|
if (!sessionManager) return;
|
|
30
|
-
// Skip token requests when not in iframe - the app will show GatewayRequiredError instead
|
|
31
|
-
if (!sessionManager.isInIframe)
|
|
31
|
+
// Skip token requests when not in iframe (unless in demo mode) - the app will show GatewayRequiredError instead
|
|
32
|
+
if (!sessionManager.isInIframe && !sessionManager.isDemoModeLocalOnly)
|
|
33
|
+
return;
|
|
32
34
|
|
|
33
35
|
const interval = setInterval(() => {
|
|
34
36
|
setSessionTokenState(sessionManager.getTokenState());
|
|
35
37
|
}, 5000);
|
|
36
38
|
|
|
37
|
-
sessionManager
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
sessionManager
|
|
40
|
+
.getToken()
|
|
41
|
+
.then(() => {
|
|
42
|
+
setSessionTokenState(sessionManager.getTokenState());
|
|
43
|
+
})
|
|
44
|
+
.catch((err) => {
|
|
45
|
+
console.error("[EmbeddedProvider] Initial token request failed:", err);
|
|
46
|
+
});
|
|
40
47
|
|
|
41
48
|
return () => {
|
|
42
49
|
clearInterval(interval);
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { AuthConfig } from "./types";
|
|
2
2
|
import { env } from "cloudflare:workers";
|
|
3
|
+
import { isDemoModeLocalOnlyServer } from "../../shared/demoModeLocalOnly";
|
|
3
4
|
|
|
4
5
|
export function getAuthConfig(): AuthConfig {
|
|
6
|
+
const demoModeLocalOnlyEnv = (env as { LOCAL_ONLY?: string }).LOCAL_ONLY;
|
|
7
|
+
const isDemoModeLocalOnly =
|
|
8
|
+
demoModeLocalOnlyEnv === "true" || isDemoModeLocalOnlyServer() === true;
|
|
9
|
+
const issuer = env.GATEWAY_URL || (isDemoModeLocalOnly ? "local" : "");
|
|
10
|
+
|
|
5
11
|
return {
|
|
6
|
-
issuer
|
|
12
|
+
issuer,
|
|
7
13
|
audience: import.meta.env.VITE_APP_ID,
|
|
8
14
|
};
|
|
9
15
|
}
|
|
@@ -8,6 +8,11 @@ import {
|
|
|
8
8
|
|
|
9
9
|
import type { AuthConfig } from "./types";
|
|
10
10
|
import { env } from "cloudflare:workers";
|
|
11
|
+
import {
|
|
12
|
+
DEMO_MODE_LOCAL_ONLY_TOKEN,
|
|
13
|
+
createDemoModeLocalOnlySessionPayload,
|
|
14
|
+
isDemoModeLocalOnlyServer,
|
|
15
|
+
} from "../../shared/demoModeLocalOnly";
|
|
11
16
|
|
|
12
17
|
/**
|
|
13
18
|
* JWT payload structure for embedded app session tokens.
|
|
@@ -35,6 +40,10 @@ export async function authenticateRequest(
|
|
|
35
40
|
const request = providedRequest || getRequest();
|
|
36
41
|
const authHeader = request.headers.get("authorization");
|
|
37
42
|
|
|
43
|
+
const demoModeLocalOnlyEnv = (env as { LOCAL_ONLY?: string }).LOCAL_ONLY;
|
|
44
|
+
const isDemoModeLocalOnly =
|
|
45
|
+
demoModeLocalOnlyEnv === "true" || isDemoModeLocalOnlyServer() === true;
|
|
46
|
+
|
|
38
47
|
if (!authHeader) {
|
|
39
48
|
console.log("No auth header found");
|
|
40
49
|
return null;
|
|
@@ -46,6 +55,14 @@ export async function authenticateRequest(
|
|
|
46
55
|
return null;
|
|
47
56
|
}
|
|
48
57
|
|
|
58
|
+
if (isDemoModeLocalOnly) {
|
|
59
|
+
if (token !== DEMO_MODE_LOCAL_ONLY_TOKEN) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return createDemoModeLocalOnlySessionPayload(authConfig.audience);
|
|
64
|
+
}
|
|
65
|
+
|
|
49
66
|
try {
|
|
50
67
|
const session = await verifySessionToken(token, authConfig);
|
|
51
68
|
return session;
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { createMiddleware } from "@tanstack/react-start";
|
|
2
2
|
import type { SessionManager } from "../core/sessionManager";
|
|
3
|
+
import {
|
|
4
|
+
DEMO_MODE_LOCAL_ONLY_TOKEN,
|
|
5
|
+
isDemoModeLocalOnlyClient,
|
|
6
|
+
} from "../shared/demoModeLocalOnly";
|
|
3
7
|
|
|
4
8
|
export const useSessionTokenClientMiddleware = createMiddleware({
|
|
5
9
|
type: "function",
|
|
6
10
|
}).client(async ({ next }) => {
|
|
11
|
+
if (isDemoModeLocalOnlyClient()) {
|
|
12
|
+
return next({
|
|
13
|
+
headers: {
|
|
14
|
+
Authorization: `Bearer ${DEMO_MODE_LOCAL_ONLY_TOKEN}`,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
7
19
|
// Get the global sessionManager - this MUST be available for embedded apps
|
|
8
20
|
const sessionManager = (window as any)
|
|
9
21
|
.__embeddedSessionManager as SessionManager;
|