@oxyhq/services 6.10.5 → 6.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A comprehensive TypeScript UI library for the Oxy API providing authentication, user management, and UI components for React Native and Expo applications.
4
4
 
5
- **Current published version: 6.10.4**
5
+ **Current published version: 6.10.5**
6
6
 
7
7
  > **For web apps (Vite, Next.js, CRA):** Use [`@oxyhq/auth`](../auth) for authentication and [`@oxyhq/core`](../core) for types and services.
8
8
  >
@@ -747,11 +747,11 @@ Typed returns are defined in `ui/hooks/queries/paymentTypes.ts` (`Subscription`,
747
747
 
748
748
  ## Sign-In Token Planting
749
749
 
750
- `useAuthOperations.performSignIn` plants the `accessToken` returned directly by `verifyChallenge` via `oxyServices.setTokens(...)`. It falls back to the bearer-protected `getTokenBySession` only when the verify response omits the token. Without this, a brand-new identity 401s on the session sync step.
750
+ `@oxyhq/core` `OxyServices.verifyChallenge()` plants `setTokens(accessToken, refreshToken ?? '')` internally before returning. `useAuthOperations.performSignIn` no longer needs to hand-plant the token or fall back to `getTokenBySession` just await `verifyChallenge` and proceed.
751
751
 
752
752
  ## Silent SSO Run-Once Guard
753
753
 
754
- `useWebSSO` contains a module-level `silentSSOAttempted` Set keyed on `origin+baseURL`. Silent FedCM sign-in fires exactly once per page load regardless of unmount/remount or StrictMode double-invoke.
754
+ The cross-page-load deduplication guard for `navigator.credentials.get({mediation:'silent'})` lives in `@oxyhq/core` `OxyServices.silentSignInWithFedCM()` (module-level memo keyed on `origin+baseURL`). `useWebSSO` in this package keeps only a per-instance `hasCheckedRef` fast-path no cross-mount guard.
755
755
 
756
756
  ## Requirements
757
757
 
@@ -23,6 +23,36 @@ var _react = require("react");
23
23
  * @see https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API
24
24
  */
25
25
 
26
+ /**
27
+ * Module-level guard tracking which (origin + API) signatures have already
28
+ * had a silent SSO attempt this page load.
29
+ *
30
+ * A per-component `useRef` guard resets whenever the provider remounts (route
31
+ * churn, StrictMode double-invoke, error-boundary recovery), which previously
32
+ * allowed silent SSO to re-fire and — combined with a routing redirect loop —
33
+ * produced an accelerating `navigator.credentials.get` retry storm. Keying the
34
+ * guard on a stable signature instead of the component instance makes silent
35
+ * SSO fire EXACTLY ONCE per page load regardless of how many times the
36
+ * provider mounts. The set is intentionally never cleared: a fresh page load
37
+ * (the only thing that can change the answer) starts a fresh module scope.
38
+ */
39
+ const silentSSOAttempted = new Set();
40
+
41
+ /**
42
+ * Build a stable signature for the silent-SSO run-once guard. Two providers
43
+ * pointed at the same API from the same origin share one attempt.
44
+ */
45
+ function ssoSignature(oxyServices) {
46
+ const origin = typeof window !== 'undefined' ? window.location.origin : 'no-origin';
47
+ let baseURL = '';
48
+ try {
49
+ baseURL = oxyServices.getBaseURL?.() ?? '';
50
+ } catch {
51
+ baseURL = '';
52
+ }
53
+ return `${origin}|${baseURL}`;
54
+ }
55
+
26
56
  /**
27
57
  * Check if we're running in a web browser environment (not React Native)
28
58
  */
@@ -140,12 +170,12 @@ function useWebSSO({
140
170
 
141
171
  // Auto-check SSO on mount (web only, FedCM only, not on auth domain).
142
172
  //
143
- // `hasCheckedRef` is a cheap per-instance fast-path so effect re-runs (from
144
- // changing deps) within one mount never re-fire. The page-load run-once
145
- // guarantee silent SSO invoking `navigator.credentials.get` AT MOST ONCE
146
- // per page load across remounts / StrictMode / multiple consumers — lives in
147
- // `@oxyhq/core`'s `silentSignInWithFedCM`, which memoizes the first silent
148
- // attempt's result for this origin + API. The hook therefore calls it freely.
173
+ // Run-once is enforced by TWO guards:
174
+ // 1. `hasCheckedRef` cheap per-instance fast-path so effect re-runs
175
+ // (from changing deps) within one mount never re-fire.
176
+ // 2. `silentSSOAttempted` module-level, survives remounts/StrictMode so
177
+ // silent SSO fires exactly once per page load even if the provider
178
+ // unmounts and remounts.
149
179
  (0, _react.useEffect)(() => {
150
180
  if (!enabled || !isWebBrowser() || hasCheckedRef.current || isIdentityProvider(authWebUrl)) {
151
181
  if (isIdentityProvider(authWebUrl)) {
@@ -153,13 +183,21 @@ function useWebSSO({
153
183
  }
154
184
  return;
155
185
  }
186
+ const signature = ssoSignature(oxyServices);
187
+ if (silentSSOAttempted.has(signature)) {
188
+ // Already attempted this page load (e.g. before a remount) — do not
189
+ // re-fire. Mark the local fast-path too so subsequent re-renders skip.
190
+ hasCheckedRef.current = true;
191
+ return;
192
+ }
156
193
  hasCheckedRef.current = true;
194
+ silentSSOAttempted.add(signature);
157
195
  if (fedCMSupported) {
158
196
  checkSSO();
159
197
  } else {
160
198
  onSSOUnavailable?.();
161
199
  }
162
- }, [enabled, checkSSO, fedCMSupported, onSSOUnavailable, authWebUrl]);
200
+ }, [enabled, checkSSO, fedCMSupported, onSSOUnavailable, oxyServices, authWebUrl]);
163
201
  return {
164
202
  checkSSO,
165
203
  signInWithFedCM,
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","isWebBrowser","window","document","documentElement","isIdentityProvider","authWebUrl","hostname","location","idpHostname","URL","useWebSSO","oxyServices","onSessionFound","onSSOUnavailable","onError","enabled","isCheckingRef","useRef","hasCheckedRef","fedCMSupported","isFedCMSupported","config","checkSSO","useCallback","current","session","silentSignInWithFedCM","error","Error","String","signInWithFedCM","useEffect","isChecking"],"sourceRoot":"../../../../src","sources":["ui/hooks/useWebSSO.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","silentSSOAttempted","Set","ssoSignature","oxyServices","origin","window","location","baseURL","getBaseURL","isWebBrowser","document","documentElement","isIdentityProvider","authWebUrl","hostname","idpHostname","URL","useWebSSO","onSessionFound","onSSOUnavailable","onError","enabled","isCheckingRef","useRef","hasCheckedRef","fedCMSupported","isFedCMSupported","config","checkSSO","useCallback","current","session","silentSignInWithFedCM","error","Error","String","signInWithFedCM","useEffect","signature","has","add","isChecking"],"sourceRoot":"../../../../src","sources":["ui/hooks/useWebSSO.ts"],"mappings":"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","ignoreList":[]}
@@ -18,6 +18,36 @@
18
18
  */
19
19
 
20
20
  import { useEffect, useRef, useCallback } from 'react';
21
+ /**
22
+ * Module-level guard tracking which (origin + API) signatures have already
23
+ * had a silent SSO attempt this page load.
24
+ *
25
+ * A per-component `useRef` guard resets whenever the provider remounts (route
26
+ * churn, StrictMode double-invoke, error-boundary recovery), which previously
27
+ * allowed silent SSO to re-fire and — combined with a routing redirect loop —
28
+ * produced an accelerating `navigator.credentials.get` retry storm. Keying the
29
+ * guard on a stable signature instead of the component instance makes silent
30
+ * SSO fire EXACTLY ONCE per page load regardless of how many times the
31
+ * provider mounts. The set is intentionally never cleared: a fresh page load
32
+ * (the only thing that can change the answer) starts a fresh module scope.
33
+ */
34
+ const silentSSOAttempted = new Set();
35
+
36
+ /**
37
+ * Build a stable signature for the silent-SSO run-once guard. Two providers
38
+ * pointed at the same API from the same origin share one attempt.
39
+ */
40
+ function ssoSignature(oxyServices) {
41
+ const origin = typeof window !== 'undefined' ? window.location.origin : 'no-origin';
42
+ let baseURL = '';
43
+ try {
44
+ baseURL = oxyServices.getBaseURL?.() ?? '';
45
+ } catch {
46
+ baseURL = '';
47
+ }
48
+ return `${origin}|${baseURL}`;
49
+ }
50
+
21
51
  /**
22
52
  * Check if we're running in a web browser environment (not React Native)
23
53
  */
@@ -135,12 +165,12 @@ export function useWebSSO({
135
165
 
136
166
  // Auto-check SSO on mount (web only, FedCM only, not on auth domain).
137
167
  //
138
- // `hasCheckedRef` is a cheap per-instance fast-path so effect re-runs (from
139
- // changing deps) within one mount never re-fire. The page-load run-once
140
- // guarantee silent SSO invoking `navigator.credentials.get` AT MOST ONCE
141
- // per page load across remounts / StrictMode / multiple consumers — lives in
142
- // `@oxyhq/core`'s `silentSignInWithFedCM`, which memoizes the first silent
143
- // attempt's result for this origin + API. The hook therefore calls it freely.
168
+ // Run-once is enforced by TWO guards:
169
+ // 1. `hasCheckedRef` cheap per-instance fast-path so effect re-runs
170
+ // (from changing deps) within one mount never re-fire.
171
+ // 2. `silentSSOAttempted` module-level, survives remounts/StrictMode so
172
+ // silent SSO fires exactly once per page load even if the provider
173
+ // unmounts and remounts.
144
174
  useEffect(() => {
145
175
  if (!enabled || !isWebBrowser() || hasCheckedRef.current || isIdentityProvider(authWebUrl)) {
146
176
  if (isIdentityProvider(authWebUrl)) {
@@ -148,13 +178,21 @@ export function useWebSSO({
148
178
  }
149
179
  return;
150
180
  }
181
+ const signature = ssoSignature(oxyServices);
182
+ if (silentSSOAttempted.has(signature)) {
183
+ // Already attempted this page load (e.g. before a remount) — do not
184
+ // re-fire. Mark the local fast-path too so subsequent re-renders skip.
185
+ hasCheckedRef.current = true;
186
+ return;
187
+ }
151
188
  hasCheckedRef.current = true;
189
+ silentSSOAttempted.add(signature);
152
190
  if (fedCMSupported) {
153
191
  checkSSO();
154
192
  } else {
155
193
  onSSOUnavailable?.();
156
194
  }
157
- }, [enabled, checkSSO, fedCMSupported, onSSOUnavailable, authWebUrl]);
195
+ }, [enabled, checkSSO, fedCMSupported, onSSOUnavailable, oxyServices, authWebUrl]);
158
196
  return {
159
197
  checkSSO,
160
198
  signInWithFedCM,
@@ -1 +1 @@
1
- {"version":3,"names":["useEffect","useRef","useCallback","isWebBrowser","window","document","documentElement","isIdentityProvider","authWebUrl","hostname","location","idpHostname","URL","useWebSSO","oxyServices","onSessionFound","onSSOUnavailable","onError","enabled","isCheckingRef","hasCheckedRef","fedCMSupported","isFedCMSupported","config","checkSSO","current","session","silentSignInWithFedCM","error","Error","String","signInWithFedCM","isChecking"],"sourceRoot":"../../../../src","sources":["ui/hooks/useWebSSO.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useEffect","useRef","useCallback","silentSSOAttempted","Set","ssoSignature","oxyServices","origin","window","location","baseURL","getBaseURL","isWebBrowser","document","documentElement","isIdentityProvider","authWebUrl","hostname","idpHostname","URL","useWebSSO","onSessionFound","onSSOUnavailable","onError","enabled","isCheckingRef","hasCheckedRef","fedCMSupported","isFedCMSupported","config","checkSSO","current","session","silentSignInWithFedCM","error","Error","String","signInWithFedCM","signature","has","add","isChecking"],"sourceRoot":"../../../../src","sources":["ui/hooks/useWebSSO.ts"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"useWebSSO.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useWebSSO.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,UAAU,gBAAgB;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACrD,2DAA2D;IAC3D,eAAe,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC5D,uCAAuC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,iBAAS,YAAY,IAAI,OAAO,CAI/B;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,EACxB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,OAAO,EACP,OAAc,GACf,EAAE,gBAAgB,GAAG,eAAe,CA+GpC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"useWebSSO.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useWebSSO.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,UAAU,gBAAgB;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACrD,2DAA2D;IAC3D,eAAe,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC5D,uCAAuC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAgCD;;GAEG;AACH,iBAAS,YAAY,IAAI,OAAO,CAI/B;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,EACxB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,OAAO,EACP,OAAc,GACf,EAAE,gBAAgB,GAAG,eAAe,CAwHpC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useWebSSO.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useWebSSO.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,UAAU,gBAAgB;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACrD,2DAA2D;IAC3D,eAAe,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC5D,uCAAuC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,iBAAS,YAAY,IAAI,OAAO,CAI/B;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,EACxB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,OAAO,EACP,OAAc,GACf,EAAE,gBAAgB,GAAG,eAAe,CA+GpC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"useWebSSO.d.ts","sourceRoot":"","sources":["../../../../../src/ui/hooks/useWebSSO.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,UAAU,gBAAgB;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACrD,2DAA2D;IAC3D,eAAe,EAAE,MAAM,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC5D,uCAAuC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAgCD;;GAEG;AACH,iBAAS,YAAY,IAAI,OAAO,CAI/B;AAgBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,EACxB,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,OAAO,EACP,OAAc,GACf,EAAE,gBAAgB,GAAG,eAAe,CAwHpC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/services",
3
- "version": "6.10.5",
3
+ "version": "6.10.6",
4
4
  "description": "OxyHQ Expo/React Native SDK — UI components, screens, and native features",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -38,6 +38,36 @@ interface UseWebSSOResult {
38
38
  isFedCMSupported: boolean;
39
39
  }
40
40
 
41
+ /**
42
+ * Module-level guard tracking which (origin + API) signatures have already
43
+ * had a silent SSO attempt this page load.
44
+ *
45
+ * A per-component `useRef` guard resets whenever the provider remounts (route
46
+ * churn, StrictMode double-invoke, error-boundary recovery), which previously
47
+ * allowed silent SSO to re-fire and — combined with a routing redirect loop —
48
+ * produced an accelerating `navigator.credentials.get` retry storm. Keying the
49
+ * guard on a stable signature instead of the component instance makes silent
50
+ * SSO fire EXACTLY ONCE per page load regardless of how many times the
51
+ * provider mounts. The set is intentionally never cleared: a fresh page load
52
+ * (the only thing that can change the answer) starts a fresh module scope.
53
+ */
54
+ const silentSSOAttempted = new Set<string>();
55
+
56
+ /**
57
+ * Build a stable signature for the silent-SSO run-once guard. Two providers
58
+ * pointed at the same API from the same origin share one attempt.
59
+ */
60
+ function ssoSignature(oxyServices: OxyServices): string {
61
+ const origin = typeof window !== 'undefined' ? window.location.origin : 'no-origin';
62
+ let baseURL = '';
63
+ try {
64
+ baseURL = oxyServices.getBaseURL?.() ?? '';
65
+ } catch {
66
+ baseURL = '';
67
+ }
68
+ return `${origin}|${baseURL}`;
69
+ }
70
+
41
71
  /**
42
72
  * Check if we're running in a web browser environment (not React Native)
43
73
  */
@@ -165,12 +195,12 @@ export function useWebSSO({
165
195
 
166
196
  // Auto-check SSO on mount (web only, FedCM only, not on auth domain).
167
197
  //
168
- // `hasCheckedRef` is a cheap per-instance fast-path so effect re-runs (from
169
- // changing deps) within one mount never re-fire. The page-load run-once
170
- // guarantee silent SSO invoking `navigator.credentials.get` AT MOST ONCE
171
- // per page load across remounts / StrictMode / multiple consumers — lives in
172
- // `@oxyhq/core`'s `silentSignInWithFedCM`, which memoizes the first silent
173
- // attempt's result for this origin + API. The hook therefore calls it freely.
198
+ // Run-once is enforced by TWO guards:
199
+ // 1. `hasCheckedRef` cheap per-instance fast-path so effect re-runs
200
+ // (from changing deps) within one mount never re-fire.
201
+ // 2. `silentSSOAttempted` module-level, survives remounts/StrictMode so
202
+ // silent SSO fires exactly once per page load even if the provider
203
+ // unmounts and remounts.
174
204
  useEffect(() => {
175
205
  if (!enabled || !isWebBrowser() || hasCheckedRef.current || isIdentityProvider(authWebUrl)) {
176
206
  if (isIdentityProvider(authWebUrl)) {
@@ -179,14 +209,23 @@ export function useWebSSO({
179
209
  return;
180
210
  }
181
211
 
212
+ const signature = ssoSignature(oxyServices);
213
+ if (silentSSOAttempted.has(signature)) {
214
+ // Already attempted this page load (e.g. before a remount) — do not
215
+ // re-fire. Mark the local fast-path too so subsequent re-renders skip.
216
+ hasCheckedRef.current = true;
217
+ return;
218
+ }
219
+
182
220
  hasCheckedRef.current = true;
221
+ silentSSOAttempted.add(signature);
183
222
 
184
223
  if (fedCMSupported) {
185
224
  checkSSO();
186
225
  } else {
187
226
  onSSOUnavailable?.();
188
227
  }
189
- }, [enabled, checkSSO, fedCMSupported, onSSOUnavailable, authWebUrl]);
228
+ }, [enabled, checkSSO, fedCMSupported, onSSOUnavailable, oxyServices, authWebUrl]);
190
229
 
191
230
  return {
192
231
  checkSSO,