UNPKG

@oxyhq/services

Version:

OxyHQ Expo/React Native SDK — UI components, screens, and native features

156 lines (147 loc) 4.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isWebBrowser = isWebBrowser; exports.useWebSSO = useWebSSO; var _react = require("react"); /** * Web SSO Hook * * Handles cross-domain SSO for web apps using FedCM (Federated Credential Management). * * FedCM is the modern, privacy-preserving standard for cross-domain identity federation. * It works across completely different TLDs (alia.onl, mention.earth, homiio.com, etc.) * without relying on third-party cookies. * * For browsers without FedCM support, users will need to click a sign-in button * which triggers a popup-based authentication flow. * * This is called automatically by OxyContext on web platforms. * * @see https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API */ /** * Check if we're running in a web browser environment (not React Native) */ function isWebBrowser() { return typeof window !== 'undefined' && typeof document !== 'undefined' && typeof document.documentElement !== 'undefined'; } /** * Check if we're on the identity provider domain (where FedCM would authenticate against itself) * Only auth.oxy.so is the IdP - accounts.oxy.so is a client app like any other */ function isIdentityProvider() { if (!isWebBrowser()) return false; const hostname = window.location.hostname; return hostname === 'auth.oxy.so'; } /** * Hook for automatic cross-domain web SSO * * Uses FedCM (Federated Credential Management) - the modern browser-native * identity federation API. This is the same technology that powers * Google's cross-domain SSO (YouTube, Gmail, Maps, etc.). * * Key benefits: * - Works across different TLDs (alia.onl ↔ mention.earth ↔ homiio.com) * - No third-party cookies required * - Privacy-preserving (browser mediates identity, IdP can't track) * - Automatic silent sign-in after initial authentication * * For browsers without FedCM (Firefox, older browsers), automatic SSO * is not possible. Users will see a sign-in button instead. */ function useWebSSO({ oxyServices, onSessionFound, onSSOUnavailable, onError, enabled = true }) { const isCheckingRef = (0, _react.useRef)(false); const hasCheckedRef = (0, _react.useRef)(false); // Check FedCM support once const fedCMSupported = isWebBrowser() && oxyServices.isFedCMSupported?.(); const checkSSO = (0, _react.useCallback)(async () => { if (!isWebBrowser() || isCheckingRef.current) { return null; } // Don't use FedCM on the auth domain itself - it would authenticate against itself if (isIdentityProvider()) { onSSOUnavailable?.(); return null; } // FedCM is the only reliable cross-domain SSO mechanism if (!fedCMSupported) { onSSOUnavailable?.(); return null; } isCheckingRef.current = true; try { const session = await oxyServices.silentSignInWithFedCM?.(); if (session) { await onSessionFound(session); return session; } onSSOUnavailable?.(); return null; } catch (error) { onSSOUnavailable?.(); onError?.(error instanceof Error ? error : new Error(String(error))); return null; } finally { isCheckingRef.current = false; } }, [oxyServices, onSessionFound, onSSOUnavailable, onError, fedCMSupported]); /** * Trigger interactive FedCM sign-in * This shows the browser's native "Sign in with Oxy" prompt. * Use this when silent mediation fails (user hasn't previously consented). */ const signInWithFedCM = (0, _react.useCallback)(async () => { if (!isWebBrowser() || isCheckingRef.current) { return null; } if (!fedCMSupported) { onError?.(new Error('FedCM is not supported in this browser')); return null; } isCheckingRef.current = true; try { const session = await oxyServices.signInWithFedCM?.(); if (session) { await onSessionFound(session); return session; } return null; } catch (error) { onError?.(error instanceof Error ? error : new Error(String(error))); return null; } finally { isCheckingRef.current = false; } }, [oxyServices, onSessionFound, onError, fedCMSupported]); // Auto-check SSO on mount (web only, FedCM only, not on auth domain) (0, _react.useEffect)(() => { if (!enabled || !isWebBrowser() || hasCheckedRef.current || isIdentityProvider()) { if (isIdentityProvider()) { onSSOUnavailable?.(); } return; } hasCheckedRef.current = true; if (fedCMSupported) { checkSSO(); } else { onSSOUnavailable?.(); } }, [enabled, checkSSO, fedCMSupported, onSSOUnavailable]); return { checkSSO, signInWithFedCM, isChecking: isCheckingRef.current, isFedCMSupported: fedCMSupported }; } //# sourceMappingURL=useWebSSO.js.map