@oxyhq/services 12.1.1 → 12.2.0

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.
Files changed (47) hide show
  1. package/lib/commonjs/index.js +17 -0
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/ui/components/SignInModal.js +9 -2
  4. package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
  5. package/lib/commonjs/ui/context/OxyContext.js +8 -0
  6. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  7. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +8 -0
  8. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  9. package/lib/commonjs/ui/screens/OxyAuthScreen.js +10 -2
  10. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
  11. package/lib/commonjs/utils/crossApex.js +74 -0
  12. package/lib/commonjs/utils/crossApex.js.map +1 -0
  13. package/lib/module/index.js +5 -0
  14. package/lib/module/index.js.map +1 -1
  15. package/lib/module/ui/components/SignInModal.js +9 -2
  16. package/lib/module/ui/components/SignInModal.js.map +1 -1
  17. package/lib/module/ui/context/OxyContext.js +8 -0
  18. package/lib/module/ui/context/OxyContext.js.map +1 -1
  19. package/lib/module/ui/context/hooks/useAuthOperations.js +8 -0
  20. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  21. package/lib/module/ui/screens/OxyAuthScreen.js +10 -2
  22. package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
  23. package/lib/module/utils/crossApex.js +69 -0
  24. package/lib/module/utils/crossApex.js.map +1 -0
  25. package/lib/typescript/commonjs/index.d.ts +1 -0
  26. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  27. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
  28. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  29. package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  30. package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  31. package/lib/typescript/commonjs/utils/crossApex.d.ts +55 -0
  32. package/lib/typescript/commonjs/utils/crossApex.d.ts.map +1 -0
  33. package/lib/typescript/module/index.d.ts +1 -0
  34. package/lib/typescript/module/index.d.ts.map +1 -1
  35. package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
  36. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  37. package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  38. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +1 -1
  39. package/lib/typescript/module/utils/crossApex.d.ts +55 -0
  40. package/lib/typescript/module/utils/crossApex.d.ts.map +1 -0
  41. package/package.json +1 -1
  42. package/src/index.ts +4 -0
  43. package/src/ui/components/SignInModal.tsx +18 -6
  44. package/src/ui/context/OxyContext.tsx +8 -0
  45. package/src/ui/context/hooks/useAuthOperations.ts +8 -0
  46. package/src/ui/screens/OxyAuthScreen.tsx +20 -6
  47. package/src/utils/crossApex.ts +75 -0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Cross-apex web detection for sign-in durability gating.
3
+ *
4
+ * On a web Relying Party whose registrable apex differs from the central Oxy
5
+ * Identity Provider apex (`oxy.so`), the ONLY sign-in completion that survives a
6
+ * page reload is the interactive "Continue with Oxy" IdP flow, because it is the
7
+ * only one that establishes a first-party `fedcm_session` cookie at
8
+ * `auth.<apex>` — the anchor the cross-domain cold-boot restore reads on reload.
9
+ *
10
+ * The other sign-in completions the SDK can drive do NOT plant a `fedcm_session`:
11
+ * - password / public-key sign-in mints a bearer directly against the Oxy API
12
+ * (its refresh cookie is host-scoped to `api.oxy.so` and `SameSite=Lax`, so
13
+ * it is unreachable cross-site from the RP), and
14
+ * - the Commons-app device-flow handoff (cross-device QR / same-device
15
+ * deep-link) is approved OUTSIDE the browser, so no IdP browser session is
16
+ * established.
17
+ * On a cross-apex RP each of these leaves the user signed in for the current
18
+ * page only — a reload logs them out. See OxyHQServices AGENTS.md
19
+ * "Auth / Session Contract".
20
+ *
21
+ * Same-apex `*.oxy.so` apps (e.g. `accounts.oxy.so`) are first-party with
22
+ * `api.oxy.so`: their refresh cookie rides same-site requests so reload restore
23
+ * works without `fedcm_session`, and they are therefore NOT gated.
24
+ *
25
+ * Returns `false` off-browser (React Native has no `window.location`) and for
26
+ * hosts without a registrable apex (localhost / raw IP / single-label dev
27
+ * hosts), so native and local development keep every sign-in method.
28
+ */
29
+
30
+ import { registrableApex, CENTRAL_IDP_APEX } from '@oxyhq/core';
31
+
32
+ /**
33
+ * Whether the given host is a web RP on a registrable apex other than the
34
+ * central Oxy IdP apex (`oxy.so`). See the module doc for why this gates the
35
+ * non-durable sign-in paths.
36
+ *
37
+ * @param hostname - The host to classify. Defaults to the current
38
+ * `window.location.hostname`; resolves to `undefined` off-browser (React
39
+ * Native / SSR), which yields `false`. The explicit parameter mirrors
40
+ * `autoDetectAuthWebUrl(location?)` and keeps the predicate unit-testable
41
+ * without manipulating the global `window.location`.
42
+ */
43
+ export function isCrossApexWeb(
44
+ hostname: string | undefined = typeof window !== 'undefined'
45
+ ? window.location?.hostname
46
+ : undefined,
47
+ ): boolean {
48
+ if (!hostname) {
49
+ return false;
50
+ }
51
+ const apex = registrableApex(hostname);
52
+ return apex !== null && apex !== CENTRAL_IDP_APEX;
53
+ }
54
+
55
+ /**
56
+ * Thrown when an app attempts a direct (non-IdP) sign-in — password or
57
+ * public-key — on a cross-apex web RP, where such a sign-in would not survive a
58
+ * page reload because no `fedcm_session` is established (see {@link isCrossApexWeb}).
59
+ *
60
+ * Apps on a cross-apex apex must sign in through the interactive
61
+ * "Continue with Oxy" IdP flow (`OxySignInButton` / `showSignInModal()`), which
62
+ * plants the durable session.
63
+ */
64
+ export class CrossApexDirectSignInError extends Error {
65
+ override readonly name = 'CrossApexDirectSignInError';
66
+ readonly code = 'CROSS_APEX_DIRECT_SIGN_IN_UNSUPPORTED';
67
+
68
+ constructor() {
69
+ super(
70
+ 'Direct sign-in is unavailable on this domain because the session would ' +
71
+ 'not survive a page reload. Use "Continue with Oxy" to sign in through ' +
72
+ 'the Oxy identity provider.',
73
+ );
74
+ }
75
+ }