@sendoracloud/sdk-react-native 1.0.2 → 1.0.4

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.cjs CHANGED
@@ -485,16 +485,30 @@ var Auth = class {
485
485
  signInWithDiscord(code, redirectUri) {
486
486
  return this.loginSocial({ provider: "discord", code, redirectUri });
487
487
  }
488
+ /**
489
+ * Read the stored anon refresh token if (and only if) the local
490
+ * subject is currently anonymous. Used by every identified-session
491
+ * mint path so the backend can run device-takeover (s58.111 +
492
+ * s58.112). Returns `undefined` when not anonymous — never forward
493
+ * an identified user's own refresh token.
494
+ */
495
+ readPrevAnonRefreshToken() {
496
+ if (!this.user?.isAnonymous) return void 0;
497
+ return this.hooks.storage.get(REFRESH_KEY) ?? void 0;
498
+ }
488
499
  /**
489
500
  * Exchange the MFA challenge token from `signIn` for a real session
490
501
  * by submitting a TOTP or recovery code from the user's authenticator.
491
502
  */
492
503
  challengeMfa(mfaChallengeToken, code) {
493
504
  return this.serialize(async () => {
494
- const data = await this.callAuth("/api/v1/auth-service/mfa/challenge", {
505
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
506
+ const body = {
495
507
  challengeToken: mfaChallengeToken,
496
508
  code
497
- });
509
+ };
510
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
511
+ const data = await this.callAuth("/api/v1/auth-service/mfa/challenge", body);
498
512
  this.persist(data);
499
513
  return data.user;
500
514
  });
@@ -514,8 +528,11 @@ var Auth = class {
514
528
  }
515
529
  verifyMagicLink(token) {
516
530
  return this.serialize(async () => {
531
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
517
532
  if (this.user !== null) await this.wipeLocalIdentity();
518
- const data = await this.callAuth("/api/v1/auth-service/magic-link/verify", { token });
533
+ const body = { token };
534
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
535
+ const data = await this.callAuth("/api/v1/auth-service/magic-link/verify", body);
519
536
  this.persist(data);
520
537
  return data.user;
521
538
  });
@@ -535,8 +552,11 @@ var Auth = class {
535
552
  }
536
553
  verifyEmailOtp(email, code) {
537
554
  return this.serialize(async () => {
555
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
538
556
  if (this.user !== null) await this.wipeLocalIdentity();
539
- const data = await this.callAuth("/api/v1/auth-service/email-otp/verify", { email, code });
557
+ const body = { email, code };
558
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
559
+ const data = await this.callAuth("/api/v1/auth-service/email-otp/verify", body);
540
560
  this.persist(data);
541
561
  return data.user;
542
562
  });
@@ -664,10 +684,13 @@ var Auth = class {
664
684
  * call `consumeSsoFragment(url)` on the captured URL.
665
685
  */
666
686
  async startSso(returnTo) {
687
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
688
+ const body = { returnTo };
689
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
667
690
  const res = await post(
668
691
  { apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
669
692
  "/api/v1/auth-service/sso/oidc/start",
670
- { returnTo }
693
+ body
671
694
  );
672
695
  if (!res || !res.ok) throw new AuthError("SSO_START_FAILED", `HTTP ${res?.status ?? "network"}`);
673
696
  const parsed = await res.json();
@@ -687,10 +710,13 @@ var Auth = class {
687
710
  * and SAML fragments transparently.
688
711
  */
689
712
  async startSaml(returnTo) {
713
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
714
+ const body = { returnTo };
715
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
690
716
  const res = await post(
691
717
  { apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
692
718
  "/api/v1/auth-service/sso/saml/start",
693
- { returnTo }
719
+ body
694
720
  );
695
721
  if (!res || !res.ok) throw new AuthError("SAML_START_FAILED", `HTTP ${res?.status ?? "network"}`);
696
722
  const parsed = await res.json();
package/dist/index.d.cts CHANGED
@@ -220,6 +220,14 @@ declare class Auth {
220
220
  signInWithLinkedIn(code: string, redirectUri: string): Promise<AuthUser>;
221
221
  signInWithFacebook(code: string, redirectUri: string): Promise<AuthUser>;
222
222
  signInWithDiscord(code: string, redirectUri: string): Promise<AuthUser>;
223
+ /**
224
+ * Read the stored anon refresh token if (and only if) the local
225
+ * subject is currently anonymous. Used by every identified-session
226
+ * mint path so the backend can run device-takeover (s58.111 +
227
+ * s58.112). Returns `undefined` when not anonymous — never forward
228
+ * an identified user's own refresh token.
229
+ */
230
+ private readPrevAnonRefreshToken;
223
231
  /**
224
232
  * Exchange the MFA challenge token from `signIn` for a real session
225
233
  * by submitting a TOTP or recovery code from the user's authenticator.
package/dist/index.d.ts CHANGED
@@ -220,6 +220,14 @@ declare class Auth {
220
220
  signInWithLinkedIn(code: string, redirectUri: string): Promise<AuthUser>;
221
221
  signInWithFacebook(code: string, redirectUri: string): Promise<AuthUser>;
222
222
  signInWithDiscord(code: string, redirectUri: string): Promise<AuthUser>;
223
+ /**
224
+ * Read the stored anon refresh token if (and only if) the local
225
+ * subject is currently anonymous. Used by every identified-session
226
+ * mint path so the backend can run device-takeover (s58.111 +
227
+ * s58.112). Returns `undefined` when not anonymous — never forward
228
+ * an identified user's own refresh token.
229
+ */
230
+ private readPrevAnonRefreshToken;
223
231
  /**
224
232
  * Exchange the MFA challenge token from `signIn` for a real session
225
233
  * by submitting a TOTP or recovery code from the user's authenticator.
package/dist/index.js CHANGED
@@ -442,16 +442,30 @@ var Auth = class {
442
442
  signInWithDiscord(code, redirectUri) {
443
443
  return this.loginSocial({ provider: "discord", code, redirectUri });
444
444
  }
445
+ /**
446
+ * Read the stored anon refresh token if (and only if) the local
447
+ * subject is currently anonymous. Used by every identified-session
448
+ * mint path so the backend can run device-takeover (s58.111 +
449
+ * s58.112). Returns `undefined` when not anonymous — never forward
450
+ * an identified user's own refresh token.
451
+ */
452
+ readPrevAnonRefreshToken() {
453
+ if (!this.user?.isAnonymous) return void 0;
454
+ return this.hooks.storage.get(REFRESH_KEY) ?? void 0;
455
+ }
445
456
  /**
446
457
  * Exchange the MFA challenge token from `signIn` for a real session
447
458
  * by submitting a TOTP or recovery code from the user's authenticator.
448
459
  */
449
460
  challengeMfa(mfaChallengeToken, code) {
450
461
  return this.serialize(async () => {
451
- const data = await this.callAuth("/api/v1/auth-service/mfa/challenge", {
462
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
463
+ const body = {
452
464
  challengeToken: mfaChallengeToken,
453
465
  code
454
- });
466
+ };
467
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
468
+ const data = await this.callAuth("/api/v1/auth-service/mfa/challenge", body);
455
469
  this.persist(data);
456
470
  return data.user;
457
471
  });
@@ -471,8 +485,11 @@ var Auth = class {
471
485
  }
472
486
  verifyMagicLink(token) {
473
487
  return this.serialize(async () => {
488
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
474
489
  if (this.user !== null) await this.wipeLocalIdentity();
475
- const data = await this.callAuth("/api/v1/auth-service/magic-link/verify", { token });
490
+ const body = { token };
491
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
492
+ const data = await this.callAuth("/api/v1/auth-service/magic-link/verify", body);
476
493
  this.persist(data);
477
494
  return data.user;
478
495
  });
@@ -492,8 +509,11 @@ var Auth = class {
492
509
  }
493
510
  verifyEmailOtp(email, code) {
494
511
  return this.serialize(async () => {
512
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
495
513
  if (this.user !== null) await this.wipeLocalIdentity();
496
- const data = await this.callAuth("/api/v1/auth-service/email-otp/verify", { email, code });
514
+ const body = { email, code };
515
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
516
+ const data = await this.callAuth("/api/v1/auth-service/email-otp/verify", body);
497
517
  this.persist(data);
498
518
  return data.user;
499
519
  });
@@ -621,10 +641,13 @@ var Auth = class {
621
641
  * call `consumeSsoFragment(url)` on the captured URL.
622
642
  */
623
643
  async startSso(returnTo) {
644
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
645
+ const body = { returnTo };
646
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
624
647
  const res = await post(
625
648
  { apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
626
649
  "/api/v1/auth-service/sso/oidc/start",
627
- { returnTo }
650
+ body
628
651
  );
629
652
  if (!res || !res.ok) throw new AuthError("SSO_START_FAILED", `HTTP ${res?.status ?? "network"}`);
630
653
  const parsed = await res.json();
@@ -644,10 +667,13 @@ var Auth = class {
644
667
  * and SAML fragments transparently.
645
668
  */
646
669
  async startSaml(returnTo) {
670
+ const prevAnonRefreshToken = this.readPrevAnonRefreshToken();
671
+ const body = { returnTo };
672
+ if (prevAnonRefreshToken) body.prevAnonRefreshToken = prevAnonRefreshToken;
647
673
  const res = await post(
648
674
  { apiUrl: this.hooks.apiUrl, publicKey: this.hooks.publicKey, debug: this.hooks.debug },
649
675
  "/api/v1/auth-service/sso/saml/start",
650
- { returnTo }
676
+ body
651
677
  );
652
678
  if (!res || !res.ok) throw new AuthError("SAML_START_FAILED", `HTTP ${res?.status ?? "network"}`);
653
679
  const parsed = await res.json();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendoracloud/sdk-react-native",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Sendora Cloud React Native + Expo SDK — analytics, identity, push-token registration, auth, deep links (Branch / Firebase Dynamic Links parity). Auth + analytics + deep links work in Expo Go; push token registration requires a Dev Client (EAS Build or `npx expo prebuild`).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",