@orangecheck/auth-client 2.17.2 → 2.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +206 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +198 -15
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -31,6 +31,7 @@ interface OcSessionState {
|
|
|
31
31
|
status: OcSessionStatus;
|
|
32
32
|
account: OcAccount | null;
|
|
33
33
|
roster: OcAccountSummary[];
|
|
34
|
+
tabPinned: boolean;
|
|
34
35
|
error: Error | null;
|
|
35
36
|
refresh: () => Promise<void>;
|
|
36
37
|
signOut: (opts?: {
|
|
@@ -152,6 +153,20 @@ interface OcLinkedIdentitiesProps {
|
|
|
152
153
|
}
|
|
153
154
|
declare function OcLinkedIdentities({ authOrigin, className, onChange, }: OcLinkedIdentitiesProps): React.ReactElement;
|
|
154
155
|
|
|
156
|
+
declare const TAB_SESSION_HEADER = "x-oc-tab-session";
|
|
157
|
+
declare const TAB_SESSION_STORAGE_KEY = "oc_tab_session";
|
|
158
|
+
declare const TAB_ADOPT_HASH = "#oc-adopt";
|
|
159
|
+
interface OcTabSession {
|
|
160
|
+
token: string;
|
|
161
|
+
didOc: string;
|
|
162
|
+
}
|
|
163
|
+
declare function readTabSession(): OcTabSession | null;
|
|
164
|
+
declare function writeTabSession(session: OcTabSession): void;
|
|
165
|
+
declare function clearTabSession(): void;
|
|
166
|
+
declare function tabSessionHeader(): Record<string, string>;
|
|
167
|
+
declare function installTabFetchInterceptor(authOrigin: string): () => void;
|
|
168
|
+
declare function consumeTabAdoptMarker(): boolean;
|
|
169
|
+
|
|
155
170
|
interface WebAuthnCredentialPublic {
|
|
156
171
|
id: string;
|
|
157
172
|
label: string;
|
|
@@ -234,4 +249,4 @@ declare function handleSudoRequired(body: {
|
|
|
234
249
|
returnTo?: string;
|
|
235
250
|
}): boolean;
|
|
236
251
|
|
|
237
|
-
export { DEFAULT_CONFIG, DISPLAY_IDENTITY_KINDS, type DisplayIdentity, type DisplayIdentityKind, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, type OcAccountSummary, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcLinkedIdentities, type OcLinkedIdentitiesProps, type OcLinkedIdentity, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type OcSignOutScope, type RedirectToSudoArgs, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnRemoveResult, type WebAuthnRenameResult, type WebAuthnStepUpResult, buildAddAccountUrl, buildSignInUrl, fetchOcLinkedIdentities, handleSudoRequired, redirectToSudo, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister };
|
|
252
|
+
export { DEFAULT_CONFIG, DISPLAY_IDENTITY_KINDS, type DisplayIdentity, type DisplayIdentityKind, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, type OcAccountSummary, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcLinkedIdentities, type OcLinkedIdentitiesProps, type OcLinkedIdentity, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type OcSignOutScope, type OcTabSession, type RedirectToSudoArgs, TAB_ADOPT_HASH, TAB_SESSION_HEADER, TAB_SESSION_STORAGE_KEY, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnRemoveResult, type WebAuthnRenameResult, type WebAuthnStepUpResult, buildAddAccountUrl, buildSignInUrl, clearTabSession, consumeTabAdoptMarker, fetchOcLinkedIdentities, handleSudoRequired, installTabFetchInterceptor, readTabSession, redirectToSudo, tabSessionHeader, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister, writeTabSession };
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ interface OcSessionState {
|
|
|
31
31
|
status: OcSessionStatus;
|
|
32
32
|
account: OcAccount | null;
|
|
33
33
|
roster: OcAccountSummary[];
|
|
34
|
+
tabPinned: boolean;
|
|
34
35
|
error: Error | null;
|
|
35
36
|
refresh: () => Promise<void>;
|
|
36
37
|
signOut: (opts?: {
|
|
@@ -152,6 +153,20 @@ interface OcLinkedIdentitiesProps {
|
|
|
152
153
|
}
|
|
153
154
|
declare function OcLinkedIdentities({ authOrigin, className, onChange, }: OcLinkedIdentitiesProps): React.ReactElement;
|
|
154
155
|
|
|
156
|
+
declare const TAB_SESSION_HEADER = "x-oc-tab-session";
|
|
157
|
+
declare const TAB_SESSION_STORAGE_KEY = "oc_tab_session";
|
|
158
|
+
declare const TAB_ADOPT_HASH = "#oc-adopt";
|
|
159
|
+
interface OcTabSession {
|
|
160
|
+
token: string;
|
|
161
|
+
didOc: string;
|
|
162
|
+
}
|
|
163
|
+
declare function readTabSession(): OcTabSession | null;
|
|
164
|
+
declare function writeTabSession(session: OcTabSession): void;
|
|
165
|
+
declare function clearTabSession(): void;
|
|
166
|
+
declare function tabSessionHeader(): Record<string, string>;
|
|
167
|
+
declare function installTabFetchInterceptor(authOrigin: string): () => void;
|
|
168
|
+
declare function consumeTabAdoptMarker(): boolean;
|
|
169
|
+
|
|
155
170
|
interface WebAuthnCredentialPublic {
|
|
156
171
|
id: string;
|
|
157
172
|
label: string;
|
|
@@ -234,4 +249,4 @@ declare function handleSudoRequired(body: {
|
|
|
234
249
|
returnTo?: string;
|
|
235
250
|
}): boolean;
|
|
236
251
|
|
|
237
|
-
export { DEFAULT_CONFIG, DISPLAY_IDENTITY_KINDS, type DisplayIdentity, type DisplayIdentityKind, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, type OcAccountSummary, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcLinkedIdentities, type OcLinkedIdentitiesProps, type OcLinkedIdentity, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type OcSignOutScope, type RedirectToSudoArgs, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnRemoveResult, type WebAuthnRenameResult, type WebAuthnStepUpResult, buildAddAccountUrl, buildSignInUrl, fetchOcLinkedIdentities, handleSudoRequired, redirectToSudo, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister };
|
|
252
|
+
export { DEFAULT_CONFIG, DISPLAY_IDENTITY_KINDS, type DisplayIdentity, type DisplayIdentityKind, type OcAccount, OcAccountChip, type OcAccountChipProps, OcAccountPill, type OcAccountPillProps, type OcAccountSummary, OcAddressInput, type OcAddressInputProps, type OcAuthConfig, OcLinkedIdentities, type OcLinkedIdentitiesProps, type OcLinkedIdentity, OcSessionProvider, type OcSessionState, type OcSessionStatus, OcSignIn, OcSignInButton, type OcSignInButtonProps, type OcSignInProps, type OcSignOutScope, type OcTabSession, type RedirectToSudoArgs, TAB_ADOPT_HASH, TAB_SESSION_HEADER, TAB_SESSION_STORAGE_KEY, type UseOcAddressSuggestionOptions, type UseOcAddressSuggestionReturn, type UseStepUpAuthReturn, type UseWebAuthnListReturn, type UseWebAuthnRegisterReturn, type WebAuthnAssertionStatus, type WebAuthnCredentialPublic, type WebAuthnListStatus, type WebAuthnRegisterResult, type WebAuthnRegisterStatus, type WebAuthnRemoveResult, type WebAuthnRenameResult, type WebAuthnStepUpResult, buildAddAccountUrl, buildSignInUrl, clearTabSession, consumeTabAdoptMarker, fetchOcLinkedIdentities, handleSudoRequired, installTabFetchInterceptor, readTabSession, redirectToSudo, tabSessionHeader, useOcAddressSuggestion, useOcSession, useOptionalOcSession, useStepUpAuth, useWebAuthnList, useWebAuthnRegister, writeTabSession };
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,91 @@ function buildAddAccountUrl(cfg, returnTo) {
|
|
|
49
49
|
u.searchParams.set("add", "1");
|
|
50
50
|
return u.toString();
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
// src/tab-session.ts
|
|
54
|
+
var TAB_SESSION_HEADER = "x-oc-tab-session";
|
|
55
|
+
var TAB_SESSION_STORAGE_KEY = "oc_tab_session";
|
|
56
|
+
var TAB_ADOPT_HASH = "#oc-adopt";
|
|
57
|
+
function readTabSession() {
|
|
58
|
+
if (typeof window === "undefined") return null;
|
|
59
|
+
try {
|
|
60
|
+
const raw = window.sessionStorage.getItem(TAB_SESSION_STORAGE_KEY);
|
|
61
|
+
if (!raw) return null;
|
|
62
|
+
const parsed = JSON.parse(raw);
|
|
63
|
+
if (typeof parsed.token !== "string" || parsed.token.length === 0) return null;
|
|
64
|
+
if (typeof parsed.didOc !== "string" || parsed.didOc.length === 0) return null;
|
|
65
|
+
return { token: parsed.token, didOc: parsed.didOc };
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function writeTabSession(session) {
|
|
71
|
+
if (typeof window === "undefined") return;
|
|
72
|
+
try {
|
|
73
|
+
window.sessionStorage.setItem(TAB_SESSION_STORAGE_KEY, JSON.stringify(session));
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function clearTabSession() {
|
|
78
|
+
if (typeof window === "undefined") return;
|
|
79
|
+
try {
|
|
80
|
+
window.sessionStorage.removeItem(TAB_SESSION_STORAGE_KEY);
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function tabSessionHeader() {
|
|
85
|
+
const pin = readTabSession();
|
|
86
|
+
return pin ? { [TAB_SESSION_HEADER]: pin.token } : {};
|
|
87
|
+
}
|
|
88
|
+
function isPinnableUrl(url, authOrigin) {
|
|
89
|
+
if (typeof window === "undefined") return false;
|
|
90
|
+
try {
|
|
91
|
+
const u = new URL(url, window.location.href);
|
|
92
|
+
return u.origin === window.location.origin || u.origin === authOrigin;
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function installTabFetchInterceptor(authOrigin) {
|
|
98
|
+
if (typeof window === "undefined") return () => {
|
|
99
|
+
};
|
|
100
|
+
const original = window.fetch;
|
|
101
|
+
const wrapped = (input, init) => {
|
|
102
|
+
try {
|
|
103
|
+
const pin = readTabSession();
|
|
104
|
+
if (pin) {
|
|
105
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
106
|
+
if (isPinnableUrl(url, authOrigin)) {
|
|
107
|
+
const headers = new Headers(
|
|
108
|
+
init?.headers ?? (input instanceof Request ? input.headers : void 0)
|
|
109
|
+
);
|
|
110
|
+
if (!headers.has("authorization") && !headers.has(TAB_SESSION_HEADER)) {
|
|
111
|
+
headers.set(TAB_SESSION_HEADER, pin.token);
|
|
112
|
+
init = { ...init, headers };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
} catch {
|
|
117
|
+
}
|
|
118
|
+
return original.call(window, input, init);
|
|
119
|
+
};
|
|
120
|
+
window.fetch = wrapped;
|
|
121
|
+
return () => {
|
|
122
|
+
if (window.fetch === wrapped) window.fetch = original;
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function consumeTabAdoptMarker() {
|
|
126
|
+
if (typeof window === "undefined") return false;
|
|
127
|
+
if (!window.location.hash.includes(TAB_ADOPT_HASH.slice(1))) return false;
|
|
128
|
+
clearTabSession();
|
|
129
|
+
try {
|
|
130
|
+
const url = new URL(window.location.href);
|
|
131
|
+
url.hash = "";
|
|
132
|
+
window.history.replaceState(window.history.state, "", url.toString());
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
52
137
|
var SessionContext = React3__namespace.createContext(null);
|
|
53
138
|
function normalizeDisplayIdentity(raw, didOc) {
|
|
54
139
|
const di = raw.display_identity ?? raw.displayIdentity;
|
|
@@ -75,7 +160,7 @@ async function fetchHostRoster(cfg) {
|
|
|
75
160
|
const res = await fetch(`${cfg.authOrigin}${cfg.mePath}`, {
|
|
76
161
|
method: "GET",
|
|
77
162
|
credentials: "include",
|
|
78
|
-
headers: { Accept: "application/json" }
|
|
163
|
+
headers: { Accept: "application/json", ...tabSessionHeader() }
|
|
79
164
|
});
|
|
80
165
|
if (!res.ok) return [];
|
|
81
166
|
const body = await res.json();
|
|
@@ -112,14 +197,50 @@ function OcSessionProvider({
|
|
|
112
197
|
const [roster, setRoster] = React3__namespace.useState([]);
|
|
113
198
|
const [status, setStatus] = React3__namespace.useState("loading");
|
|
114
199
|
const [error, setError] = React3__namespace.useState(null);
|
|
200
|
+
const [tabPinned, setTabPinned] = React3__namespace.useState(false);
|
|
201
|
+
const pinInFlightRef = React3__namespace.useRef(false);
|
|
202
|
+
const pinThisTab = React3__namespace.useCallback(
|
|
203
|
+
async (didOc) => {
|
|
204
|
+
if (pinInFlightRef.current || readTabSession()) return;
|
|
205
|
+
pinInFlightRef.current = true;
|
|
206
|
+
try {
|
|
207
|
+
const res = await fetch(`${cfg.authOrigin}/api/auth/tab`, {
|
|
208
|
+
method: "POST",
|
|
209
|
+
credentials: "include",
|
|
210
|
+
headers: { Accept: "application/json" }
|
|
211
|
+
});
|
|
212
|
+
if (!res.ok) return;
|
|
213
|
+
const body = await res.json();
|
|
214
|
+
if (body.ok && typeof body.token === "string" && body.account?.did_oc === didOc) {
|
|
215
|
+
writeTabSession({ token: body.token, didOc });
|
|
216
|
+
setTabPinned(true);
|
|
217
|
+
}
|
|
218
|
+
} catch {
|
|
219
|
+
} finally {
|
|
220
|
+
pinInFlightRef.current = false;
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
[cfg.authOrigin]
|
|
224
|
+
);
|
|
115
225
|
const refresh = React3__namespace.useCallback(async () => {
|
|
116
226
|
if (typeof window === "undefined") return;
|
|
117
227
|
try {
|
|
118
|
-
|
|
228
|
+
let pin = readTabSession();
|
|
229
|
+
let res = await fetch(cfg.mePath, {
|
|
119
230
|
method: "GET",
|
|
120
231
|
credentials: "include",
|
|
121
|
-
headers: { Accept: "application/json" }
|
|
232
|
+
headers: { Accept: "application/json", ...tabSessionHeader() }
|
|
122
233
|
});
|
|
234
|
+
if (res.status === 401 && pin) {
|
|
235
|
+
clearTabSession();
|
|
236
|
+
pin = null;
|
|
237
|
+
setTabPinned(false);
|
|
238
|
+
res = await fetch(cfg.mePath, {
|
|
239
|
+
method: "GET",
|
|
240
|
+
credentials: "include",
|
|
241
|
+
headers: { Accept: "application/json" }
|
|
242
|
+
});
|
|
243
|
+
}
|
|
123
244
|
if (res.status === 401) {
|
|
124
245
|
setAccount(null);
|
|
125
246
|
setRoster([]);
|
|
@@ -134,11 +255,17 @@ function OcSessionProvider({
|
|
|
134
255
|
}
|
|
135
256
|
const body = await res.json();
|
|
136
257
|
const acct = normalizeAccount(body.account);
|
|
258
|
+
if (acct && pin && acct.didOc !== pin.didOc) {
|
|
259
|
+
clearTabSession();
|
|
260
|
+
pin = null;
|
|
261
|
+
}
|
|
262
|
+
setTabPinned(pin !== null);
|
|
137
263
|
const rosterEntries = Array.isArray(body.roster) ? body.roster.map(normalizeRosterEntry).filter((r) => r !== null) : [];
|
|
138
264
|
setAccount(acct);
|
|
139
265
|
setRoster(rosterEntries);
|
|
140
266
|
setStatus(acct ? "authenticated" : "anonymous");
|
|
141
267
|
setError(null);
|
|
268
|
+
if (acct && !pin) void pinThisTab(acct.didOc);
|
|
142
269
|
const currentOrigin = typeof window !== "undefined" ? window.location.origin : null;
|
|
143
270
|
if (acct && rosterEntries.length === 0 && currentOrigin !== null && !cfg.authOrigin.startsWith(currentOrigin)) {
|
|
144
271
|
const peers = await fetchHostRoster(cfg);
|
|
@@ -148,10 +275,12 @@ function OcSessionProvider({
|
|
|
148
275
|
setStatus("error");
|
|
149
276
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
150
277
|
}
|
|
151
|
-
}, [cfg]);
|
|
278
|
+
}, [cfg, pinThisTab]);
|
|
152
279
|
React3__namespace.useEffect(() => {
|
|
280
|
+
consumeTabAdoptMarker();
|
|
153
281
|
void refresh();
|
|
154
282
|
}, [refresh]);
|
|
283
|
+
React3__namespace.useEffect(() => installTabFetchInterceptor(cfg.authOrigin), [cfg.authOrigin]);
|
|
155
284
|
const signOut = React3__namespace.useCallback(
|
|
156
285
|
async (opts) => {
|
|
157
286
|
const scope = opts?.scope ?? "all";
|
|
@@ -161,6 +290,10 @@ function OcSessionProvider({
|
|
|
161
290
|
const res = await fetch(url.toString(), {
|
|
162
291
|
method: "POST",
|
|
163
292
|
credentials: "include",
|
|
293
|
+
// Per-tab · carry the pin so scope='current' signs out
|
|
294
|
+
// the account THIS tab is operating as, not whichever
|
|
295
|
+
// account the shared cookie happens to point at.
|
|
296
|
+
headers: { ...tabSessionHeader() },
|
|
164
297
|
// `keepalive` lets the logout round-trip complete even if
|
|
165
298
|
// the caller hard-navigates away in the same tick (e.g.
|
|
166
299
|
// `<OcAccountMenu>` redirects home immediately on sign-out).
|
|
@@ -168,11 +301,15 @@ function OcSessionProvider({
|
|
|
168
301
|
// and the `.ochk.io` cookie may never get cleared.
|
|
169
302
|
keepalive: true
|
|
170
303
|
});
|
|
304
|
+
clearTabSession();
|
|
305
|
+
setTabPinned(false);
|
|
171
306
|
if (scope === "current" && res.ok) {
|
|
172
307
|
await refresh();
|
|
173
308
|
return;
|
|
174
309
|
}
|
|
175
310
|
} catch {
|
|
311
|
+
clearTabSession();
|
|
312
|
+
setTabPinned(false);
|
|
176
313
|
}
|
|
177
314
|
setAccount(null);
|
|
178
315
|
setRoster([]);
|
|
@@ -186,7 +323,7 @@ function OcSessionProvider({
|
|
|
186
323
|
const res = await fetch(`${cfg.authOrigin}/api/auth/switch`, {
|
|
187
324
|
method: "POST",
|
|
188
325
|
credentials: "include",
|
|
189
|
-
headers: { "Content-Type": "application/json" },
|
|
326
|
+
headers: { "Content-Type": "application/json", ...tabSessionHeader() },
|
|
190
327
|
body: JSON.stringify({ did_oc: didOc })
|
|
191
328
|
});
|
|
192
329
|
if (!res.ok) {
|
|
@@ -198,6 +335,14 @@ function OcSessionProvider({
|
|
|
198
335
|
}
|
|
199
336
|
throw new Error(`[@orangecheck/auth-client] switchAccount failed: ${reason}`);
|
|
200
337
|
}
|
|
338
|
+
try {
|
|
339
|
+
const body = await res.json();
|
|
340
|
+
if (typeof body.token === "string" && body.account?.did_oc) {
|
|
341
|
+
writeTabSession({ token: body.token, didOc: body.account.did_oc });
|
|
342
|
+
setTabPinned(true);
|
|
343
|
+
}
|
|
344
|
+
} catch {
|
|
345
|
+
}
|
|
201
346
|
await refresh();
|
|
202
347
|
},
|
|
203
348
|
[cfg.authOrigin, refresh]
|
|
@@ -215,7 +360,7 @@ function OcSessionProvider({
|
|
|
215
360
|
const res = await fetch(`${cfg.authOrigin}/api/auth/account`, {
|
|
216
361
|
method: "PATCH",
|
|
217
362
|
credentials: "include",
|
|
218
|
-
headers: { "Content-Type": "application/json" },
|
|
363
|
+
headers: { "Content-Type": "application/json", ...tabSessionHeader() },
|
|
219
364
|
body: JSON.stringify({ display_identity: kind })
|
|
220
365
|
});
|
|
221
366
|
if (!res.ok) {
|
|
@@ -227,6 +372,14 @@ function OcSessionProvider({
|
|
|
227
372
|
}
|
|
228
373
|
throw new Error(`[@orangecheck/auth-client] setDisplayIdentity failed: ${reason}`);
|
|
229
374
|
}
|
|
375
|
+
try {
|
|
376
|
+
const body = await res.json();
|
|
377
|
+
const pin = readTabSession();
|
|
378
|
+
if (pin && typeof body.token === "string" && body.account?.did_oc === pin.didOc) {
|
|
379
|
+
writeTabSession({ token: body.token, didOc: pin.didOc });
|
|
380
|
+
}
|
|
381
|
+
} catch {
|
|
382
|
+
}
|
|
230
383
|
await refresh();
|
|
231
384
|
},
|
|
232
385
|
[cfg.authOrigin, refresh]
|
|
@@ -237,6 +390,7 @@ function OcSessionProvider({
|
|
|
237
390
|
status,
|
|
238
391
|
account,
|
|
239
392
|
roster,
|
|
393
|
+
tabPinned,
|
|
240
394
|
error,
|
|
241
395
|
refresh,
|
|
242
396
|
signOut,
|
|
@@ -249,6 +403,7 @@ function OcSessionProvider({
|
|
|
249
403
|
status,
|
|
250
404
|
account,
|
|
251
405
|
roster,
|
|
406
|
+
tabPinned,
|
|
252
407
|
error,
|
|
253
408
|
refresh,
|
|
254
409
|
signOut,
|
|
@@ -1774,6 +1929,18 @@ function safeReturnTo(input) {
|
|
|
1774
1929
|
if (!candidate.startsWith("/") || candidate.startsWith("//")) return "/";
|
|
1775
1930
|
return candidate;
|
|
1776
1931
|
}
|
|
1932
|
+
function familyReturnTarget(input) {
|
|
1933
|
+
if (typeof input !== "string" || input.length === 0) return void 0;
|
|
1934
|
+
if (input.startsWith("/") && !input.startsWith("//")) return input;
|
|
1935
|
+
try {
|
|
1936
|
+
const u = new URL(input);
|
|
1937
|
+
if (u.protocol !== "https:") return void 0;
|
|
1938
|
+
const host = u.hostname.toLowerCase();
|
|
1939
|
+
if (host === "ochk.io" || host.endsWith(".ochk.io")) return u.toString();
|
|
1940
|
+
} catch {
|
|
1941
|
+
}
|
|
1942
|
+
return void 0;
|
|
1943
|
+
}
|
|
1777
1944
|
function hardNavigate(target) {
|
|
1778
1945
|
if (typeof window === "undefined") return;
|
|
1779
1946
|
window.location.assign(target);
|
|
@@ -1792,7 +1959,20 @@ function OcSignIn({
|
|
|
1792
1959
|
}) {
|
|
1793
1960
|
const walletEnabled = paths?.wallet ?? true;
|
|
1794
1961
|
const emailEnabled = paths?.email ?? true;
|
|
1795
|
-
const
|
|
1962
|
+
const [resolvedReturn, setResolvedReturn] = React3__namespace.useState(
|
|
1963
|
+
() => familyReturnTarget(returnTo) ?? safeReturnTo(returnTo)
|
|
1964
|
+
);
|
|
1965
|
+
React3__namespace.useEffect(() => {
|
|
1966
|
+
const fromProp = familyReturnTarget(returnTo);
|
|
1967
|
+
if (fromProp) {
|
|
1968
|
+
setResolvedReturn(fromProp);
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
if (typeof window === "undefined") return;
|
|
1972
|
+
const q = new URLSearchParams(window.location.search);
|
|
1973
|
+
const fromQuery = familyReturnTarget(q.get("return_to")) ?? familyReturnTarget(q.get("next"));
|
|
1974
|
+
setResolvedReturn(fromQuery ?? "/");
|
|
1975
|
+
}, [returnTo]);
|
|
1796
1976
|
const [addMode, setAddMode] = React3__namespace.useState(Boolean(addProp));
|
|
1797
1977
|
React3__namespace.useEffect(() => {
|
|
1798
1978
|
if (typeof window === "undefined") return;
|
|
@@ -1816,18 +1996,20 @@ function OcSignIn({
|
|
|
1816
1996
|
async (account) => {
|
|
1817
1997
|
if (resolveReturnTo) {
|
|
1818
1998
|
try {
|
|
1819
|
-
|
|
1999
|
+
const resolved = familyReturnTarget(await resolveReturnTo(account));
|
|
2000
|
+
hardNavigate(resolved ?? resolvedReturn);
|
|
1820
2001
|
return;
|
|
1821
2002
|
} catch {
|
|
1822
2003
|
}
|
|
1823
2004
|
}
|
|
1824
|
-
hardNavigate(
|
|
2005
|
+
hardNavigate(resolvedReturn);
|
|
1825
2006
|
},
|
|
1826
|
-
[resolveReturnTo,
|
|
2007
|
+
[resolveReturnTo, resolvedReturn]
|
|
1827
2008
|
);
|
|
1828
2009
|
const handleSuccess = React3__namespace.useCallback(
|
|
1829
2010
|
async (account, token, via) => {
|
|
1830
2011
|
const proceed = () => {
|
|
2012
|
+
clearTabSession();
|
|
1831
2013
|
if (onSuccess) onSuccess(account, token);
|
|
1832
2014
|
else void navigate(account);
|
|
1833
2015
|
};
|
|
@@ -1992,7 +2174,7 @@ function OcSignIn({
|
|
|
1992
2174
|
}
|
|
1993
2175
|
)
|
|
1994
2176
|
] }),
|
|
1995
|
-
/* @__PURE__ */ jsxRuntime.jsx(ProviderSignIn, { authOrigin, returnTo:
|
|
2177
|
+
/* @__PURE__ */ jsxRuntime.jsx(ProviderSignIn, { authOrigin, returnTo: resolvedReturn, add: addMode }),
|
|
1996
2178
|
linkPrompt && /* @__PURE__ */ jsxRuntime.jsxs("label", { "data-oc-signin-linkalso": "", style: linkAlsoStyle, children: [
|
|
1997
2179
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1998
2180
|
"input",
|
|
@@ -2062,7 +2244,8 @@ function ProviderIcon({ id }) {
|
|
|
2062
2244
|
}
|
|
2063
2245
|
function ProviderSignIn({
|
|
2064
2246
|
authOrigin,
|
|
2065
|
-
returnTo
|
|
2247
|
+
returnTo,
|
|
2248
|
+
add
|
|
2066
2249
|
}) {
|
|
2067
2250
|
const [providers, setProviders] = React3__namespace.useState([]);
|
|
2068
2251
|
const [origin, setOrigin] = React3__namespace.useState("");
|
|
@@ -2078,7 +2261,7 @@ function ProviderSignIn({
|
|
|
2078
2261
|
};
|
|
2079
2262
|
}, [authOrigin]);
|
|
2080
2263
|
if (providers.length === 0) return null;
|
|
2081
|
-
const providerReturnTo = origin ? `${origin}${returnTo}` : returnTo;
|
|
2264
|
+
const providerReturnTo = returnTo.startsWith("/") ? origin ? `${origin}${returnTo}` : returnTo : returnTo;
|
|
2082
2265
|
const line = { flex: 1, height: 1, background: "var(--border, #27272a)" };
|
|
2083
2266
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-oc-signin-providers": "", style: { marginTop: 20 }, children: [
|
|
2084
2267
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2107,7 +2290,7 @@ function ProviderSignIn({
|
|
|
2107
2290
|
{
|
|
2108
2291
|
href: `${authOrigin}/api/auth/${p.id}/start?return_to=${encodeURIComponent(
|
|
2109
2292
|
providerReturnTo
|
|
2110
|
-
)}`,
|
|
2293
|
+
)}${add ? "&add=1" : ""}`,
|
|
2111
2294
|
"data-oc-signin-provider": p.id,
|
|
2112
2295
|
style: {
|
|
2113
2296
|
display: "flex",
|
|
@@ -2797,16 +2980,25 @@ exports.OcLinkedIdentities = OcLinkedIdentities;
|
|
|
2797
2980
|
exports.OcSessionProvider = OcSessionProvider;
|
|
2798
2981
|
exports.OcSignIn = OcSignIn;
|
|
2799
2982
|
exports.OcSignInButton = OcSignInButton;
|
|
2983
|
+
exports.TAB_ADOPT_HASH = TAB_ADOPT_HASH;
|
|
2984
|
+
exports.TAB_SESSION_HEADER = TAB_SESSION_HEADER;
|
|
2985
|
+
exports.TAB_SESSION_STORAGE_KEY = TAB_SESSION_STORAGE_KEY;
|
|
2800
2986
|
exports.buildAddAccountUrl = buildAddAccountUrl;
|
|
2801
2987
|
exports.buildSignInUrl = buildSignInUrl;
|
|
2988
|
+
exports.clearTabSession = clearTabSession;
|
|
2989
|
+
exports.consumeTabAdoptMarker = consumeTabAdoptMarker;
|
|
2802
2990
|
exports.fetchOcLinkedIdentities = fetchOcLinkedIdentities;
|
|
2803
2991
|
exports.handleSudoRequired = handleSudoRequired;
|
|
2992
|
+
exports.installTabFetchInterceptor = installTabFetchInterceptor;
|
|
2993
|
+
exports.readTabSession = readTabSession;
|
|
2804
2994
|
exports.redirectToSudo = redirectToSudo;
|
|
2995
|
+
exports.tabSessionHeader = tabSessionHeader;
|
|
2805
2996
|
exports.useOcAddressSuggestion = useOcAddressSuggestion;
|
|
2806
2997
|
exports.useOcSession = useOcSession;
|
|
2807
2998
|
exports.useOptionalOcSession = useOptionalOcSession;
|
|
2808
2999
|
exports.useStepUpAuth = useStepUpAuth;
|
|
2809
3000
|
exports.useWebAuthnList = useWebAuthnList;
|
|
2810
3001
|
exports.useWebAuthnRegister = useWebAuthnRegister;
|
|
3002
|
+
exports.writeTabSession = writeTabSession;
|
|
2811
3003
|
//# sourceMappingURL=index.js.map
|
|
2812
3004
|
//# sourceMappingURL=index.js.map
|