@burdenoff/microfe-auth 2026.626.1 → 2026.627.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.
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import { useEffect as e, useRef as t } from "react";
|
|
2
2
|
import { jsx as n } from "react/jsx-runtime";
|
|
3
3
|
//#region src/auth/pages/SessionBridgePage.tsx
|
|
4
|
-
var r = "burdenoff-auth-bridge", i = "
|
|
4
|
+
var r = "burdenoff-auth-bridge", i = "burdenoff-auth-client", a = "bf-p", o = "bf-profiles", s = "bf-active-profile";
|
|
5
5
|
function c(e) {
|
|
6
|
+
return e !== null && typeof e.postMessage == "function";
|
|
7
|
+
}
|
|
8
|
+
function l(e) {
|
|
9
|
+
return typeof e == "object" && !!e && typeof e.type == "string";
|
|
10
|
+
}
|
|
11
|
+
var u = new Set(/* @__PURE__ */ "burdenoff.com,vibecontrols.com,fluidgrids.com,botlit.ai,bigconsole.com,gethealthybowl.com,headshotmarketing.com,timecampus.com,ggnomad.com,movethewheels.com,crewfoundry.com,planmagnet.com,eventfullymanaged.com,kadaikodi.com,assethandler.com,technospam.com,semanticfed.com,manufacturedops.com,theglobalfuel.com,housingvista.com,proserviceworld.com,mybodyshield.com,artistrybase.com,collabkin.com,brainyrich.com,theculturepost.com,comradecircle.com,cosmicintersection.com,govcitizenhub.com,intelwatchtower.com,ecoimpacthub.com,buildmyiq.com,fluidgrids.ai,atheletebridge.com,adaptercloud.com,coolandlovely.com,subscriberbot.com,labsofscience.com,hookmovies.com".split(","));
|
|
12
|
+
function d(e) {
|
|
6
13
|
try {
|
|
7
14
|
let t = new URL(e);
|
|
8
15
|
if (t.hostname === "localhost" || t.hostname === "127.0.0.1" || t.hostname.endsWith(".local.burdenoff.com")) return !0;
|
|
9
|
-
for (let e of
|
|
16
|
+
for (let e of u) if (t.hostname === e || t.hostname === `app.${e}` || t.hostname === `alphaapp.${e}` || t.hostname === `admin.${e}` || t.hostname === `alphaadmin.${e}` || t.hostname === `www.${e}`) return !0;
|
|
10
17
|
return !1;
|
|
11
18
|
} catch {
|
|
12
19
|
return !1;
|
|
13
20
|
}
|
|
14
21
|
}
|
|
15
|
-
function
|
|
22
|
+
function f() {
|
|
16
23
|
try {
|
|
17
|
-
let e = localStorage.getItem(
|
|
24
|
+
let e = localStorage.getItem(o), t = sessionStorage.getItem(s);
|
|
18
25
|
if (!t && e) try {
|
|
19
26
|
let n = JSON.parse(e);
|
|
20
|
-
n.length > 0 && (t = n[0].id, sessionStorage.setItem(
|
|
27
|
+
n.length > 0 && (t = n[0].id, sessionStorage.setItem(s, t));
|
|
21
28
|
} catch {}
|
|
22
29
|
if (!t) return {
|
|
23
30
|
user: null,
|
|
@@ -25,12 +32,12 @@ function l() {
|
|
|
25
32
|
profiles: e ? JSON.parse(e) : [],
|
|
26
33
|
activeProfileId: null
|
|
27
34
|
};
|
|
28
|
-
let n = localStorage.getItem(`${
|
|
35
|
+
let n = localStorage.getItem(`${a}-${t}-user`), r = localStorage.getItem(`${a}-${t}-tokens`), i = localStorage.getItem(`${a}-${t}-workspace-token`);
|
|
29
36
|
return {
|
|
30
37
|
user: n ? JSON.parse(n) : null,
|
|
31
38
|
tokens: r ? {
|
|
32
39
|
...JSON.parse(r),
|
|
33
|
-
workspaceToken:
|
|
40
|
+
workspaceToken: i ?? void 0
|
|
34
41
|
} : null,
|
|
35
42
|
profiles: e ? JSON.parse(e) : [],
|
|
36
43
|
activeProfileId: t
|
|
@@ -44,180 +51,186 @@ function l() {
|
|
|
44
51
|
};
|
|
45
52
|
}
|
|
46
53
|
}
|
|
47
|
-
function
|
|
48
|
-
let t = e.activeProfileId ?? e.user?.id ?? sessionStorage.getItem(
|
|
54
|
+
function p(e) {
|
|
55
|
+
let t = e.activeProfileId ?? e.user?.id ?? sessionStorage.getItem(s);
|
|
49
56
|
if (t) {
|
|
50
|
-
if (e.user && localStorage.setItem(`${
|
|
57
|
+
if (e.user && localStorage.setItem(`${a}-${t}-user`, JSON.stringify(e.user)), e.tokens && typeof e.tokens == "object") {
|
|
51
58
|
let { workspaceToken: n, ...r } = e.tokens;
|
|
52
|
-
localStorage.setItem(`${
|
|
59
|
+
localStorage.setItem(`${a}-${t}-tokens`, JSON.stringify(r)), n && localStorage.setItem(`${a}-${t}-workspace-token`, String(n));
|
|
53
60
|
}
|
|
54
|
-
e.profiles && localStorage.setItem(
|
|
61
|
+
e.profiles && localStorage.setItem(o, JSON.stringify(e.profiles)), sessionStorage.setItem(s, t);
|
|
55
62
|
}
|
|
56
63
|
}
|
|
57
|
-
function
|
|
58
|
-
let e = sessionStorage.getItem(
|
|
64
|
+
function m() {
|
|
65
|
+
let e = sessionStorage.getItem(s);
|
|
59
66
|
if (e) {
|
|
60
|
-
localStorage.removeItem(`${
|
|
67
|
+
localStorage.removeItem(`${a}-${e}-user`), localStorage.removeItem(`${a}-${e}-tokens`), localStorage.removeItem(`${a}-${e}-workspace-token`), localStorage.removeItem(`${a}-${e}-auth-storage`);
|
|
61
68
|
try {
|
|
62
|
-
let t = localStorage.getItem(
|
|
63
|
-
localStorage.setItem(
|
|
69
|
+
let t = localStorage.getItem(o), n = t ? JSON.parse(t) : [];
|
|
70
|
+
localStorage.setItem(o, JSON.stringify(n.filter((t) => t.id !== e)));
|
|
64
71
|
} catch {}
|
|
65
|
-
sessionStorage.removeItem(
|
|
72
|
+
sessionStorage.removeItem(s);
|
|
66
73
|
}
|
|
67
74
|
localStorage.removeItem("auth-storage");
|
|
68
75
|
}
|
|
69
|
-
function
|
|
76
|
+
function h() {
|
|
70
77
|
try {
|
|
71
|
-
let e = localStorage.getItem(
|
|
72
|
-
for (let e of t) localStorage.removeItem(`${
|
|
78
|
+
let e = localStorage.getItem(o), t = e ? JSON.parse(e) : [];
|
|
79
|
+
for (let e of t) localStorage.removeItem(`${a}-${e.id}-user`), localStorage.removeItem(`${a}-${e.id}-tokens`), localStorage.removeItem(`${a}-${e.id}-workspace-token`), localStorage.removeItem(`${a}-${e.id}-auth-storage`), localStorage.removeItem(`${a}-${e.id}-context`);
|
|
73
80
|
} catch {}
|
|
74
|
-
for (let e of Object.keys(localStorage)) e.startsWith(`${
|
|
75
|
-
localStorage.removeItem(
|
|
81
|
+
for (let e of Object.keys(localStorage)) e.startsWith(`${a}-`) && e.endsWith("-auth-storage") && localStorage.removeItem(e);
|
|
82
|
+
localStorage.removeItem(o), localStorage.removeItem("auth-storage"), sessionStorage.removeItem(s);
|
|
76
83
|
}
|
|
77
|
-
var
|
|
78
|
-
function
|
|
84
|
+
var g = "bf-sso-profile", _ = "bf-sso";
|
|
85
|
+
function v(e, t) {
|
|
79
86
|
try {
|
|
80
87
|
let n = window.location.hostname.endsWith(".local.burdenoff.com") ? ".local.burdenoff.com" : void 0, r = n ? `; domain=${n}` : "", i = window.location.protocol === "https:" ? "; secure" : "", a = JSON.stringify({
|
|
81
88
|
id: e,
|
|
82
89
|
origin: t
|
|
83
90
|
});
|
|
84
|
-
document.cookie = `${
|
|
91
|
+
document.cookie = `${g}=${encodeURIComponent(a)}${r}; path=/; samesite=lax${i}; max-age=86400`;
|
|
85
92
|
} catch {}
|
|
86
93
|
}
|
|
87
|
-
function
|
|
94
|
+
function y(e, t) {
|
|
88
95
|
try {
|
|
89
96
|
let n = window.location.hostname.endsWith(".local.burdenoff.com") ? ".local.burdenoff.com" : void 0, r = n ? `; domain=${n}` : "", i = window.location.protocol === "https:" ? "; secure" : "", a = JSON.stringify({
|
|
90
97
|
id: e,
|
|
91
98
|
origin: t
|
|
92
99
|
});
|
|
93
|
-
document.cookie = `${
|
|
100
|
+
document.cookie = `${_}=${encodeURIComponent(a)}${r}; path=/; samesite=lax${i}; max-age=86400`;
|
|
94
101
|
} catch {}
|
|
95
102
|
}
|
|
96
|
-
function
|
|
103
|
+
function b() {
|
|
97
104
|
try {
|
|
98
105
|
let e = window.location.hostname, t = e.endsWith(".local.burdenoff.com") ? ".local.burdenoff.com" : void 0;
|
|
99
|
-
document.cookie = `${
|
|
106
|
+
document.cookie = `${g}=; path=/; max-age=0`, document.cookie = `${_}=; path=/; max-age=0`, t && (document.cookie = `${g}=; path=/; domain=${t}; max-age=0`, document.cookie = `${_}=; path=/; domain=${t}; max-age=0`), e && !["localhost", "127.0.0.1"].includes(e) && (document.cookie = `${g}=; path=/; domain=${e}; max-age=0`, document.cookie = `${_}=; path=/; domain=${e}; max-age=0`);
|
|
100
107
|
} catch {}
|
|
101
108
|
}
|
|
102
|
-
function
|
|
103
|
-
let
|
|
109
|
+
function x() {
|
|
110
|
+
let s = t(/* @__PURE__ */ new Map()), u = t(/* @__PURE__ */ new Map()), g = t(!1);
|
|
104
111
|
return e(() => {
|
|
105
112
|
async function e() {
|
|
106
113
|
try {
|
|
107
114
|
if (!document.requestStorageAccess) {
|
|
108
|
-
|
|
115
|
+
g.current = !0;
|
|
109
116
|
return;
|
|
110
117
|
}
|
|
111
118
|
if (await document.hasStorageAccess()) {
|
|
112
|
-
|
|
119
|
+
g.current = !0;
|
|
113
120
|
return;
|
|
114
121
|
}
|
|
115
|
-
await document.requestStorageAccess(),
|
|
122
|
+
await document.requestStorageAccess(), g.current = !0;
|
|
116
123
|
} catch {
|
|
117
|
-
|
|
124
|
+
g.current = !1;
|
|
118
125
|
}
|
|
119
126
|
}
|
|
120
127
|
e();
|
|
121
128
|
}, []), e(() => {
|
|
122
129
|
function e(e) {
|
|
123
|
-
return
|
|
130
|
+
return d(e);
|
|
124
131
|
}
|
|
125
132
|
function t(e, t) {
|
|
126
|
-
|
|
127
|
-
|
|
133
|
+
s.current.forEach((n, i) => {
|
|
134
|
+
i !== t && n.source.postMessage({
|
|
135
|
+
...e,
|
|
136
|
+
source: r,
|
|
137
|
+
nonce: n.nonce
|
|
138
|
+
}, n.origin);
|
|
128
139
|
});
|
|
129
140
|
}
|
|
130
141
|
function n(n) {
|
|
131
|
-
if (!e(n.origin)) return;
|
|
132
|
-
let
|
|
133
|
-
if (!
|
|
142
|
+
if (!e(n.origin) || !l(n.data) || n.data.source !== i) return;
|
|
143
|
+
let a = n.data, o = c(n.source) ? n.source : null;
|
|
144
|
+
if (!o) return;
|
|
145
|
+
let d = typeof a.nonce == "string" && a.nonce.length > 0 ? a.nonce : null, g = s.current.get(o);
|
|
146
|
+
if (a.type !== "AUTH_INIT") {
|
|
147
|
+
if (!d || g?.nonce !== d) return;
|
|
148
|
+
} else if (!d) return;
|
|
149
|
+
switch (a.type) {
|
|
134
150
|
case "AUTH_INIT": {
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
151
|
+
if (s.current.set(o, {
|
|
152
|
+
source: o,
|
|
153
|
+
origin: n.origin,
|
|
154
|
+
nonce: d
|
|
155
|
+
}), a.payload && typeof a.payload == "object") {
|
|
156
|
+
let e = a.payload;
|
|
157
|
+
e.user && e.tokens && p(e);
|
|
138
158
|
}
|
|
139
|
-
let e =
|
|
140
|
-
|
|
159
|
+
let e = f(), t = s.current.get(o);
|
|
160
|
+
t && (t.source.postMessage({
|
|
141
161
|
type: "AUTH_STATE",
|
|
142
162
|
payload: e,
|
|
143
|
-
source: r
|
|
144
|
-
|
|
163
|
+
source: r,
|
|
164
|
+
nonce: t.nonce
|
|
165
|
+
}, n.origin), u.current.get(o) !== t.nonce && (u.current.set(o, t.nonce), t.source.postMessage({
|
|
145
166
|
type: "AUTH_BRIDGE_READY",
|
|
146
|
-
source: r
|
|
167
|
+
source: r,
|
|
168
|
+
nonce: t.nonce
|
|
147
169
|
}, n.origin)));
|
|
148
170
|
break;
|
|
149
171
|
}
|
|
150
172
|
case "AUTH_LOGIN":
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
let e =
|
|
154
|
-
|
|
173
|
+
if (a.payload) {
|
|
174
|
+
p(a.payload);
|
|
175
|
+
let e = a.payload, r = e.activeProfileId ?? e.user?.id;
|
|
176
|
+
r && (b(), v(r, n.origin), y(r, n.origin)), t({
|
|
155
177
|
type: "AUTH_STATE_CHANGED",
|
|
156
178
|
payload: {
|
|
157
|
-
...
|
|
179
|
+
...f(),
|
|
158
180
|
trigger: "login"
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
}, n.source);
|
|
181
|
+
}
|
|
182
|
+
}, o);
|
|
162
183
|
}
|
|
163
184
|
break;
|
|
164
185
|
case "AUTH_LOGOUT":
|
|
165
|
-
|
|
186
|
+
m(), b(), t({
|
|
166
187
|
type: "AUTH_STATE_CHANGED",
|
|
167
188
|
payload: {
|
|
168
|
-
...
|
|
189
|
+
...f(),
|
|
169
190
|
trigger: "logout"
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
}, n.source);
|
|
191
|
+
}
|
|
192
|
+
}, o);
|
|
173
193
|
break;
|
|
174
194
|
case "AUTH_LOGOUT_ALL":
|
|
175
|
-
|
|
195
|
+
h(), b(), t({
|
|
176
196
|
type: "AUTH_STATE_CHANGED",
|
|
177
197
|
payload: {
|
|
178
|
-
...
|
|
198
|
+
...f(),
|
|
179
199
|
trigger: "logout_all"
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
}, n.source);
|
|
200
|
+
}
|
|
201
|
+
}, o);
|
|
183
202
|
break;
|
|
184
203
|
case "AUTH_TOKEN_REFRESH":
|
|
185
|
-
|
|
204
|
+
a.payload?.tokens && (p({ tokens: a.payload.tokens }), t({
|
|
186
205
|
type: "AUTH_STATE_CHANGED",
|
|
187
206
|
payload: {
|
|
188
|
-
...
|
|
207
|
+
...f(),
|
|
189
208
|
trigger: "refresh"
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
}, n.source));
|
|
209
|
+
}
|
|
210
|
+
}, o));
|
|
193
211
|
break;
|
|
194
212
|
case "AUTH_ACCOUNT_SWITCH":
|
|
195
|
-
|
|
213
|
+
a.payload && (p(a.payload), t({
|
|
196
214
|
type: "AUTH_STATE_CHANGED",
|
|
197
215
|
payload: {
|
|
198
|
-
...
|
|
216
|
+
...f(),
|
|
199
217
|
trigger: "account_switch"
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
}, n.source));
|
|
218
|
+
}
|
|
219
|
+
}, o));
|
|
203
220
|
break;
|
|
204
221
|
}
|
|
205
222
|
}
|
|
206
|
-
function
|
|
207
|
-
(e.key?.startsWith(
|
|
223
|
+
function g(e) {
|
|
224
|
+
(e.key?.startsWith(a) || e.key === o) && t({
|
|
208
225
|
type: "AUTH_STATE_CHANGED",
|
|
209
226
|
payload: {
|
|
210
|
-
...
|
|
227
|
+
...f(),
|
|
211
228
|
trigger: "storage_sync"
|
|
212
|
-
}
|
|
213
|
-
source: r
|
|
229
|
+
}
|
|
214
230
|
});
|
|
215
231
|
}
|
|
216
|
-
return window.addEventListener("message", n), window.addEventListener("storage",
|
|
217
|
-
|
|
218
|
-
source: r
|
|
219
|
-
}, "*")), () => {
|
|
220
|
-
window.removeEventListener("message", n), window.removeEventListener("storage", m);
|
|
232
|
+
return window.addEventListener("message", n), window.addEventListener("storage", g), () => {
|
|
233
|
+
window.removeEventListener("message", n), window.removeEventListener("storage", g);
|
|
221
234
|
};
|
|
222
235
|
}, []), /* @__PURE__ */ n("div", {
|
|
223
236
|
id: "auth-session-bridge-root",
|
|
@@ -226,6 +239,6 @@ function v() {
|
|
|
226
239
|
});
|
|
227
240
|
}
|
|
228
241
|
//#endregion
|
|
229
|
-
export {
|
|
242
|
+
export { x as SessionBridgePage };
|
|
230
243
|
|
|
231
244
|
//# sourceMappingURL=SessionBridgePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionBridgePage.js","names":[],"sources":["../../../src/auth/pages/SessionBridgePage.tsx"],"sourcesContent":["/**\n * SessionBridgePage — Cross-Domain Auth Session Bridge (Profile-Scoped)\n *\n * Embedded as hidden iframe by other app shells. Manages profile-scoped\n * auth tokens in localStorage and relays state via postMessage.\n *\n * Storage uses ProfileStorageManager keys:\n * bf-profiles, bf-p-{id}-user, bf-p-{id}-tokens, bf-p-{id}-workspace-token\n * bf-active-profile (sessionStorage, per-tab)\n *\n * URL: /auth/session-bridge\n */\n\nimport { useEffect, useRef } from \"react\";\n\nconst BRIDGE_SOURCE = \"burdenoff-auth-bridge\";\nconst BF_PREFIX = \"bf-p\";\nconst BF_PROFILES = \"bf-profiles\";\nconst BF_ACTIVE = \"bf-active-profile\";\n\ninterface BridgeMessage {\n type: string;\n payload?: Record<string, unknown>;\n source?: string;\n}\n\n/**\n * Dynamically validates allowed origins for the auth bridge.\n * Accepts all Burdenoff product domains (prod + alpha + local dev).\n */\nconst ALLOWED_PRODUCT_DOMAINS = new Set([\n \"burdenoff.com\",\n \"vibecontrols.com\",\n \"fluidgrids.com\",\n \"botlit.ai\",\n \"bigconsole.com\",\n \"gethealthybowl.com\",\n \"headshotmarketing.com\",\n \"timecampus.com\",\n \"ggnomad.com\",\n \"movethewheels.com\",\n \"crewfoundry.com\",\n \"planmagnet.com\",\n \"eventfullymanaged.com\",\n \"kadaikodi.com\",\n \"assethandler.com\",\n \"technospam.com\",\n \"semanticfed.com\",\n \"manufacturedops.com\",\n \"theglobalfuel.com\",\n \"housingvista.com\",\n \"proserviceworld.com\",\n \"mybodyshield.com\",\n \"artistrybase.com\",\n \"collabkin.com\",\n \"brainyrich.com\",\n \"theculturepost.com\",\n \"comradecircle.com\",\n \"cosmicintersection.com\",\n \"govcitizenhub.com\",\n \"intelwatchtower.com\",\n \"ecoimpacthub.com\",\n \"buildmyiq.com\",\n \"fluidgrids.ai\",\n \"atheletebridge.com\",\n \"adaptercloud.com\",\n \"coolandlovely.com\",\n \"subscriberbot.com\",\n \"labsofscience.com\",\n \"hookmovies.com\",\n]);\n\nfunction isAllowedOrigin(origin: string): boolean {\n try {\n const url = new URL(origin);\n // Allow all localhost ports (local dev)\n if (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\") {\n return true;\n }\n // Allow *.local.burdenoff.com (local dev with nginx)\n if (url.hostname.endsWith(\".local.burdenoff.com\")) {\n return true;\n }\n // Allow app.{domain} and alphaapp.{domain} for all known product domains\n for (const domain of ALLOWED_PRODUCT_DOMAINS) {\n if (\n url.hostname === domain ||\n url.hostname === `app.${domain}` ||\n url.hostname === `alphaapp.${domain}` ||\n // Admin app shells (admin.burdenoff.com / alphaadmin.burdenoff.com)\n // embed this bridge iframe too. Without trusting their origin, the\n // bridge ignores their postMessages and the admin shell never receives\n // the shared session.\n url.hostname === `admin.${domain}` ||\n url.hostname === `alphaadmin.${domain}` ||\n url.hostname === `www.${domain}`\n ) {\n return true;\n }\n }\n return false;\n } catch {\n return false;\n }\n}\n\nfunction readAuthState(): Record<string, unknown> {\n try {\n const profiles = localStorage.getItem(BF_PROFILES);\n let activeId = sessionStorage.getItem(BF_ACTIVE);\n\n // Fall back: if sessionStorage is empty but localStorage has profiles,\n // pick the first profile (same logic as resolveActiveProfileId)\n if (!activeId && profiles) {\n try {\n const profileList = JSON.parse(profiles) as Array<{ id: string }>;\n if (profileList.length > 0) {\n activeId = profileList[0].id;\n sessionStorage.setItem(BF_ACTIVE, activeId);\n }\n } catch {\n // ignore\n }\n }\n\n if (!activeId) {\n return {\n user: null,\n tokens: null,\n profiles: profiles ? JSON.parse(profiles) : [],\n activeProfileId: null,\n };\n }\n const user = localStorage.getItem(`${BF_PREFIX}-${activeId}-user`);\n const tokens = localStorage.getItem(`${BF_PREFIX}-${activeId}-tokens`);\n const wsToken = localStorage.getItem(\n `${BF_PREFIX}-${activeId}-workspace-token`,\n );\n\n return {\n user: user ? JSON.parse(user) : null,\n tokens: tokens\n ? { ...JSON.parse(tokens), workspaceToken: wsToken ?? undefined }\n : null,\n profiles: profiles ? JSON.parse(profiles) : [],\n activeProfileId: activeId,\n };\n } catch {\n return { user: null, tokens: null, profiles: [], activeProfileId: null };\n }\n}\n\nfunction writeAuthState(payload: Record<string, unknown>): void {\n const profileId =\n (payload.activeProfileId as string) ??\n ((payload.user as Record<string, unknown>)?.id as string) ??\n sessionStorage.getItem(BF_ACTIVE);\n if (!profileId) return;\n\n if (payload.user) {\n localStorage.setItem(\n `${BF_PREFIX}-${profileId}-user`,\n JSON.stringify(payload.user),\n );\n }\n if (payload.tokens && typeof payload.tokens === \"object\") {\n const t = payload.tokens as Record<string, unknown>;\n const { workspaceToken, ...rest } = t;\n localStorage.setItem(\n `${BF_PREFIX}-${profileId}-tokens`,\n JSON.stringify(rest),\n );\n if (workspaceToken) {\n localStorage.setItem(\n `${BF_PREFIX}-${profileId}-workspace-token`,\n String(workspaceToken),\n );\n }\n }\n if (payload.profiles) {\n localStorage.setItem(BF_PROFILES, JSON.stringify(payload.profiles));\n }\n sessionStorage.setItem(BF_ACTIVE, profileId);\n}\n\nfunction clearAuthState(): void {\n const activeId = sessionStorage.getItem(BF_ACTIVE);\n if (activeId) {\n localStorage.removeItem(`${BF_PREFIX}-${activeId}-user`);\n localStorage.removeItem(`${BF_PREFIX}-${activeId}-tokens`);\n localStorage.removeItem(`${BF_PREFIX}-${activeId}-workspace-token`);\n localStorage.removeItem(`${BF_PREFIX}-${activeId}-auth-storage`);\n // Remove from profiles list\n try {\n const raw = localStorage.getItem(BF_PROFILES);\n const profiles = raw ? JSON.parse(raw) : [];\n localStorage.setItem(\n BF_PROFILES,\n JSON.stringify(\n profiles.filter((p: { id: string }) => p.id !== activeId),\n ),\n );\n } catch {\n /* ignore */\n }\n sessionStorage.removeItem(BF_ACTIVE);\n }\n localStorage.removeItem(\"auth-storage\");\n}\n\nfunction clearAllAuthState(): void {\n // Get all profiles and remove their data\n try {\n const raw = localStorage.getItem(BF_PROFILES);\n const profiles: Array<{ id: string }> = raw ? JSON.parse(raw) : [];\n for (const p of profiles) {\n localStorage.removeItem(`${BF_PREFIX}-${p.id}-user`);\n localStorage.removeItem(`${BF_PREFIX}-${p.id}-tokens`);\n localStorage.removeItem(`${BF_PREFIX}-${p.id}-workspace-token`);\n localStorage.removeItem(`${BF_PREFIX}-${p.id}-auth-storage`);\n localStorage.removeItem(`${BF_PREFIX}-${p.id}-context`);\n }\n } catch {\n /* ignore */\n }\n for (const key of Object.keys(localStorage)) {\n if (key.startsWith(`${BF_PREFIX}-`) && key.endsWith(\"-auth-storage\")) {\n localStorage.removeItem(key);\n }\n }\n localStorage.removeItem(BF_PROFILES);\n localStorage.removeItem(\"auth-storage\");\n sessionStorage.removeItem(BF_ACTIVE);\n}\n\n// SSO cookie helpers (shared domain cookie for local dev fast-path)\nconst SSO_COOKIE_NAME = \"bf-sso-profile\";\nconst SHELL_SSO_COOKIE_NAME = \"bf-sso\";\nfunction setSSoCookieBridge(profileId: string, origin: string): void {\n try {\n const hostname = window.location.hostname;\n const domain = hostname.endsWith(\".local.burdenoff.com\")\n ? \".local.burdenoff.com\"\n : undefined;\n const domainPart = domain ? `; domain=${domain}` : \"\";\n const securePart = window.location.protocol === \"https:\" ? \"; secure\" : \"\";\n const cookieValue = JSON.stringify({ id: profileId, origin });\n document.cookie = `${SSO_COOKIE_NAME}=${encodeURIComponent(cookieValue)}${domainPart}; path=/; samesite=lax${securePart}; max-age=86400`;\n } catch {\n /* ignore */\n }\n}\n\nfunction setShellSsoCookieBridge(profileId: string, origin: string): void {\n try {\n const hostname = window.location.hostname;\n const domain = hostname.endsWith(\".local.burdenoff.com\")\n ? \".local.burdenoff.com\"\n : undefined;\n const domainPart = domain ? `; domain=${domain}` : \"\";\n const securePart = window.location.protocol === \"https:\" ? \"; secure\" : \"\";\n const ssoValue = JSON.stringify({ id: profileId, origin });\n document.cookie = `${SHELL_SSO_COOKIE_NAME}=${encodeURIComponent(ssoValue)}${domainPart}; path=/; samesite=lax${securePart}; max-age=86400`;\n } catch {\n /* ignore */\n }\n}\n\nfunction clearSSoCookieBridge(): void {\n try {\n const hostname = window.location.hostname;\n const domain = hostname.endsWith(\".local.burdenoff.com\")\n ? \".local.burdenoff.com\"\n : undefined;\n document.cookie = `${SSO_COOKIE_NAME}=; path=/; max-age=0`;\n document.cookie = `${SHELL_SSO_COOKIE_NAME}=; path=/; max-age=0`;\n if (domain) {\n document.cookie = `${SSO_COOKIE_NAME}=; path=/; domain=${domain}; max-age=0`;\n document.cookie = `${SHELL_SSO_COOKIE_NAME}=; path=/; domain=${domain}; max-age=0`;\n }\n if (hostname && ![\"localhost\", \"127.0.0.1\"].includes(hostname)) {\n document.cookie = `${SSO_COOKIE_NAME}=; path=/; domain=${hostname}; max-age=0`;\n document.cookie = `${SHELL_SSO_COOKIE_NAME}=; path=/; domain=${hostname}; max-age=0`;\n }\n } catch {\n /* ignore */\n }\n}\n\nexport function SessionBridgePage() {\n const connectedParents = useRef<Set<MessageEventSource>>(new Set());\n const initialReadySent = useRef(false);\n const readySentTo = useRef<Set<MessageEventSource>>(new Set());\n const storageAccessGranted = useRef(false);\n\n // Request unpartitioned storage access (Storage Access API).\n // This is critical for cross-domain SSO in modern browsers that\n // partition third-party iframe localStorage.\n useEffect(() => {\n async function requestAccess() {\n try {\n // Check if Storage Access API is available\n if (!document.requestStorageAccess) {\n storageAccessGranted.current = true;\n return;\n }\n // Check if we already have access\n const hasAccess = await document.hasStorageAccess();\n if (hasAccess) {\n storageAccessGranted.current = true;\n return;\n }\n // Request unpartitioned storage access\n await document.requestStorageAccess();\n storageAccessGranted.current = true;\n } catch {\n // Storage Access API not available or denied — fall through\n // to cookie-based fallback. localStorage will be partitioned.\n storageAccessGranted.current = false;\n }\n }\n void requestAccess();\n }, []);\n\n useEffect(() => {\n function isOriginAllowed(origin: string): boolean {\n return isAllowedOrigin(origin);\n }\n\n function broadcastToAll(\n message: BridgeMessage,\n excludeSource?: MessageEventSource | null,\n ): void {\n if (window.parent && window.parent !== window) {\n window.parent.postMessage(message, \"*\");\n }\n connectedParents.current.forEach((parent) => {\n if (parent !== excludeSource && \"postMessage\" in parent) {\n (parent as Window).postMessage(message, \"*\");\n }\n });\n }\n\n function handleMessage(event: MessageEvent): void {\n if (!isOriginAllowed(event.origin)) return;\n const message = event.data as BridgeMessage;\n if (!message?.type || message.source === BRIDGE_SOURCE) return;\n\n switch (message.type) {\n case \"AUTH_INIT\": {\n if (event.source) connectedParents.current.add(event.source);\n\n // If the parent sends its current auth state in AUTH_INIT,\n // store it so other cross-domain shells can pick it up.\n if (message.payload && typeof message.payload === \"object\") {\n const initPayload = message.payload as Record<string, unknown>;\n if (initPayload.user && initPayload.tokens) {\n writeAuthState(initPayload);\n }\n }\n\n const state = readAuthState();\n if (event.source && \"postMessage\" in event.source) {\n (event.source as Window).postMessage(\n { type: \"AUTH_STATE\", payload: state, source: BRIDGE_SOURCE },\n event.origin,\n );\n if (!readySentTo.current.has(event.source)) {\n readySentTo.current.add(event.source);\n (event.source as Window).postMessage(\n { type: \"AUTH_BRIDGE_READY\", source: BRIDGE_SOURCE },\n event.origin,\n );\n }\n }\n break;\n }\n case \"AUTH_LOGIN\": {\n if (message.payload) {\n writeAuthState(message.payload);\n // Set SSO cookie for cross-domain fast-path detection\n const loginPayload = message.payload as Record<string, unknown>;\n const loginProfileId =\n (loginPayload.activeProfileId as string) ??\n ((loginPayload.user as Record<string, unknown>)?.id as string);\n if (loginProfileId) {\n clearSSoCookieBridge();\n setSSoCookieBridge(loginProfileId, event.origin);\n setShellSsoCookieBridge(loginProfileId, event.origin);\n }\n broadcastToAll(\n {\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"login\" },\n source: BRIDGE_SOURCE,\n },\n event.source,\n );\n }\n break;\n }\n case \"AUTH_LOGOUT\": {\n clearAuthState();\n clearSSoCookieBridge();\n broadcastToAll(\n {\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"logout\" },\n source: BRIDGE_SOURCE,\n },\n event.source,\n );\n break;\n }\n case \"AUTH_LOGOUT_ALL\": {\n clearAllAuthState();\n clearSSoCookieBridge();\n broadcastToAll(\n {\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"logout_all\" },\n source: BRIDGE_SOURCE,\n },\n event.source,\n );\n break;\n }\n case \"AUTH_TOKEN_REFRESH\": {\n if (message.payload?.tokens) {\n writeAuthState({ tokens: message.payload.tokens });\n broadcastToAll(\n {\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"refresh\" },\n source: BRIDGE_SOURCE,\n },\n event.source,\n );\n }\n break;\n }\n case \"AUTH_ACCOUNT_SWITCH\": {\n if (message.payload) {\n writeAuthState(message.payload);\n broadcastToAll(\n {\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"account_switch\" },\n source: BRIDGE_SOURCE,\n },\n event.source,\n );\n }\n break;\n }\n }\n }\n\n function handleStorageChange(event: StorageEvent): void {\n if (event.key?.startsWith(BF_PREFIX) || event.key === BF_PROFILES) {\n broadcastToAll({\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"storage_sync\" },\n source: BRIDGE_SOURCE,\n });\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n window.addEventListener(\"storage\", handleStorageChange);\n\n // Send initial AUTH_BRIDGE_READY to parent (only once, guard against StrictMode double-mount)\n if (\n window.parent &&\n window.parent !== window &&\n !initialReadySent.current\n ) {\n initialReadySent.current = true;\n window.parent.postMessage(\n { type: \"AUTH_BRIDGE_READY\", source: BRIDGE_SOURCE },\n \"*\",\n );\n }\n\n return () => {\n window.removeEventListener(\"message\", handleMessage);\n window.removeEventListener(\"storage\", handleStorageChange);\n // Don't clear connectedParents or readySentTo on cleanup to maintain state across StrictMode remounts\n };\n }, []);\n\n return (\n <div\n id=\"auth-session-bridge-root\"\n data-bridge=\"active\"\n style={{ display: \"none\" }}\n />\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionBridgePage.js","names":[],"sources":["../../../src/auth/pages/SessionBridgePage.tsx"],"sourcesContent":["/**\n * SessionBridgePage — Cross-Domain Auth Session Bridge (Profile-Scoped)\n *\n * Embedded as hidden iframe by other app shells. Manages profile-scoped\n * auth tokens in localStorage and relays state via postMessage.\n *\n * Storage uses ProfileStorageManager keys:\n * bf-profiles, bf-p-{id}-user, bf-p-{id}-tokens, bf-p-{id}-workspace-token\n * bf-active-profile (sessionStorage, per-tab)\n *\n * URL: /auth/session-bridge\n */\n\nimport { useEffect, useRef } from \"react\";\n\nconst BRIDGE_SOURCE = \"burdenoff-auth-bridge\";\nconst PARENT_SOURCE = \"burdenoff-auth-client\";\nconst BF_PREFIX = \"bf-p\";\nconst BF_PROFILES = \"bf-profiles\";\nconst BF_ACTIVE = \"bf-active-profile\";\n\ninterface BridgeMessage {\n type: string;\n payload?: Record<string, unknown>;\n nonce?: string;\n source?: string;\n}\n\ninterface ConnectedParent {\n source: Window;\n origin: string;\n nonce: string;\n}\n\nfunction isWindowMessageSource(\n source: MessageEventSource | null,\n): source is Window {\n return (\n source !== null &&\n typeof (source as { postMessage?: unknown }).postMessage === \"function\"\n );\n}\n\nfunction isBridgeMessage(value: unknown): value is BridgeMessage {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { type?: unknown }).type === \"string\"\n );\n}\n\n/**\n * Dynamically validates allowed origins for the auth bridge.\n * Accepts all Burdenoff product domains (prod + alpha + local dev).\n */\nconst ALLOWED_PRODUCT_DOMAINS = new Set([\n \"burdenoff.com\",\n \"vibecontrols.com\",\n \"fluidgrids.com\",\n \"botlit.ai\",\n \"bigconsole.com\",\n \"gethealthybowl.com\",\n \"headshotmarketing.com\",\n \"timecampus.com\",\n \"ggnomad.com\",\n \"movethewheels.com\",\n \"crewfoundry.com\",\n \"planmagnet.com\",\n \"eventfullymanaged.com\",\n \"kadaikodi.com\",\n \"assethandler.com\",\n \"technospam.com\",\n \"semanticfed.com\",\n \"manufacturedops.com\",\n \"theglobalfuel.com\",\n \"housingvista.com\",\n \"proserviceworld.com\",\n \"mybodyshield.com\",\n \"artistrybase.com\",\n \"collabkin.com\",\n \"brainyrich.com\",\n \"theculturepost.com\",\n \"comradecircle.com\",\n \"cosmicintersection.com\",\n \"govcitizenhub.com\",\n \"intelwatchtower.com\",\n \"ecoimpacthub.com\",\n \"buildmyiq.com\",\n \"fluidgrids.ai\",\n \"atheletebridge.com\",\n \"adaptercloud.com\",\n \"coolandlovely.com\",\n \"subscriberbot.com\",\n \"labsofscience.com\",\n \"hookmovies.com\",\n]);\n\nfunction isAllowedOrigin(origin: string): boolean {\n try {\n const url = new URL(origin);\n // Allow all localhost ports (local dev)\n if (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\") {\n return true;\n }\n // Allow *.local.burdenoff.com (local dev with nginx)\n if (url.hostname.endsWith(\".local.burdenoff.com\")) {\n return true;\n }\n // Allow app.{domain} and alphaapp.{domain} for all known product domains\n for (const domain of ALLOWED_PRODUCT_DOMAINS) {\n if (\n url.hostname === domain ||\n url.hostname === `app.${domain}` ||\n url.hostname === `alphaapp.${domain}` ||\n // Admin app shells (admin.burdenoff.com / alphaadmin.burdenoff.com)\n // embed this bridge iframe too. Without trusting their origin, the\n // bridge ignores their postMessages and the admin shell never receives\n // the shared session.\n url.hostname === `admin.${domain}` ||\n url.hostname === `alphaadmin.${domain}` ||\n url.hostname === `www.${domain}`\n ) {\n return true;\n }\n }\n return false;\n } catch {\n return false;\n }\n}\n\nfunction readAuthState(): Record<string, unknown> {\n try {\n const profiles = localStorage.getItem(BF_PROFILES);\n let activeId = sessionStorage.getItem(BF_ACTIVE);\n\n // Fall back: if sessionStorage is empty but localStorage has profiles,\n // pick the first profile (same logic as resolveActiveProfileId)\n if (!activeId && profiles) {\n try {\n const profileList = JSON.parse(profiles) as Array<{ id: string }>;\n if (profileList.length > 0) {\n activeId = profileList[0].id;\n sessionStorage.setItem(BF_ACTIVE, activeId);\n }\n } catch {\n // ignore\n }\n }\n\n if (!activeId) {\n return {\n user: null,\n tokens: null,\n profiles: profiles ? JSON.parse(profiles) : [],\n activeProfileId: null,\n };\n }\n const user = localStorage.getItem(`${BF_PREFIX}-${activeId}-user`);\n const tokens = localStorage.getItem(`${BF_PREFIX}-${activeId}-tokens`);\n const wsToken = localStorage.getItem(\n `${BF_PREFIX}-${activeId}-workspace-token`,\n );\n\n return {\n user: user ? JSON.parse(user) : null,\n tokens: tokens\n ? { ...JSON.parse(tokens), workspaceToken: wsToken ?? undefined }\n : null,\n profiles: profiles ? JSON.parse(profiles) : [],\n activeProfileId: activeId,\n };\n } catch {\n return { user: null, tokens: null, profiles: [], activeProfileId: null };\n }\n}\n\nfunction writeAuthState(payload: Record<string, unknown>): void {\n const profileId =\n (payload.activeProfileId as string) ??\n ((payload.user as Record<string, unknown>)?.id as string) ??\n sessionStorage.getItem(BF_ACTIVE);\n if (!profileId) return;\n\n if (payload.user) {\n localStorage.setItem(\n `${BF_PREFIX}-${profileId}-user`,\n JSON.stringify(payload.user),\n );\n }\n if (payload.tokens && typeof payload.tokens === \"object\") {\n const t = payload.tokens as Record<string, unknown>;\n const { workspaceToken, ...rest } = t;\n localStorage.setItem(\n `${BF_PREFIX}-${profileId}-tokens`,\n JSON.stringify(rest),\n );\n if (workspaceToken) {\n localStorage.setItem(\n `${BF_PREFIX}-${profileId}-workspace-token`,\n String(workspaceToken),\n );\n }\n }\n if (payload.profiles) {\n localStorage.setItem(BF_PROFILES, JSON.stringify(payload.profiles));\n }\n sessionStorage.setItem(BF_ACTIVE, profileId);\n}\n\nfunction clearAuthState(): void {\n const activeId = sessionStorage.getItem(BF_ACTIVE);\n if (activeId) {\n localStorage.removeItem(`${BF_PREFIX}-${activeId}-user`);\n localStorage.removeItem(`${BF_PREFIX}-${activeId}-tokens`);\n localStorage.removeItem(`${BF_PREFIX}-${activeId}-workspace-token`);\n localStorage.removeItem(`${BF_PREFIX}-${activeId}-auth-storage`);\n // Remove from profiles list\n try {\n const raw = localStorage.getItem(BF_PROFILES);\n const profiles = raw ? JSON.parse(raw) : [];\n localStorage.setItem(\n BF_PROFILES,\n JSON.stringify(\n profiles.filter((p: { id: string }) => p.id !== activeId),\n ),\n );\n } catch {\n /* ignore */\n }\n sessionStorage.removeItem(BF_ACTIVE);\n }\n localStorage.removeItem(\"auth-storage\");\n}\n\nfunction clearAllAuthState(): void {\n // Get all profiles and remove their data\n try {\n const raw = localStorage.getItem(BF_PROFILES);\n const profiles: Array<{ id: string }> = raw ? JSON.parse(raw) : [];\n for (const p of profiles) {\n localStorage.removeItem(`${BF_PREFIX}-${p.id}-user`);\n localStorage.removeItem(`${BF_PREFIX}-${p.id}-tokens`);\n localStorage.removeItem(`${BF_PREFIX}-${p.id}-workspace-token`);\n localStorage.removeItem(`${BF_PREFIX}-${p.id}-auth-storage`);\n localStorage.removeItem(`${BF_PREFIX}-${p.id}-context`);\n }\n } catch {\n /* ignore */\n }\n for (const key of Object.keys(localStorage)) {\n if (key.startsWith(`${BF_PREFIX}-`) && key.endsWith(\"-auth-storage\")) {\n localStorage.removeItem(key);\n }\n }\n localStorage.removeItem(BF_PROFILES);\n localStorage.removeItem(\"auth-storage\");\n sessionStorage.removeItem(BF_ACTIVE);\n}\n\n// SSO cookie helpers (shared domain cookie for local dev fast-path)\nconst SSO_COOKIE_NAME = \"bf-sso-profile\";\nconst SHELL_SSO_COOKIE_NAME = \"bf-sso\";\nfunction setSSoCookieBridge(profileId: string, origin: string): void {\n try {\n const hostname = window.location.hostname;\n const domain = hostname.endsWith(\".local.burdenoff.com\")\n ? \".local.burdenoff.com\"\n : undefined;\n const domainPart = domain ? `; domain=${domain}` : \"\";\n const securePart = window.location.protocol === \"https:\" ? \"; secure\" : \"\";\n const cookieValue = JSON.stringify({ id: profileId, origin });\n document.cookie = `${SSO_COOKIE_NAME}=${encodeURIComponent(cookieValue)}${domainPart}; path=/; samesite=lax${securePart}; max-age=86400`;\n } catch {\n /* ignore */\n }\n}\n\nfunction setShellSsoCookieBridge(profileId: string, origin: string): void {\n try {\n const hostname = window.location.hostname;\n const domain = hostname.endsWith(\".local.burdenoff.com\")\n ? \".local.burdenoff.com\"\n : undefined;\n const domainPart = domain ? `; domain=${domain}` : \"\";\n const securePart = window.location.protocol === \"https:\" ? \"; secure\" : \"\";\n const ssoValue = JSON.stringify({ id: profileId, origin });\n document.cookie = `${SHELL_SSO_COOKIE_NAME}=${encodeURIComponent(ssoValue)}${domainPart}; path=/; samesite=lax${securePart}; max-age=86400`;\n } catch {\n /* ignore */\n }\n}\n\nfunction clearSSoCookieBridge(): void {\n try {\n const hostname = window.location.hostname;\n const domain = hostname.endsWith(\".local.burdenoff.com\")\n ? \".local.burdenoff.com\"\n : undefined;\n document.cookie = `${SSO_COOKIE_NAME}=; path=/; max-age=0`;\n document.cookie = `${SHELL_SSO_COOKIE_NAME}=; path=/; max-age=0`;\n if (domain) {\n document.cookie = `${SSO_COOKIE_NAME}=; path=/; domain=${domain}; max-age=0`;\n document.cookie = `${SHELL_SSO_COOKIE_NAME}=; path=/; domain=${domain}; max-age=0`;\n }\n if (hostname && ![\"localhost\", \"127.0.0.1\"].includes(hostname)) {\n document.cookie = `${SSO_COOKIE_NAME}=; path=/; domain=${hostname}; max-age=0`;\n document.cookie = `${SHELL_SSO_COOKIE_NAME}=; path=/; domain=${hostname}; max-age=0`;\n }\n } catch {\n /* ignore */\n }\n}\n\nexport function SessionBridgePage() {\n const connectedParents = useRef<Map<Window, ConnectedParent>>(new Map());\n const readySentTo = useRef<Map<Window, string>>(new Map());\n const storageAccessGranted = useRef(false);\n\n // Request unpartitioned storage access (Storage Access API).\n // This is critical for cross-domain SSO in modern browsers that\n // partition third-party iframe localStorage.\n useEffect(() => {\n async function requestAccess() {\n try {\n // Check if Storage Access API is available\n if (!document.requestStorageAccess) {\n storageAccessGranted.current = true;\n return;\n }\n // Check if we already have access\n const hasAccess = await document.hasStorageAccess();\n if (hasAccess) {\n storageAccessGranted.current = true;\n return;\n }\n // Request unpartitioned storage access\n await document.requestStorageAccess();\n storageAccessGranted.current = true;\n } catch {\n // Storage Access API not available or denied — fall through\n // to cookie-based fallback. localStorage will be partitioned.\n storageAccessGranted.current = false;\n }\n }\n void requestAccess();\n }, []);\n\n useEffect(() => {\n function isOriginAllowed(origin: string): boolean {\n return isAllowedOrigin(origin);\n }\n\n function broadcastToAll(\n message: BridgeMessage,\n excludeSource?: Window | null,\n ): void {\n connectedParents.current.forEach((connection, parent) => {\n if (parent !== excludeSource) {\n connection.source.postMessage(\n { ...message, source: BRIDGE_SOURCE, nonce: connection.nonce },\n connection.origin,\n );\n }\n });\n }\n\n function handleMessage(event: MessageEvent): void {\n if (!isOriginAllowed(event.origin)) return;\n if (!isBridgeMessage(event.data) || event.data.source !== PARENT_SOURCE) {\n return;\n }\n const message = event.data;\n const parentSource = isWindowMessageSource(event.source)\n ? event.source\n : null;\n if (!parentSource) return;\n\n const incomingNonce =\n typeof message.nonce === \"string\" && message.nonce.length > 0\n ? message.nonce\n : null;\n const existingConnection = connectedParents.current.get(parentSource);\n\n if (message.type !== \"AUTH_INIT\") {\n if (!incomingNonce || existingConnection?.nonce !== incomingNonce) {\n return;\n }\n } else if (!incomingNonce) {\n return;\n }\n\n switch (message.type) {\n case \"AUTH_INIT\": {\n connectedParents.current.set(parentSource, {\n source: parentSource,\n origin: event.origin,\n nonce: incomingNonce,\n });\n\n // If the parent sends its current auth state in AUTH_INIT,\n // store it so other cross-domain shells can pick it up.\n if (message.payload && typeof message.payload === \"object\") {\n const initPayload = message.payload as Record<string, unknown>;\n if (initPayload.user && initPayload.tokens) {\n writeAuthState(initPayload);\n }\n }\n\n const state = readAuthState();\n const connection = connectedParents.current.get(parentSource);\n if (connection) {\n connection.source.postMessage(\n {\n type: \"AUTH_STATE\",\n payload: state,\n source: BRIDGE_SOURCE,\n nonce: connection.nonce,\n },\n event.origin,\n );\n if (readySentTo.current.get(parentSource) !== connection.nonce) {\n readySentTo.current.set(parentSource, connection.nonce);\n connection.source.postMessage(\n {\n type: \"AUTH_BRIDGE_READY\",\n source: BRIDGE_SOURCE,\n nonce: connection.nonce,\n },\n event.origin,\n );\n }\n }\n break;\n }\n case \"AUTH_LOGIN\": {\n if (message.payload) {\n writeAuthState(message.payload);\n // Set SSO cookie for cross-domain fast-path detection\n const loginPayload = message.payload as Record<string, unknown>;\n const loginProfileId =\n (loginPayload.activeProfileId as string) ??\n ((loginPayload.user as Record<string, unknown>)?.id as string);\n if (loginProfileId) {\n clearSSoCookieBridge();\n setSSoCookieBridge(loginProfileId, event.origin);\n setShellSsoCookieBridge(loginProfileId, event.origin);\n }\n broadcastToAll(\n {\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"login\" },\n },\n parentSource,\n );\n }\n break;\n }\n case \"AUTH_LOGOUT\": {\n clearAuthState();\n clearSSoCookieBridge();\n broadcastToAll(\n {\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"logout\" },\n },\n parentSource,\n );\n break;\n }\n case \"AUTH_LOGOUT_ALL\": {\n clearAllAuthState();\n clearSSoCookieBridge();\n broadcastToAll(\n {\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"logout_all\" },\n },\n parentSource,\n );\n break;\n }\n case \"AUTH_TOKEN_REFRESH\": {\n if (message.payload?.tokens) {\n writeAuthState({ tokens: message.payload.tokens });\n broadcastToAll(\n {\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"refresh\" },\n },\n parentSource,\n );\n }\n break;\n }\n case \"AUTH_ACCOUNT_SWITCH\": {\n if (message.payload) {\n writeAuthState(message.payload);\n broadcastToAll(\n {\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"account_switch\" },\n },\n parentSource,\n );\n }\n break;\n }\n }\n }\n\n function handleStorageChange(event: StorageEvent): void {\n if (event.key?.startsWith(BF_PREFIX) || event.key === BF_PROFILES) {\n broadcastToAll({\n type: \"AUTH_STATE_CHANGED\",\n payload: { ...readAuthState(), trigger: \"storage_sync\" },\n });\n }\n }\n\n window.addEventListener(\"message\", handleMessage);\n window.addEventListener(\"storage\", handleStorageChange);\n\n return () => {\n window.removeEventListener(\"message\", handleMessage);\n window.removeEventListener(\"storage\", handleStorageChange);\n // Don't clear connectedParents or readySentTo on cleanup to maintain state across StrictMode remounts\n };\n }, []);\n\n return (\n <div\n id=\"auth-session-bridge-root\"\n data-bridge=\"active\"\n style={{ display: \"none\" }}\n />\n );\n}\n"],"mappings":"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"}
|