@bounded-sh/client 0.0.111 → 0.0.112-ux-audit.2
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/auth/index.d.ts +3 -1
- package/dist/auth/oidc-auth.d.ts +3 -1
- package/dist/auth/providers/email-auth-provider.d.ts +1 -1
- package/dist/auth/providers/guest-auth-provider.d.ts +1 -1
- package/dist/auth/providers/injected-evm-wallet-provider.d.ts +1 -1
- package/dist/auth/providers/injected-wallet-provider.d.ts +1 -1
- package/dist/auth/providers/offchain-auth-provider.d.ts +1 -1
- package/dist/auth/providers/privy-expo-provider.d.ts +1 -1
- package/dist/{email-auth-provider-DxS2WYxM.js → email-auth-provider-53sA5_i2.js} +4 -3
- package/dist/email-auth-provider-53sA5_i2.js.map +1 -0
- package/dist/{email-auth-provider-CVp6hSCo.mjs → email-auth-provider-BfCH7K6N.mjs} +4 -3
- package/dist/email-auth-provider-BfCH7K6N.mjs.map +1 -0
- package/dist/{email-auth-provider-BfBvF_4M.mjs → email-auth-provider-C7RXLVd9.mjs} +4 -3
- package/dist/email-auth-provider-C7RXLVd9.mjs.map +1 -0
- package/dist/{email-auth-provider-CiqhQ1c2.js → email-auth-provider-DTrCfOJd.js} +4 -3
- package/dist/email-auth-provider-DTrCfOJd.js.map +1 -0
- package/dist/{guest-auth-provider-DDBXeHoo.js → guest-auth-provider-00KkSNpE.js} +10 -5
- package/dist/guest-auth-provider-00KkSNpE.js.map +1 -0
- package/dist/{guest-auth-provider-Bm_yqQF6.mjs → guest-auth-provider-2J4fnTX5.mjs} +10 -5
- package/dist/guest-auth-provider-2J4fnTX5.mjs.map +1 -0
- package/dist/{guest-auth-provider-Cc8y4Qd1.mjs → guest-auth-provider-DjOFjtnk.mjs} +10 -5
- package/dist/guest-auth-provider-DjOFjtnk.mjs.map +1 -0
- package/dist/{guest-auth-provider-D9FGNuP9.js → guest-auth-provider-Tndt6tzJ.js} +10 -5
- package/dist/guest-auth-provider-Tndt6tzJ.js.map +1 -0
- package/dist/{index-B9__gwTi.mjs → index-D3kdhCpH.mjs} +313 -84
- package/dist/index-D3kdhCpH.mjs.map +1 -0
- package/dist/{index-BghQ8jX0.js → index-DJeEMevo.js} +312 -83
- package/dist/index-DJeEMevo.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{index.native-BHjpXkKQ.mjs → index.native-CAH_ks0s.mjs} +200 -56
- package/dist/index.native-CAH_ks0s.mjs.map +1 -0
- package/dist/{index.native-B_AFa0GD.js → index.native-ingNhWPw.js} +199 -55
- package/dist/index.native-ingNhWPw.js.map +1 -0
- package/dist/index.native.js +1 -1
- package/dist/index.native.mjs +1 -1
- package/dist/{injected-evm-wallet-provider-CIeCSOPL.mjs → injected-evm-wallet-provider-BtyG1HOX.mjs} +4 -3
- package/dist/injected-evm-wallet-provider-BtyG1HOX.mjs.map +1 -0
- package/dist/{injected-evm-wallet-provider-DeLUwvGs.js → injected-evm-wallet-provider-Cao1U0NZ.js} +4 -3
- package/dist/{injected-evm-wallet-provider-DeLUwvGs.js.map → injected-evm-wallet-provider-Cao1U0NZ.js.map} +1 -1
- package/dist/{injected-evm-wallet-provider-BUjqxQxp.mjs → injected-evm-wallet-provider-DXjwPjLW.mjs} +4 -3
- package/dist/{injected-evm-wallet-provider-BUjqxQxp.mjs.map → injected-evm-wallet-provider-DXjwPjLW.mjs.map} +1 -1
- package/dist/{injected-evm-wallet-provider-Ckb85p6a.js → injected-evm-wallet-provider-IlkuKffc.js} +4 -3
- package/dist/injected-evm-wallet-provider-IlkuKffc.js.map +1 -0
- package/dist/{injected-wallet-provider-BlzA0J_V.mjs → injected-wallet-provider-0SSONh1d.mjs} +4 -3
- package/dist/{injected-wallet-provider-BlzA0J_V.mjs.map → injected-wallet-provider-0SSONh1d.mjs.map} +1 -1
- package/dist/{injected-wallet-provider-Cfb4ayCP.js → injected-wallet-provider-BEYwsn6M.js} +4 -3
- package/dist/{injected-wallet-provider-Cfb4ayCP.js.map → injected-wallet-provider-BEYwsn6M.js.map} +1 -1
- package/dist/{injected-wallet-provider-BEuj4sM3.mjs → injected-wallet-provider-CfYNIIHd.mjs} +4 -3
- package/dist/{injected-wallet-provider-BEuj4sM3.mjs.map → injected-wallet-provider-CfYNIIHd.mjs.map} +1 -1
- package/dist/{injected-wallet-provider-CUKdAuFu.js → injected-wallet-provider-DSlHfgMU.js} +4 -3
- package/dist/{injected-wallet-provider-CUKdAuFu.js.map → injected-wallet-provider-DSlHfgMU.js.map} +1 -1
- package/package.json +2 -2
- package/dist/email-auth-provider-BfBvF_4M.mjs.map +0 -1
- package/dist/email-auth-provider-CVp6hSCo.mjs.map +0 -1
- package/dist/email-auth-provider-CiqhQ1c2.js.map +0 -1
- package/dist/email-auth-provider-DxS2WYxM.js.map +0 -1
- package/dist/guest-auth-provider-Bm_yqQF6.mjs.map +0 -1
- package/dist/guest-auth-provider-Cc8y4Qd1.mjs.map +0 -1
- package/dist/guest-auth-provider-D9FGNuP9.js.map +0 -1
- package/dist/guest-auth-provider-DDBXeHoo.js.map +0 -1
- package/dist/index-B9__gwTi.mjs.map +0 -1
- package/dist/index-BghQ8jX0.js.map +0 -1
- package/dist/index.native-BHjpXkKQ.mjs.map +0 -1
- package/dist/index.native-B_AFa0GD.js.map +0 -1
- package/dist/injected-evm-wallet-provider-CIeCSOPL.mjs.map +0 -1
- package/dist/injected-evm-wallet-provider-Ckb85p6a.js.map +0 -1
|
@@ -236,8 +236,9 @@ class OffchainAuthProvider {
|
|
|
236
236
|
async logout() {
|
|
237
237
|
await this.wrappedProvider.logout();
|
|
238
238
|
}
|
|
239
|
-
async restoreSession() {
|
|
240
|
-
const
|
|
239
|
+
async restoreSession(beforeCommit) {
|
|
240
|
+
const provider = this.wrappedProvider;
|
|
241
|
+
const user = await provider.restoreSession(beforeCommit);
|
|
241
242
|
if (user) {
|
|
242
243
|
return Object.assign(Object.assign({}, user), { provider: this });
|
|
243
244
|
}
|
|
@@ -5297,7 +5298,8 @@ async function loginWithRedirect(opts) {
|
|
|
5297
5298
|
return runNativeLogin(opts);
|
|
5298
5299
|
if (!hasDOM$1())
|
|
5299
5300
|
throw new Error('loginWithRedirect requires a browser or a configured React Native platform');
|
|
5300
|
-
const { url, pkce } = await buildAuthorize(opts);
|
|
5301
|
+
const { url, pkce } = await untilAborted(buildAuthorize(opts), opts.signal);
|
|
5302
|
+
throwIfCancelled(opts.signal);
|
|
5301
5303
|
// Stash the verifier + state so the redirect_uri page can finish the exchange. sessionStorage
|
|
5302
5304
|
// is per-tab and cleared on close — appropriate for a short-lived auth handshake. Keyed by
|
|
5303
5305
|
// this attempt's own state so a second concurrent login cannot overwrite it.
|
|
@@ -5326,9 +5328,29 @@ async function completeLoginFromRedirect() {
|
|
|
5326
5328
|
throw error;
|
|
5327
5329
|
return result.user;
|
|
5328
5330
|
}
|
|
5331
|
+
function throwIfCancelled(signal) {
|
|
5332
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted)
|
|
5333
|
+
throw new Error('cancelled');
|
|
5334
|
+
}
|
|
5335
|
+
async function untilAborted(work, signal) {
|
|
5336
|
+
if (!signal)
|
|
5337
|
+
return work;
|
|
5338
|
+
throwIfCancelled(signal);
|
|
5339
|
+
let onAbort;
|
|
5340
|
+
try {
|
|
5341
|
+
return await Promise.race([work, new Promise((_, reject) => {
|
|
5342
|
+
onAbort = () => reject(new Error('cancelled'));
|
|
5343
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
5344
|
+
})]);
|
|
5345
|
+
}
|
|
5346
|
+
finally {
|
|
5347
|
+
signal.removeEventListener('abort', onAbort);
|
|
5348
|
+
}
|
|
5349
|
+
}
|
|
5329
5350
|
/** Popup variant: open the hosted login in a popup; resolves with the User once the popup's
|
|
5330
5351
|
* redirect_uri page initializes the SDK, which hands the code back automatically. */
|
|
5331
5352
|
async function loginWithPopup(opts) {
|
|
5353
|
+
throwIfCancelled(opts.signal);
|
|
5332
5354
|
if (!hasDOM$1())
|
|
5333
5355
|
throw new Error('loginWithPopup is web-only — on React Native use loginWithRedirect()');
|
|
5334
5356
|
// Open synchronously, before PKCE/config awaits consume the click's user-
|
|
@@ -5346,7 +5368,7 @@ async function loginWithPopup(opts) {
|
|
|
5346
5368
|
throw new Error('Popup blocked — use loginWithRedirect() instead');
|
|
5347
5369
|
let authorization;
|
|
5348
5370
|
try {
|
|
5349
|
-
authorization = await buildAuthorize(opts, 'popup');
|
|
5371
|
+
authorization = await untilAborted(buildAuthorize(opts, 'popup'), opts.signal);
|
|
5350
5372
|
}
|
|
5351
5373
|
catch (error) {
|
|
5352
5374
|
try {
|
|
@@ -5363,6 +5385,7 @@ async function loginWithPopup(opts) {
|
|
|
5363
5385
|
// window with no listener or watchdog attached.
|
|
5364
5386
|
let expectedOrigin;
|
|
5365
5387
|
try {
|
|
5388
|
+
throwIfCancelled(opts.signal);
|
|
5366
5389
|
expectedOrigin = new URL(pkce.redirectUri).origin;
|
|
5367
5390
|
sessionStorage.setItem(pkceKey(pkce.state), JSON.stringify(pkce));
|
|
5368
5391
|
}
|
|
@@ -5394,20 +5417,42 @@ async function loginWithPopup(opts) {
|
|
|
5394
5417
|
setAuthLoading(true); // reflect "signing in…" while the popup is open
|
|
5395
5418
|
try {
|
|
5396
5419
|
return await new Promise((resolve, reject) => {
|
|
5420
|
+
var _a, _b;
|
|
5397
5421
|
let settled = false;
|
|
5422
|
+
let handedOff = false;
|
|
5423
|
+
let committing = false;
|
|
5398
5424
|
let timer;
|
|
5399
5425
|
let navigationTimer;
|
|
5400
5426
|
let completionTimer;
|
|
5401
5427
|
const cleanup = () => {
|
|
5402
|
-
settled = true;
|
|
5403
5428
|
clearInterval(timer);
|
|
5404
5429
|
clearTimeout(navigationTimer);
|
|
5405
5430
|
clearTimeout(completionTimer);
|
|
5406
5431
|
window.removeEventListener('message', onMsg);
|
|
5407
5432
|
removeAttempt(pkce.state);
|
|
5408
5433
|
};
|
|
5434
|
+
const finish = (error, user) => {
|
|
5435
|
+
var _a;
|
|
5436
|
+
if (settled)
|
|
5437
|
+
return;
|
|
5438
|
+
settled = true;
|
|
5439
|
+
cleanup();
|
|
5440
|
+
(_a = opts.signal) === null || _a === void 0 ? void 0 : _a.removeEventListener('abort', onAbort);
|
|
5441
|
+
try {
|
|
5442
|
+
popup.close();
|
|
5443
|
+
}
|
|
5444
|
+
catch ( /* ignore */_b) { /* ignore */ }
|
|
5445
|
+
if (error)
|
|
5446
|
+
reject(error);
|
|
5447
|
+
else
|
|
5448
|
+
resolve(user);
|
|
5449
|
+
};
|
|
5450
|
+
// Provider adoption commits synchronously after its final guard. An auth
|
|
5451
|
+
// listener dismissing the card there cannot cancel an already signed-in user.
|
|
5452
|
+
const onAbort = () => { if (!committing)
|
|
5453
|
+
finish(new Error('cancelled')); };
|
|
5409
5454
|
const onMsg = async (ev) => {
|
|
5410
|
-
if (settled || ev.origin !== expectedOrigin || ev.source !== popup)
|
|
5455
|
+
if (settled || handedOff || ev.origin !== expectedOrigin || ev.source !== popup)
|
|
5411
5456
|
return;
|
|
5412
5457
|
const d = ev.data;
|
|
5413
5458
|
if (!d || d.type !== 'bounded-oidc-code' ||
|
|
@@ -5421,35 +5466,30 @@ async function loginWithPopup(opts) {
|
|
|
5421
5466
|
return;
|
|
5422
5467
|
if (d.appId !== pkce.appId || d.issuer !== pkce.issuer)
|
|
5423
5468
|
return;
|
|
5469
|
+
handedOff = true;
|
|
5424
5470
|
cleanup();
|
|
5425
5471
|
try {
|
|
5472
|
+
throwIfCancelled(opts.signal);
|
|
5426
5473
|
await validateAttempt(pkce, new URL(d.callbackUrl));
|
|
5474
|
+
throwIfCancelled(opts.signal);
|
|
5427
5475
|
popup.postMessage({ type: 'bounded-oidc-accepted', state: pkce.state }, expectedOrigin);
|
|
5428
5476
|
if (d.error)
|
|
5429
5477
|
throw new Error(typeof d.errorDescription === 'string' ? d.errorDescription : `Login failed: ${d.error}`);
|
|
5430
|
-
const user = await exchangeCode(d.code, pkce);
|
|
5431
|
-
|
|
5432
|
-
popup.close();
|
|
5433
|
-
}
|
|
5434
|
-
catch ( /* ignore */_a) { /* ignore */ }
|
|
5435
|
-
resolve(user);
|
|
5478
|
+
const user = await exchangeCode(d.code, pkce, opts.signal, () => { committing = true; });
|
|
5479
|
+
finish(undefined, user);
|
|
5436
5480
|
}
|
|
5437
5481
|
catch (e) {
|
|
5438
|
-
|
|
5439
|
-
popup.close();
|
|
5440
|
-
}
|
|
5441
|
-
catch ( /* ignore */_b) { /* ignore */ }
|
|
5442
|
-
reject(e);
|
|
5482
|
+
finish(e);
|
|
5443
5483
|
}
|
|
5444
5484
|
};
|
|
5485
|
+
(_a = opts.signal) === null || _a === void 0 ? void 0 : _a.addEventListener('abort', onAbort, { once: true });
|
|
5486
|
+
if ((_b = opts.signal) === null || _b === void 0 ? void 0 : _b.aborted) {
|
|
5487
|
+
onAbort();
|
|
5488
|
+
return;
|
|
5489
|
+
}
|
|
5445
5490
|
window.addEventListener('message', onMsg);
|
|
5446
5491
|
completionTimer = setTimeout(() => {
|
|
5447
|
-
|
|
5448
|
-
try {
|
|
5449
|
-
popup.close();
|
|
5450
|
-
}
|
|
5451
|
-
catch ( /* ignore */_a) { /* ignore */ }
|
|
5452
|
-
reject(new Error('Login expired or its popup disconnected. Start sign-in again.'));
|
|
5492
|
+
finish(new Error('Login expired or its popup disconnected. Start sign-in again.'));
|
|
5453
5493
|
}, LOGIN_TIMEOUT_MS);
|
|
5454
5494
|
// Some browser/extension combinations can return a real popup handle but
|
|
5455
5495
|
// strand the window at about:blank instead of navigating to the hosted
|
|
@@ -5470,23 +5510,18 @@ async function loginWithPopup(opts) {
|
|
|
5470
5510
|
const NAVIGATION_RECHECK_MS = 2000;
|
|
5471
5511
|
const navigationStartedAt = Date.now();
|
|
5472
5512
|
const checkNavigation = () => {
|
|
5473
|
-
if (settled || popup.closed)
|
|
5513
|
+
if (settled || handedOff || popup.closed)
|
|
5474
5514
|
return;
|
|
5475
5515
|
try {
|
|
5476
5516
|
if (popup.location.href === 'about:blank') {
|
|
5477
5517
|
if (Date.now() - navigationStartedAt >= NAVIGATION_GRACE_MS) {
|
|
5478
|
-
|
|
5479
|
-
try {
|
|
5480
|
-
popup.close();
|
|
5481
|
-
}
|
|
5482
|
-
catch ( /* ignore */_a) { /* ignore */ }
|
|
5483
|
-
reject(new Error('Popup stalled at about:blank - use loginWithRedirect() instead'));
|
|
5518
|
+
finish(new Error('Popup stalled at about:blank - use loginWithRedirect() instead'));
|
|
5484
5519
|
return;
|
|
5485
5520
|
}
|
|
5486
5521
|
navigationTimer = setTimeout(checkNavigation, NAVIGATION_RECHECK_MS);
|
|
5487
5522
|
}
|
|
5488
5523
|
}
|
|
5489
|
-
catch ( /* cross-origin hosted auth loaded normally */
|
|
5524
|
+
catch ( /* cross-origin hosted auth loaded normally */_a) { /* cross-origin hosted auth loaded normally */ }
|
|
5490
5525
|
};
|
|
5491
5526
|
navigationTimer = setTimeout(checkNavigation, NAVIGATION_RECHECK_MS);
|
|
5492
5527
|
// The popup posts its code and then closes ITSELF, so a naive "popup.closed -> reject"
|
|
@@ -5496,10 +5531,8 @@ async function loginWithPopup(opts) {
|
|
|
5496
5531
|
timer = setInterval(() => {
|
|
5497
5532
|
if (popup.closed) {
|
|
5498
5533
|
clearInterval(timer);
|
|
5499
|
-
setTimeout(() => { if (!settled)
|
|
5500
|
-
|
|
5501
|
-
reject(new Error('Login window closed'));
|
|
5502
|
-
} }, 500);
|
|
5534
|
+
setTimeout(() => { if (!settled && !handedOff)
|
|
5535
|
+
finish(new Error('Login window closed')); }, 500);
|
|
5503
5536
|
}
|
|
5504
5537
|
}, 500);
|
|
5505
5538
|
});
|
|
@@ -5508,9 +5541,10 @@ async function loginWithPopup(opts) {
|
|
|
5508
5541
|
setAuthLoading(false);
|
|
5509
5542
|
}
|
|
5510
5543
|
}
|
|
5511
|
-
async function exchangeCode(code, pkce) {
|
|
5544
|
+
async function exchangeCode(code, pkce, signal, onCommitting) {
|
|
5512
5545
|
const generation = getInitializationGeneration();
|
|
5513
5546
|
const beforeCommit = () => {
|
|
5547
|
+
throwIfCancelled(signal);
|
|
5514
5548
|
if (generation !== getInitializationGeneration())
|
|
5515
5549
|
throw new Error('Login was superseded by SDK reinitialization. Start sign-in again.');
|
|
5516
5550
|
};
|
|
@@ -5526,7 +5560,7 @@ async function exchangeCode(code, pkce) {
|
|
|
5526
5560
|
let res;
|
|
5527
5561
|
try {
|
|
5528
5562
|
res = await fetch(`${base}/api/auth/oauth2/token`, {
|
|
5529
|
-
method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, body: body.toString(),
|
|
5563
|
+
method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, body: body.toString(), signal,
|
|
5530
5564
|
});
|
|
5531
5565
|
}
|
|
5532
5566
|
catch (err) {
|
|
@@ -5552,7 +5586,7 @@ async function exchangeCode(code, pkce) {
|
|
|
5552
5586
|
// Adopt on EVERY session surface (see establishInlineSession) - hosted
|
|
5553
5587
|
// popup/redirect completions all land here, so this closes their gap too.
|
|
5554
5588
|
try {
|
|
5555
|
-
await adoptSessionProvider({ provider: oidcProviderSingleton, method: 'email', configKey: 'direct:oidc', user, beforeCommit });
|
|
5589
|
+
await adoptSessionProvider({ provider: oidcProviderSingleton, method: 'email', configKey: 'direct:oidc', user, beforeCommit: () => { beforeCommit(); onCommitting === null || onCommitting === void 0 ? void 0 : onCommitting(); } });
|
|
5556
5590
|
}
|
|
5557
5591
|
catch (error) {
|
|
5558
5592
|
if (typeof rollback === 'function')
|
|
@@ -5621,6 +5655,31 @@ function idTokenIsGuest(idToken, expectedAddress) {
|
|
|
5621
5655
|
function storedSessionIsGuest() {
|
|
5622
5656
|
return idTokenIsGuest(getStoredIdToken());
|
|
5623
5657
|
}
|
|
5658
|
+
/** Internal: select a cross-tab restore from bearer claims, never global hints. */
|
|
5659
|
+
function storedSessionAuthMethod(config) {
|
|
5660
|
+
try {
|
|
5661
|
+
const token = getStoredIdToken();
|
|
5662
|
+
if (!token)
|
|
5663
|
+
return null;
|
|
5664
|
+
let payload = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
5665
|
+
payload += '='.repeat((4 - payload.length % 4) % 4);
|
|
5666
|
+
const claims = JSON.parse(getPlatform().atob(payload));
|
|
5667
|
+
const method = claims.is_anonymous === true ? 'guest'
|
|
5668
|
+
: claims['custom:walletProvider'] === 'turnkey' || claims.email ? 'email'
|
|
5669
|
+
: claims['custom:evmWalletAddress'] ? 'evm-wallet'
|
|
5670
|
+
: claims['custom:walletAddress'] ? 'phantom' : 'email';
|
|
5671
|
+
if (config.authMethod != null && canonicalWalletAuthMethod(config.authMethod) !== method)
|
|
5672
|
+
return null;
|
|
5673
|
+
if (method === 'evm-wallet' && config.authMethod !== 'evm-wallet')
|
|
5674
|
+
return null;
|
|
5675
|
+
if (method === 'phantom' && (isWalletLoginDisabled(config) || isEmailRequired(config)))
|
|
5676
|
+
return null;
|
|
5677
|
+
return method;
|
|
5678
|
+
}
|
|
5679
|
+
catch (_a) {
|
|
5680
|
+
return null;
|
|
5681
|
+
}
|
|
5682
|
+
}
|
|
5624
5683
|
/**
|
|
5625
5684
|
* Pick the provider used for an ordinary `init({ appId })` restore.
|
|
5626
5685
|
*
|
|
@@ -5867,9 +5926,10 @@ function optionalProviderError(method) {
|
|
|
5867
5926
|
`loginWithRedirect(...) for Bounded Auth, signInAnonymously() for guests, ` +
|
|
5868
5927
|
`or install/import an explicit wallet-provider entry once your app opts into "${method}".`);
|
|
5869
5928
|
}
|
|
5870
|
-
async function getAuthProvider(config) {
|
|
5929
|
+
async function getAuthProvider(config, fromStorage = false) {
|
|
5871
5930
|
var _a;
|
|
5872
|
-
const
|
|
5931
|
+
const requestedAuthMethod = config ? (fromStorage ? storedSessionAuthMethod(config) : authMethodForInit(config)) : null;
|
|
5932
|
+
const nextProviderConfigKey = config ? authProviderConfigKey(Object.assign(Object.assign({}, config), { authMethod: requestedAuthMethod })) : null;
|
|
5873
5933
|
if (currentAuthProvider && (!config || currentAuthProviderConfigKey === nextProviderConfigKey)) {
|
|
5874
5934
|
return currentAuthProvider;
|
|
5875
5935
|
}
|
|
@@ -5884,7 +5944,8 @@ async function getAuthProvider(config) {
|
|
|
5884
5944
|
initConfig = config;
|
|
5885
5945
|
// Keep what the app actually wrote for error text; everything else runs on
|
|
5886
5946
|
// the canonical method so exactly one string reaches storage and the issuer.
|
|
5887
|
-
|
|
5947
|
+
if (!requestedAuthMethod)
|
|
5948
|
+
throw new Error('The stored session is incompatible with this app authentication configuration.');
|
|
5888
5949
|
const authMethod = canonicalWalletAuthMethod(requestedAuthMethod);
|
|
5889
5950
|
const rpcUrl = normalizeSolanaRpcUrl(config.rpcUrl);
|
|
5890
5951
|
const configuredNetwork = getConfiguredSolanaNetwork(config);
|
|
@@ -5909,7 +5970,7 @@ async function getAuthProvider(config) {
|
|
|
5909
5970
|
// manager as legacy email sessions. Human login should be started
|
|
5910
5971
|
// with loginWithRedirect(); this provider is kept as the restore and
|
|
5911
5972
|
// logout surface for those sessions.
|
|
5912
|
-
currentAuthProvider = new (await Promise.resolve().then(function () { return require('./email-auth-provider-
|
|
5973
|
+
currentAuthProvider = new (await Promise.resolve().then(function () { return require('./email-auth-provider-DTrCfOJd.js'); })).EmailAuthProvider();
|
|
5913
5974
|
break;
|
|
5914
5975
|
case "phantom": {
|
|
5915
5976
|
// First-class Solana WALLET LOGIN (the poof/TaroBase-style "connect
|
|
@@ -5951,7 +6012,7 @@ async function getAuthProvider(config) {
|
|
|
5951
6012
|
// (bounded-login-widget.ts), so registration never counts as
|
|
5952
6013
|
// evidence the user has a wallet.
|
|
5953
6014
|
await ensureSolanaMobileWalletRegistered(config, configuredNetwork);
|
|
5954
|
-
const { InjectedWalletProvider } = await Promise.resolve().then(function () { return require('./injected-wallet-provider-
|
|
6015
|
+
const { InjectedWalletProvider } = await Promise.resolve().then(function () { return require('./injected-wallet-provider-DSlHfgMU.js'); });
|
|
5955
6016
|
currentAuthProvider = new InjectedWalletProvider(resolveInjectedWalletConfig(config), rpcUrl, configuredNetwork);
|
|
5956
6017
|
break;
|
|
5957
6018
|
}
|
|
@@ -5964,7 +6025,7 @@ async function getAuthProvider(config) {
|
|
|
5964
6025
|
// Selecting authMethod:'evm-wallet' IS the opt-in — pass evmWalletConfig
|
|
5965
6026
|
// to point at a specific wallet or set chainId/domain.
|
|
5966
6027
|
const evmWalletConfig = ((_a = config.evmWalletConfig) !== null && _a !== void 0 ? _a : {});
|
|
5967
|
-
const { InjectedEvmWalletProvider } = await Promise.resolve().then(function () { return require('./injected-evm-wallet-provider-
|
|
6028
|
+
const { InjectedEvmWalletProvider } = await Promise.resolve().then(function () { return require('./injected-evm-wallet-provider-Cao1U0NZ.js'); });
|
|
5968
6029
|
currentAuthProvider = new InjectedEvmWalletProvider(evmWalletConfig);
|
|
5969
6030
|
break;
|
|
5970
6031
|
}
|
|
@@ -5989,7 +6050,7 @@ async function getAuthProvider(config) {
|
|
|
5989
6050
|
break;
|
|
5990
6051
|
case "guest":
|
|
5991
6052
|
// Anonymous auth: a device-local ed25519 keypair signs the challenge.
|
|
5992
|
-
currentAuthProvider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-
|
|
6053
|
+
currentAuthProvider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-Tndt6tzJ.js'); })).GuestAuthProvider();
|
|
5993
6054
|
break;
|
|
5994
6055
|
}
|
|
5995
6056
|
if (!currentAuthProvider) {
|
|
@@ -6051,7 +6112,7 @@ async function signInAnonymously() {
|
|
|
6051
6112
|
// Lazy-load the guest provider so its ed25519/web3 dependencies stay out of
|
|
6052
6113
|
// the main bundle for data-only apps. Specifier is a static string literal
|
|
6053
6114
|
// so bundle-splitting can see it.
|
|
6054
|
-
const provider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-
|
|
6115
|
+
const provider = new (await Promise.resolve().then(function () { return require('./guest-auth-provider-Tndt6tzJ.js'); })).GuestAuthProvider();
|
|
6055
6116
|
setAuthLoading(true); // reflect "signing in…" while the guest keypair session is minted
|
|
6056
6117
|
// adoptSessionProvider awaits only getConfig() (already resolved here) and then
|
|
6057
6118
|
// runs every write - provider/method/config/marker/user - in one synchronous
|
|
@@ -6222,7 +6283,7 @@ function ensureSharedWalletLoginReady() {
|
|
|
6222
6283
|
if (!sharedWalletReady) {
|
|
6223
6284
|
sharedWalletReady = (async () => {
|
|
6224
6285
|
await core.getConfig();
|
|
6225
|
-
await Promise.resolve().then(function () { return require('./injected-wallet-provider-
|
|
6286
|
+
await Promise.resolve().then(function () { return require('./injected-wallet-provider-DSlHfgMU.js'); });
|
|
6226
6287
|
})().catch((error) => {
|
|
6227
6288
|
sharedWalletReady = null;
|
|
6228
6289
|
throw error;
|
|
@@ -6518,12 +6579,80 @@ let isAuthLoading = false;
|
|
|
6518
6579
|
let authReadyPromise = null;
|
|
6519
6580
|
let initializingConfig = null;
|
|
6520
6581
|
let initializationGeneration = 0;
|
|
6582
|
+
let initializedConfig = null;
|
|
6583
|
+
let storageBridgeRegistered = false;
|
|
6584
|
+
let observedIdToken = null;
|
|
6585
|
+
let observedIssuer = null;
|
|
6586
|
+
// Storage events carry no authority. Re-read the active manager's app/issuer
|
|
6587
|
+
// namespace, then use the ordinary initializer/provider restore and listeners.
|
|
6588
|
+
function registerStorageBridge() {
|
|
6589
|
+
if (storageBridgeRegistered || !getPlatform().hasDOM || typeof window === 'undefined')
|
|
6590
|
+
return;
|
|
6591
|
+
storageBridgeRegistered = true;
|
|
6592
|
+
window.addEventListener('storage', (event) => {
|
|
6593
|
+
if (event.storageArea !== window.localStorage || !initializedConfig)
|
|
6594
|
+
return;
|
|
6595
|
+
void syncStoredSession().catch((error) => console.warn('Bounded session synchronization failed:', error));
|
|
6596
|
+
});
|
|
6597
|
+
}
|
|
6598
|
+
async function syncStoredSession() {
|
|
6599
|
+
const config = initializedConfig;
|
|
6600
|
+
if (!config)
|
|
6601
|
+
return;
|
|
6602
|
+
const token = core.WebSessionManager.getIdToken();
|
|
6603
|
+
const issuer = core.WebSessionManager.getIssuer();
|
|
6604
|
+
if (token === observedIdToken && issuer === observedIssuer)
|
|
6605
|
+
return;
|
|
6606
|
+
observedIdToken = token;
|
|
6607
|
+
observedIssuer = issuer;
|
|
6608
|
+
const generation = ++initializationGeneration;
|
|
6609
|
+
// Hide the former principal while the replacement is validated. This also
|
|
6610
|
+
// reconnects live reads through the existing auth-state change path.
|
|
6611
|
+
setCurrentUser(null);
|
|
6612
|
+
if (authReadyPromise)
|
|
6613
|
+
await authReadyPromise.catch(() => { });
|
|
6614
|
+
if (generation !== initializationGeneration || config !== initializedConfig)
|
|
6615
|
+
return;
|
|
6616
|
+
const record = await core.WebSessionManager.readSessionWithGeneration();
|
|
6617
|
+
if (generation !== initializationGeneration || config !== initializedConfig)
|
|
6618
|
+
return;
|
|
6619
|
+
if (!record)
|
|
6620
|
+
return;
|
|
6621
|
+
const normalize = (url) => (url || '').replace(/\/+$/, '');
|
|
6622
|
+
const resolvedConfig = await core.getConfig();
|
|
6623
|
+
if (generation !== initializationGeneration || config !== initializedConfig)
|
|
6624
|
+
return;
|
|
6625
|
+
const allowedIssuers = [normalize(resolvedConfig.humanAuthApiUrl || 'https://auth.bounded.sh'), normalize(resolvedConfig.authApiUrl)].filter(Boolean);
|
|
6626
|
+
// A legacy shared blob can belong to another app. Never restore or clear
|
|
6627
|
+
// that app's credential; the current app remains signed out.
|
|
6628
|
+
if ((record.appId && record.appId !== config.appId)
|
|
6629
|
+
|| (record.issuer && !allowedIssuers.includes(normalize(record.issuer))))
|
|
6630
|
+
return;
|
|
6631
|
+
if (!storedSessionAuthMethod(config))
|
|
6632
|
+
return;
|
|
6633
|
+
const restored = startInitialization(config, true);
|
|
6634
|
+
const restoreGeneration = initializationGeneration;
|
|
6635
|
+
try {
|
|
6636
|
+
await restored;
|
|
6637
|
+
}
|
|
6638
|
+
catch (error) {
|
|
6639
|
+
if (restoreGeneration === initializationGeneration && core.WebSessionManager.getIdToken())
|
|
6640
|
+
throw error;
|
|
6641
|
+
}
|
|
6642
|
+
}
|
|
6521
6643
|
/** Internal guard for a login result arriving after the app reconfigured the SDK. */
|
|
6522
6644
|
function getInitializationGeneration() { return initializationGeneration; }
|
|
6523
6645
|
// This file acts as a middleware for the global state of the SDK
|
|
6524
6646
|
// This mostly involves setting up the AuthProvider and managing the current user
|
|
6525
|
-
async function initialize(requestedConfig) {
|
|
6647
|
+
async function initialize(requestedConfig, fromStorage) {
|
|
6526
6648
|
const newConfig = withDefaultSolanaRpcUrl(requestedConfig);
|
|
6649
|
+
const generation = initializationGeneration;
|
|
6650
|
+
const validateStorage = fromStorage ? core.WebSessionManager.captureSessionEstablishment() : undefined;
|
|
6651
|
+
const beforeCommit = () => {
|
|
6652
|
+
if (generation !== initializationGeneration)
|
|
6653
|
+
throw new Error('Session restore was superseded.');
|
|
6654
|
+
validateStorage === null || validateStorage === void 0 ? void 0 : validateStorage();
|
|
6655
|
+
};
|
|
6527
6656
|
// Mark auth as loading for the ENTIRE init/restore window so consumers render
|
|
6528
6657
|
// a neutral/loading state instead of the signed-out UI while we rehydrate the
|
|
6529
6658
|
// session — otherwise getCurrentUser() is null + loading is false during the
|
|
@@ -6542,8 +6671,9 @@ async function initialize(requestedConfig) {
|
|
|
6542
6671
|
// onAuthStateChanged never fired, and every consumer UI went on showing a
|
|
6543
6672
|
// connected wallet for a session the server no longer knew about.
|
|
6544
6673
|
registerSessionClearedBridge();
|
|
6674
|
+
registerStorageBridge();
|
|
6545
6675
|
// Get auth provider first
|
|
6546
|
-
authProviderInstance = await getAuthProvider(newConfig);
|
|
6676
|
+
authProviderInstance = await getAuthProvider(newConfig, fromStorage);
|
|
6547
6677
|
// Initialize config with auth provider
|
|
6548
6678
|
await core.init(Object.assign(Object.assign({}, newConfig), { authProvider: authProviderInstance }));
|
|
6549
6679
|
// A return establishes its own provider/session, or hands off a popup.
|
|
@@ -6568,7 +6698,8 @@ async function initialize(requestedConfig) {
|
|
|
6568
6698
|
// Wait for restoreSession to complete
|
|
6569
6699
|
// The appId check is done in SessionManager.getSession which is called by restoreSession
|
|
6570
6700
|
// If there's an appId mismatch, the session will be cleared and restoreSession will return null
|
|
6571
|
-
let user = await authProviderInstance.restoreSession();
|
|
6701
|
+
let user = await authProviderInstance.restoreSession(beforeCommit);
|
|
6702
|
+
beforeCommit();
|
|
6572
6703
|
// If a session exists but was created before auth method tracking (legacy session),
|
|
6573
6704
|
// clear it to avoid mismatches when the app switches auth methods (e.g. email → phantom)
|
|
6574
6705
|
//
|
|
@@ -6576,9 +6707,10 @@ async function initialize(requestedConfig) {
|
|
|
6576
6707
|
// unawaited call would return a Promise (always truthy) — nulling the user
|
|
6577
6708
|
// unconditionally AND letting setCurrentUser run while the old credential
|
|
6578
6709
|
// was still in storage.
|
|
6579
|
-
if (user && await clearIncompatibleSession()) {
|
|
6710
|
+
if (user && !fromStorage && await clearIncompatibleSession()) {
|
|
6580
6711
|
user = null;
|
|
6581
6712
|
}
|
|
6713
|
+
beforeCommit();
|
|
6582
6714
|
setCurrentUser(user);
|
|
6583
6715
|
// Mark init as completed
|
|
6584
6716
|
initCompleted = true;
|
|
@@ -6618,13 +6750,17 @@ function sameConfigValue(a, b, seen = new WeakMap()) {
|
|
|
6618
6750
|
&& sameConfigValue(a[key], b[key], seen));
|
|
6619
6751
|
}
|
|
6620
6752
|
function init(newConfig) {
|
|
6753
|
+
return startInitialization(newConfig, false);
|
|
6754
|
+
}
|
|
6755
|
+
function startInitialization(newConfig, fromStorage) {
|
|
6621
6756
|
if (initializingConfig) {
|
|
6622
6757
|
if (sameConfigValue(initializingConfig, newConfig)) {
|
|
6623
6758
|
return authReadyPromise;
|
|
6624
6759
|
}
|
|
6625
6760
|
return Promise.reject(new Error('SDK initialization is in progress. Await init() before changing its configuration.'));
|
|
6626
6761
|
}
|
|
6627
|
-
|
|
6762
|
+
initializedConfig = Object.assign({}, newConfig);
|
|
6763
|
+
initializingConfig = initializedConfig;
|
|
6628
6764
|
initializationGeneration++;
|
|
6629
6765
|
let resolveReady;
|
|
6630
6766
|
let rejectReady;
|
|
@@ -6636,7 +6772,7 @@ function init(newConfig) {
|
|
|
6636
6772
|
// auth-loading listener to call waitForAuthReady() synchronously when init()
|
|
6637
6773
|
// announces that session restoration has begun.
|
|
6638
6774
|
authReadyPromise = ready;
|
|
6639
|
-
void initialize(initializingConfig).then(() => { initializingConfig = null; resolveReady(); }, (error) => { initializingConfig = null; rejectReady(error); });
|
|
6775
|
+
void initialize(initializingConfig, fromStorage).then(() => { initializingConfig = null; resolveReady(); }, (error) => { initializingConfig = null; rejectReady(error); });
|
|
6640
6776
|
return ready;
|
|
6641
6777
|
}
|
|
6642
6778
|
/**
|
|
@@ -6709,6 +6845,13 @@ function userPrincipalKey(user) {
|
|
|
6709
6845
|
}
|
|
6710
6846
|
// Update the currentUser and notify listeners
|
|
6711
6847
|
function setCurrentUser(user) {
|
|
6848
|
+
observedIdToken = getCurrentIdToken();
|
|
6849
|
+
try {
|
|
6850
|
+
observedIssuer = core.getActiveSessionManager().getIssuer();
|
|
6851
|
+
}
|
|
6852
|
+
catch (_a) {
|
|
6853
|
+
observedIssuer = null;
|
|
6854
|
+
}
|
|
6712
6855
|
// Enrich with the universal identity fields (id/email) derived from the
|
|
6713
6856
|
// active session's idToken — central chokepoint so every provider's user
|
|
6714
6857
|
// object gains { id, address, email } without each construction site
|
|
@@ -8511,8 +8654,9 @@ class PrivyExpoProvider {
|
|
|
8511
8654
|
const { signature } = await this.signAndSubmitInternal(transaction, wallet, connection);
|
|
8512
8655
|
return signature;
|
|
8513
8656
|
}
|
|
8514
|
-
async restoreSession() {
|
|
8657
|
+
async restoreSession(beforeCommit) {
|
|
8515
8658
|
const session = await core.getActiveSessionManager().getSession();
|
|
8659
|
+
beforeCommit === null || beforeCommit === void 0 ? void 0 : beforeCommit();
|
|
8516
8660
|
if (session) {
|
|
8517
8661
|
this.authenticatedAddress = session.address;
|
|
8518
8662
|
return { provider: this, address: session.address };
|
|
@@ -8674,4 +8818,4 @@ exports.useAuth = useAuth;
|
|
|
8674
8818
|
exports.useBuildRun = useBuildRun;
|
|
8675
8819
|
exports.useQuery = useQuery;
|
|
8676
8820
|
exports.waitForAuthReady = waitForAuthReady;
|
|
8677
|
-
//# sourceMappingURL=index.native-
|
|
8821
|
+
//# sourceMappingURL=index.native-ingNhWPw.js.map
|