@oxyhq/auth 2.0.6 → 2.0.8
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 +15 -1
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/WebOxyProvider.js +49 -8
- package/dist/cjs/hooks/useWebSSO.js +8 -1
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/WebOxyProvider.js +49 -8
- package/dist/esm/hooks/useWebSSO.js +8 -1
- package/dist/types/.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/WebOxyProvider.tsx +49 -7
- package/src/hooks/useWebSSO.ts +8 -1
package/package.json
CHANGED
package/src/WebOxyProvider.tsx
CHANGED
|
@@ -58,6 +58,39 @@ export interface WebOxyContextValue extends WebAuthState, WebAuthActions {
|
|
|
58
58
|
|
|
59
59
|
const WebOxyContext = createContext<WebOxyContextValue | null>(null);
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Module-level run-once guard for the provider's silent sign-in step.
|
|
63
|
+
*
|
|
64
|
+
* The init effect runs again whenever the provider remounts (route change,
|
|
65
|
+
* StrictMode double-invoke, error-boundary recovery). The redirect-callback
|
|
66
|
+
* and local-session-restore steps are cheap and idempotent, but
|
|
67
|
+
* `crossDomainAuth.silentSignIn()` is NOT: it first tries FedCM silent
|
|
68
|
+
* mediation (`navigator.credentials.get`) and, if that yields nothing, falls
|
|
69
|
+
* back to an iframe-based silent auth against `/auth/silent`.
|
|
70
|
+
*
|
|
71
|
+
* The FedCM leg is now centrally memoized inside `@oxyhq/core`'s
|
|
72
|
+
* `silentSignInWithFedCM` (at-most-once `navigator.credentials.get` per page
|
|
73
|
+
* load). The iframe fallback, however, is a SEPARATE mechanism the core guard
|
|
74
|
+
* does not cover — without this guard a remount storm would create a hidden
|
|
75
|
+
* iframe per remount. So this guard is intentionally retained to keep the
|
|
76
|
+
* provider's WHOLE silent step run-once. Keyed on `origin + baseURL` to match
|
|
77
|
+
* the core guard's keying (so the two stay in lockstep) and to survive
|
|
78
|
+
* instance churn; never cleared because only a fresh page load can change the
|
|
79
|
+
* IdP/iframe session state.
|
|
80
|
+
*/
|
|
81
|
+
const silentSignInAttempted = new Set<string>();
|
|
82
|
+
|
|
83
|
+
function silentSignInKey(oxyServices: OxyServices): string {
|
|
84
|
+
const origin = typeof window !== 'undefined' ? window.location.origin : 'no-origin';
|
|
85
|
+
let baseURL = '';
|
|
86
|
+
try {
|
|
87
|
+
baseURL = oxyServices.getBaseURL();
|
|
88
|
+
} catch {
|
|
89
|
+
baseURL = '';
|
|
90
|
+
}
|
|
91
|
+
return `${origin}|${baseURL}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
61
94
|
export interface WebOxyProviderProps {
|
|
62
95
|
children: ReactNode;
|
|
63
96
|
baseURL: string;
|
|
@@ -191,14 +224,23 @@ export function WebOxyProvider({
|
|
|
191
224
|
}
|
|
192
225
|
}
|
|
193
226
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
227
|
+
// Silent sign-in: run AT MOST ONCE per page load. A remount (route
|
|
228
|
+
// change / StrictMode / error recovery) must not re-trigger the
|
|
229
|
+
// browser credential request OR the iframe fallback. The FedCM leg is
|
|
230
|
+
// additionally memoized in core; this guard also covers the iframe
|
|
231
|
+
// fallback that core does not.
|
|
232
|
+
const ssoKey = silentSignInKey(oxyServices);
|
|
233
|
+
if (!silentSignInAttempted.has(ssoKey)) {
|
|
234
|
+
silentSignInAttempted.add(ssoKey);
|
|
235
|
+
try {
|
|
236
|
+
const session = await crossDomainAuth.silentSignIn();
|
|
237
|
+
if (mounted && session?.user) {
|
|
238
|
+
await handleAuthSuccess(session, 'fedcm');
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
} catch {
|
|
242
|
+
// Silent sign-in failed — resolve to unauthenticated below.
|
|
199
243
|
}
|
|
200
|
-
} catch {
|
|
201
|
-
// Silent sign-in failed
|
|
202
244
|
}
|
|
203
245
|
|
|
204
246
|
if (mounted) setIsLoading(false);
|
package/src/hooks/useWebSSO.ts
CHANGED
|
@@ -158,7 +158,14 @@ export function useWebSSO({
|
|
|
158
158
|
}
|
|
159
159
|
}, [oxyServices, onSessionFound, onError, fedCMSupported]);
|
|
160
160
|
|
|
161
|
-
// Auto-check SSO on mount (web only, FedCM only, not on auth domain)
|
|
161
|
+
// Auto-check SSO on mount (web only, FedCM only, not on auth domain).
|
|
162
|
+
//
|
|
163
|
+
// `hasCheckedRef` is a cheap per-instance fast-path so effect re-runs (from
|
|
164
|
+
// changing deps) within one mount never re-fire. The page-load run-once
|
|
165
|
+
// guarantee — silent SSO invoking `navigator.credentials.get` AT MOST ONCE
|
|
166
|
+
// per page load across remounts / StrictMode / multiple consumers — lives in
|
|
167
|
+
// `@oxyhq/core`'s `silentSignInWithFedCM`, which memoizes the first silent
|
|
168
|
+
// attempt's result for this origin + API. The hook therefore calls it freely.
|
|
162
169
|
useEffect(() => {
|
|
163
170
|
if (!enabled || !isWebBrowser() || hasCheckedRef.current || isIdentityProvider()) {
|
|
164
171
|
if (isIdentityProvider()) {
|