@oxyhq/core 5.5.0 → 7.0.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 (196) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/HttpService.js +7 -4
  3. package/dist/cjs/OxyServices.base.js +7 -102
  4. package/dist/cjs/boot/coldBootV2.js +350 -0
  5. package/dist/cjs/boot/deviceBootReturn.js +152 -0
  6. package/dist/cjs/crypto/keyManager.js +95 -0
  7. package/dist/cjs/i18n/locales/en-US.json +13 -1
  8. package/dist/cjs/i18n/locales/es-ES.json +13 -1
  9. package/dist/cjs/i18n/locales/locales/en-US.json +13 -1
  10. package/dist/cjs/i18n/locales/locales/es-ES.json +13 -1
  11. package/dist/cjs/index.js +54 -45
  12. package/dist/cjs/mixins/OxyServices.accounts.js +13 -26
  13. package/dist/cjs/mixins/OxyServices.auth.js +66 -201
  14. package/dist/cjs/mixins/OxyServices.deviceBoot.js +119 -0
  15. package/dist/cjs/mixins/index.js +8 -17
  16. package/dist/cjs/server/index.js +2 -2
  17. package/dist/cjs/session/SessionClient.js +40 -1
  18. package/dist/cjs/session/authStateStore.js +284 -0
  19. package/dist/cjs/session/refresh.js +264 -0
  20. package/dist/cjs/shared/utils/debugUtils.js +3 -3
  21. package/dist/cjs/utils/accountUtils.js +1 -55
  22. package/dist/cjs/utils/authWebUrl.js +10 -39
  23. package/dist/cjs/utils/coldBoot.js +10 -8
  24. package/dist/cjs/utils/platform.js +19 -0
  25. package/dist/cjs/utils/registrableApex.js +49 -0
  26. package/dist/cjs/utils/ssoBounce.js +15 -362
  27. package/dist/cjs/utils/validationUtils.js +57 -0
  28. package/dist/esm/.tsbuildinfo +1 -1
  29. package/dist/esm/HttpService.js +7 -4
  30. package/dist/esm/OxyServices.base.js +7 -102
  31. package/dist/esm/boot/coldBootV2.js +344 -0
  32. package/dist/esm/boot/deviceBootReturn.js +146 -0
  33. package/dist/esm/crypto/keyManager.js +95 -0
  34. package/dist/esm/i18n/locales/en-US.json +13 -1
  35. package/dist/esm/i18n/locales/es-ES.json +13 -1
  36. package/dist/esm/i18n/locales/locales/en-US.json +13 -1
  37. package/dist/esm/i18n/locales/locales/es-ES.json +13 -1
  38. package/dist/esm/index.js +34 -17
  39. package/dist/esm/mixins/OxyServices.accounts.js +13 -26
  40. package/dist/esm/mixins/OxyServices.auth.js +66 -201
  41. package/dist/esm/mixins/OxyServices.deviceBoot.js +116 -0
  42. package/dist/esm/mixins/index.js +8 -17
  43. package/dist/esm/server/index.js +1 -1
  44. package/dist/esm/session/SessionClient.js +40 -1
  45. package/dist/esm/session/authStateStore.js +278 -0
  46. package/dist/esm/session/refresh.js +257 -0
  47. package/dist/esm/shared/utils/debugUtils.js +3 -3
  48. package/dist/esm/utils/accountUtils.js +0 -53
  49. package/dist/esm/utils/authWebUrl.js +9 -37
  50. package/dist/esm/utils/coldBoot.js +10 -8
  51. package/dist/esm/utils/platform.js +18 -0
  52. package/dist/esm/utils/registrableApex.js +46 -0
  53. package/dist/esm/utils/ssoBounce.js +14 -345
  54. package/dist/esm/utils/validationUtils.js +56 -0
  55. package/dist/types/.tsbuildinfo +1 -1
  56. package/dist/types/HttpService.d.ts +14 -1
  57. package/dist/types/OxyServices.base.d.ts +0 -52
  58. package/dist/types/OxyServices.d.ts +0 -25
  59. package/dist/types/boot/coldBootV2.d.ts +76 -0
  60. package/dist/types/boot/deviceBootReturn.d.ts +83 -0
  61. package/dist/types/crypto/keyManager.d.ts +21 -0
  62. package/dist/types/index.d.ts +14 -21
  63. package/dist/types/mixins/OxyServices.accounts.d.ts +24 -29
  64. package/dist/types/mixins/OxyServices.analytics.d.ts +0 -2
  65. package/dist/types/mixins/OxyServices.appData.d.ts +0 -2
  66. package/dist/types/mixins/OxyServices.assets.d.ts +0 -2
  67. package/dist/types/mixins/OxyServices.auth.d.ts +35 -77
  68. package/dist/types/mixins/OxyServices.civic.d.ts +0 -2
  69. package/dist/types/mixins/OxyServices.connectedApps.d.ts +0 -2
  70. package/dist/types/mixins/OxyServices.contacts.d.ts +0 -2
  71. package/dist/types/mixins/OxyServices.deviceBoot.d.ts +110 -0
  72. package/dist/types/mixins/OxyServices.devices.d.ts +0 -2
  73. package/dist/types/mixins/OxyServices.features.d.ts +0 -2
  74. package/dist/types/mixins/OxyServices.identity.d.ts +0 -2
  75. package/dist/types/mixins/OxyServices.language.d.ts +0 -2
  76. package/dist/types/mixins/OxyServices.links.d.ts +0 -2
  77. package/dist/types/mixins/OxyServices.location.d.ts +0 -2
  78. package/dist/types/mixins/OxyServices.nodes.d.ts +0 -2
  79. package/dist/types/mixins/OxyServices.payment.d.ts +0 -2
  80. package/dist/types/mixins/OxyServices.privacy.d.ts +0 -2
  81. package/dist/types/mixins/OxyServices.reputation.d.ts +0 -2
  82. package/dist/types/mixins/OxyServices.security.d.ts +0 -2
  83. package/dist/types/mixins/OxyServices.topics.d.ts +0 -2
  84. package/dist/types/mixins/OxyServices.user.d.ts +0 -2
  85. package/dist/types/mixins/OxyServices.utility.d.ts +0 -2
  86. package/dist/types/mixins/index.d.ts +5 -9
  87. package/dist/types/models/interfaces.d.ts +0 -67
  88. package/dist/types/models/session.d.ts +4 -5
  89. package/dist/types/server/index.d.ts +1 -1
  90. package/dist/types/session/SessionClient.d.ts +26 -1
  91. package/dist/types/session/authStateStore.d.ts +119 -0
  92. package/dist/types/session/refresh.d.ts +93 -0
  93. package/dist/types/shared/utils/debugUtils.d.ts +3 -3
  94. package/dist/types/utils/accountUtils.d.ts +2 -17
  95. package/dist/types/utils/authWebUrl.d.ts +9 -35
  96. package/dist/types/utils/coldBoot.d.ts +17 -14
  97. package/dist/types/utils/platform.d.ts +14 -0
  98. package/dist/types/utils/registrableApex.d.ts +31 -0
  99. package/dist/types/utils/ssoBounce.d.ts +14 -280
  100. package/dist/types/utils/validationUtils.d.ts +15 -0
  101. package/package.json +2 -2
  102. package/src/HttpService.ts +20 -4
  103. package/src/OxyServices.base.ts +7 -112
  104. package/src/OxyServices.ts +0 -38
  105. package/src/boot/__tests__/coldBootV2.test.ts +317 -0
  106. package/src/boot/__tests__/deviceBootReturn.test.ts +158 -0
  107. package/src/boot/coldBootV2.ts +426 -0
  108. package/src/boot/deviceBootReturn.ts +195 -0
  109. package/src/crypto/__tests__/sharedDeviceToken.test.ts +24 -0
  110. package/src/crypto/keyManager.ts +101 -0
  111. package/src/i18n/locales/en-US.json +13 -1
  112. package/src/i18n/locales/es-ES.json +13 -1
  113. package/src/index.ts +75 -65
  114. package/src/mixins/OxyServices.accounts.ts +27 -39
  115. package/src/mixins/OxyServices.auth.ts +78 -253
  116. package/src/mixins/OxyServices.deviceBoot.ts +146 -0
  117. package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +107 -0
  118. package/src/mixins/__tests__/accounts.test.ts +17 -44
  119. package/src/mixins/__tests__/passwordSignIn.test.ts +91 -0
  120. package/src/mixins/index.ts +10 -23
  121. package/src/models/interfaces.ts +0 -79
  122. package/src/models/session.ts +4 -5
  123. package/src/server/index.ts +1 -1
  124. package/src/session/SessionClient.ts +53 -2
  125. package/src/session/__tests__/SessionClient.additive.test.ts +92 -0
  126. package/src/session/__tests__/SessionClient.rest.test.ts +25 -0
  127. package/src/session/__tests__/SessionClient.state.test.ts +18 -5
  128. package/src/session/__tests__/authStateStore.test.ts +209 -0
  129. package/src/session/__tests__/refresh.test.ts +256 -0
  130. package/src/session/authStateStore.ts +335 -0
  131. package/src/session/refresh.ts +334 -0
  132. package/src/shared/utils/debugUtils.ts +3 -3
  133. package/src/utils/__tests__/authWebUrl.test.ts +5 -40
  134. package/src/utils/__tests__/registrableApex.test.ts +62 -0
  135. package/src/utils/__tests__/validationUtils.test.ts +30 -0
  136. package/src/utils/accountUtils.ts +2 -65
  137. package/src/utils/authWebUrl.ts +9 -39
  138. package/src/utils/coldBoot.ts +17 -14
  139. package/src/utils/platform.ts +21 -0
  140. package/src/utils/registrableApex.ts +45 -0
  141. package/src/utils/ssoBounce.ts +14 -393
  142. package/src/utils/validationUtils.ts +62 -0
  143. package/dist/cjs/AuthManager.js +0 -1110
  144. package/dist/cjs/AuthManagerTypes.js +0 -13
  145. package/dist/cjs/CrossDomainAuth.js +0 -206
  146. package/dist/cjs/mixins/OxyServices.fedcm.js +0 -823
  147. package/dist/cjs/mixins/OxyServices.redirect.js +0 -95
  148. package/dist/cjs/mixins/OxyServices.silent.js +0 -204
  149. package/dist/cjs/mixins/OxyServices.sso.js +0 -208
  150. package/dist/cjs/utils/fapiAutoDetect.js +0 -99
  151. package/dist/cjs/utils/ssoEstablish.js +0 -110
  152. package/dist/cjs/utils/ssoReturn.js +0 -275
  153. package/dist/esm/AuthManager.js +0 -1105
  154. package/dist/esm/AuthManagerTypes.js +0 -12
  155. package/dist/esm/CrossDomainAuth.js +0 -201
  156. package/dist/esm/mixins/OxyServices.fedcm.js +0 -821
  157. package/dist/esm/mixins/OxyServices.redirect.js +0 -92
  158. package/dist/esm/mixins/OxyServices.silent.js +0 -202
  159. package/dist/esm/mixins/OxyServices.sso.js +0 -204
  160. package/dist/esm/utils/fapiAutoDetect.js +0 -95
  161. package/dist/esm/utils/ssoEstablish.js +0 -107
  162. package/dist/esm/utils/ssoReturn.js +0 -271
  163. package/dist/types/AuthManager.d.ts +0 -380
  164. package/dist/types/AuthManagerTypes.d.ts +0 -81
  165. package/dist/types/CrossDomainAuth.d.ts +0 -164
  166. package/dist/types/mixins/OxyServices.fedcm.d.ts +0 -331
  167. package/dist/types/mixins/OxyServices.redirect.d.ts +0 -92
  168. package/dist/types/mixins/OxyServices.silent.d.ts +0 -132
  169. package/dist/types/mixins/OxyServices.sso.d.ts +0 -138
  170. package/dist/types/utils/fapiAutoDetect.d.ts +0 -56
  171. package/dist/types/utils/ssoEstablish.d.ts +0 -85
  172. package/dist/types/utils/ssoReturn.d.ts +0 -156
  173. package/src/AuthManager.ts +0 -1269
  174. package/src/AuthManagerTypes.ts +0 -86
  175. package/src/CrossDomainAuth.ts +0 -243
  176. package/src/__tests__/authManager.cookiePath.test.ts +0 -390
  177. package/src/__tests__/authManager.security.test.ts +0 -377
  178. package/src/__tests__/crossDomainAuth.test.ts +0 -116
  179. package/src/__tests__/establishDeviceRefreshSlot.test.ts +0 -221
  180. package/src/mixins/OxyServices.fedcm.ts +0 -1026
  181. package/src/mixins/OxyServices.redirect.ts +0 -122
  182. package/src/mixins/OxyServices.silent.ts +0 -272
  183. package/src/mixins/OxyServices.sso.ts +0 -261
  184. package/src/mixins/__tests__/constructorAuthWebUrl.test.ts +0 -85
  185. package/src/mixins/__tests__/fedcm.test.ts +0 -667
  186. package/src/mixins/__tests__/sessionBaseUrl.test.ts +0 -61
  187. package/src/mixins/__tests__/silent.test.ts +0 -102
  188. package/src/mixins/__tests__/sso.test.ts +0 -228
  189. package/src/utils/__tests__/consumeSsoReturn.test.ts +0 -816
  190. package/src/utils/__tests__/fapiAutoDetect.test.ts +0 -183
  191. package/src/utils/__tests__/ssoBounce.test.ts +0 -219
  192. package/src/utils/__tests__/ssoEstablish.test.ts +0 -204
  193. package/src/utils/__tests__/ssoReturn.test.ts +0 -276
  194. package/src/utils/fapiAutoDetect.ts +0 -91
  195. package/src/utils/ssoEstablish.ts +0 -174
  196. package/src/utils/ssoReturn.ts +0 -389
@@ -1,331 +0,0 @@
1
- import type { OxyServicesBase } from '../OxyServices.base';
2
- import type { SessionLoginResponse } from '../models/session';
3
- export interface FedCMAuthOptions {
4
- nonce?: string;
5
- context?: 'signin' | 'signup' | 'continue' | 'use';
6
- loginHint?: string;
7
- }
8
- export interface FedCMConfig {
9
- enabled: boolean;
10
- configURL: string;
11
- clientId?: string;
12
- }
13
- /**
14
- * FedCM request mode values.
15
- *
16
- * The W3C FedCM spec renamed the `IdentityCredentialRequestOptions.mode` enum:
17
- * `'widget'` → `'passive'` and `'button'` → `'active'`. Modern Chrome only
18
- * accepts `'active'`/`'passive'` and throws a synchronous `TypeError` for the
19
- * legacy values, while Chrome 125–131 only understands `'button'`/`'widget'`.
20
- * Callers should use the modern values; the legacy values are accepted for
21
- * convenience and normalised internally.
22
- */
23
- export type FedCMRequestMode = 'active' | 'passive' | 'button' | 'widget';
24
- /**
25
- * Normalised result of a FedCM credential request: the IdP-issued ID token plus
26
- * whether the browser auto-selected the account (no explicit user choice).
27
- */
28
- interface FedCMTokenResult {
29
- token: string;
30
- isAutoSelected: boolean;
31
- }
32
- /**
33
- * Federated Credential Management (FedCM) Authentication Mixin
34
- *
35
- * Implements the modern browser-native identity federation API that enables
36
- * Google-style cross-domain authentication without third-party cookies.
37
- *
38
- * Browser Support:
39
- * - Chrome 108+
40
- * - Safari 16.4+
41
- * - Edge 108+
42
- * - Firefox: Not yet supported (fallback required)
43
- *
44
- * Key Features:
45
- * - No redirects or secondary windows required
46
- * - Browser-native UI prompts
47
- * - Privacy-preserving (IdP can't track users)
48
- * - Automatic SSO across domains
49
- * - Silent re-authentication support
50
- *
51
- * @see https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API
52
- */
53
- export declare function OxyServicesFedCMMixin<T extends typeof OxyServicesBase>(Base: T): {
54
- new (...args: any[]): {
55
- resolveFedcmConfigUrl(): string;
56
- /**
57
- * Instance method to check FedCM support
58
- */
59
- isFedCMSupported(): boolean;
60
- /**
61
- * Sign in using FedCM (Federated Credential Management API)
62
- *
63
- * This provides a Google-style authentication experience:
64
- * - Browser shows native "Sign in with Oxy" prompt
65
- * - No redirect or secondary window required
66
- * - User approves → credential exchange happens in browser
67
- * - All apps automatically get SSO after first sign-in
68
- *
69
- * @param options - Authentication options
70
- * @returns Session with access token and user data
71
- * @throws {OxyAuthenticationError} If FedCM not supported or user cancels
72
- *
73
- * @example
74
- * ```typescript
75
- * try {
76
- * const session = await oxyServices.signInWithFedCM();
77
- * const user = session.user;
78
- * } catch (error) {
79
- * // Fallback to redirect auth
80
- * oxyServices.signInWithRedirect();
81
- * }
82
- * ```
83
- */
84
- signInWithFedCM(options?: FedCMAuthOptions): Promise<SessionLoginResponse>;
85
- /**
86
- * Run a single interactive FedCM credential request + token exchange for the
87
- * given (possibly undefined) loginHint. A successful exchange plants the
88
- * access token and persists the user id as the future loginHint — the hint is
89
- * therefore only ever stored after a GENUINELY successful sign-in, never
90
- * speculatively.
91
- *
92
- * @private
93
- */
94
- attemptInteractiveSignIn(options: FedCMAuthOptions, loginHint: string | undefined): Promise<SessionLoginResponse>;
95
- /**
96
- * Map a raw FedCM/exchange failure to a user-facing {@link OxyAuthenticationError}
97
- * (or pass it through). Extracted so the clear-and-retry path can reuse the
98
- * exact same error normalisation as the first attempt.
99
- *
100
- * @private
101
- */
102
- normalizeInteractiveSignInError(error: unknown): unknown;
103
- /**
104
- * Silent sign-in using FedCM
105
- *
106
- * Attempts to automatically re-authenticate the user without any UI.
107
- * This is what enables "instant sign-in" across all Oxy domains after
108
- * the user has signed in once.
109
- *
110
- * The browser will:
111
- * 1. Check if user has previously signed in to Oxy
112
- * 2. Check if user is still signed in at auth.oxy.so
113
- * 3. If yes, automatically provide credential without prompting
114
- *
115
- * @returns Session if user is already signed in, null otherwise
116
- *
117
- * @example
118
- * ```typescript
119
- * // On app startup
120
- * useEffect(() => {
121
- * const checkAuth = async () => {
122
- * const session = await oxyServices.silentSignInWithFedCM();
123
- * if (session) {
124
- * setUser(session.user);
125
- * } else {
126
- * // Show sign-in button
127
- * }
128
- * };
129
- * checkAuth();
130
- * }, []);
131
- * ```
132
- */
133
- silentSignInWithFedCM(): Promise<SessionLoginResponse | null>;
134
- /**
135
- * Request identity credential from browser using FedCM API
136
- *
137
- * Uses a global lock to prevent concurrent requests, as FedCM only
138
- * allows one navigator.credentials.get request at a time.
139
- *
140
- * Interactive requests (optional/required) wait for any silent request to finish first.
141
- *
142
- * @private
143
- */
144
- requestIdentityCredential(options: {
145
- configURL: string;
146
- clientId: string;
147
- nonce: string;
148
- context?: string;
149
- loginHint?: string;
150
- mediation?: "silent" | "optional" | "required";
151
- /**
152
- * FedCM request mode. The W3C spec values are `'active'` (user-gesture
153
- * button flow) and `'passive'` (browser-initiated widget flow). Chrome
154
- * 125–131 used the legacy names `'button'`/`'widget'`; those are accepted
155
- * here and mapped to the modern values, with an automatic legacy retry if
156
- * the running browser only understands the old enum.
157
- */
158
- mode?: FedCMRequestMode;
159
- }): Promise<FedCMTokenResult | null>;
160
- /**
161
- * Exchange FedCM ID token for Oxy session
162
- *
163
- * The ID token is a JWT issued by auth.oxy.so that proves the user's
164
- * identity. We exchange it for a full Oxy session with access token.
165
- *
166
- * @private
167
- */
168
- exchangeIdTokenForSession(idToken: string): Promise<SessionLoginResponse>;
169
- /**
170
- * Revoke FedCM credential (sign out)
171
- *
172
- * Uses IdentityCredential.disconnect() to tell the browser to forget
173
- * the RP-IdP-account association. This resets the "returning account"
174
- * state, which is required for silent mediation to work again.
175
- */
176
- revokeFedCMCredential(): Promise<void>;
177
- /**
178
- * Get configuration for FedCM
179
- *
180
- * @returns FedCM configuration with browser support info
181
- */
182
- getFedCMConfig(): FedCMConfig;
183
- /**
184
- * Generate a cryptographically secure local nonce for FedCM.
185
- *
186
- * NOTE: this is a *local* fallback only. The server-side `/fedcm/exchange`
187
- * endpoint requires the nonce embedded in the ID token to have been minted
188
- * by `POST /fedcm/nonce` (see {@link mintServerNonce}) and bound to this
189
- * origin. A purely local nonce will be rejected with `invalid_nonce`. Use
190
- * {@link getFedcmNonce}, which prefers a server-minted nonce and only falls
191
- * back to this generator when the mint endpoint is unreachable.
192
- *
193
- * @private
194
- */
195
- generateNonce(): string;
196
- /**
197
- * Mint a single-use, origin-bound nonce from the Oxy API.
198
- *
199
- * The FedCM ID token issued by the IdP embeds this nonce as the `nonce`
200
- * claim. When the consuming app calls `POST /fedcm/exchange`, the API burns
201
- * the nonce (atomic `usedAt` transition) and verifies it was minted for the
202
- * same origin as the token `aud`. This is the anti-replay binding required
203
- * by the API's H9 hardening — without a server-minted nonce the exchange
204
- * always fails.
205
- *
206
- * The browser attaches the `Origin` header automatically on this
207
- * cross-origin request, so the API binds the nonce to the calling app's
208
- * origin (which also becomes the FedCM `clientId`/token `aud`).
209
- *
210
- * @private
211
- */
212
- mintServerNonce(): Promise<string>;
213
- /**
214
- * Resolve the nonce to use for a FedCM credential request.
215
- *
216
- * Prefers a server-minted, origin-bound nonce (required for the token
217
- * exchange to succeed). If the mint endpoint is unreachable we fall back to
218
- * a locally generated nonce so the browser flow can still proceed; the
219
- * exchange may then fail server-side, but that is strictly better than
220
- * throwing before the browser ever shows its UI.
221
- *
222
- * @private
223
- */
224
- getFedcmNonce(): Promise<string>;
225
- /**
226
- * Get the client ID for this origin
227
- *
228
- * @private
229
- */
230
- getClientId(): string;
231
- /** @internal */
232
- getStoredLoginHint(): string | undefined;
233
- /** @internal */
234
- storeLoginHint(userId: string): void;
235
- /** @internal */
236
- clearLoginHint(): void;
237
- /**
238
- * List the authenticated user's authorized RP apps.
239
- *
240
- * Returns the intersection of the user's FedCM grants and the currently-
241
- * approved RP catalog — what powers the "Connected apps" management UI in
242
- * @oxyhq/services. Requires a real user session; service tokens are
243
- * rejected by the underlying endpoint.
244
- */
245
- listAuthorizedApps(): Promise<AuthorizedApp[]>;
246
- /**
247
- * Revoke the authenticated user's authorization for a specific RP origin.
248
- *
249
- * The next FedCM sign-in from that origin will require explicit re-consent.
250
- * The corresponding cache entry is invalidated so a subsequent
251
- * `listAuthorizedApps()` call sees fresh data.
252
- */
253
- revokeAuthorizedApp(origin: string): Promise<void>;
254
- httpService: import("../HttpService").HttpService;
255
- cloudURL: string;
256
- config: import("../OxyServices.base").OxyConfig;
257
- __resetTokensForTests(): void;
258
- makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
259
- getBaseURL(): string;
260
- getSessionBaseUrl(): string;
261
- getClient(): import("../HttpService").HttpService;
262
- createLinkedClient(config: import("../OxyServices.base").OxyConfig): import("..").LinkedHttpClient;
263
- getMetrics(): {
264
- totalRequests: number;
265
- successfulRequests: number;
266
- failedRequests: number;
267
- cacheHits: number;
268
- cacheMisses: number;
269
- averageResponseTime: number;
270
- };
271
- clearCache(): void;
272
- clearCacheEntry(key: string): void;
273
- clearCacheByPrefix(prefix: string): number;
274
- getCacheStats(): {
275
- size: number;
276
- hits: number;
277
- misses: number;
278
- hitRate: number;
279
- };
280
- getCloudURL(): string;
281
- setTokens(accessToken: string): void;
282
- clearTokens(): void;
283
- onTokensChanged(listener: (accessToken: string | null) => void): () => void;
284
- _cachedUserId: string | null | undefined;
285
- _cachedAccessToken: string | null;
286
- getCurrentUserId(): string | null;
287
- hasValidToken(): boolean;
288
- getAccessToken(): string | null;
289
- establishDeviceRefreshSlot(): Promise<number | null>;
290
- getAccessTokenExpiry(): number | null;
291
- waitForAuth(timeoutMs?: number): Promise<boolean>;
292
- withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
293
- maxRetries?: number;
294
- retryDelay?: number;
295
- authTimeoutMs?: number;
296
- }): Promise<T_1>;
297
- validate(): Promise<boolean>;
298
- handleError(error: unknown): Error;
299
- healthCheck(): Promise<{
300
- status: string;
301
- users?: number;
302
- timestamp?: string;
303
- [key: string]: any;
304
- }>;
305
- };
306
- readonly DEFAULT_CONFIG_URL: "https://auth.oxy.so/fedcm.json";
307
- readonly FEDCM_TIMEOUT: 15000;
308
- readonly FEDCM_SILENT_TIMEOUT: 4000;
309
- readonly FEDCM_ABORT_SETTLE_GRACE_MS: 500;
310
- /**
311
- * Check if FedCM is supported in the current browser
312
- */
313
- isFedCMSupported(): boolean;
314
- } & T;
315
- /**
316
- * Public summary of an RP application the user has authorized — mirrors the
317
- * `AuthorizedAppSummary` shape returned by `GET /fedcm/me/authorized-apps`.
318
- */
319
- export interface AuthorizedApp {
320
- /** Normalised RP origin. */
321
- origin: string;
322
- /** Friendly display name. */
323
- name: string;
324
- /** Optional human-readable description. */
325
- description?: string;
326
- /** ISO-8601 timestamp of when the user first authorized this RP. */
327
- firstGrantedAt: string;
328
- /** ISO-8601 timestamp of the most recent FedCM exchange for this user+RP. */
329
- lastUsedAt: string;
330
- }
331
- export { OxyServicesFedCMMixin as FedCMMixin };
@@ -1,92 +0,0 @@
1
- import type { OxyServicesBase } from '../OxyServices.base';
2
- import type { SessionLoginResponse } from '../models/session';
3
- export interface RedirectAuthOptions {
4
- redirectUri?: string;
5
- mode?: 'login' | 'signup';
6
- preserveUrl?: boolean;
7
- }
8
- /**
9
- * Redirect-based authentication without bearer tokens in URLs.
10
- *
11
- * The redirect fallback now uses the same central SSO code-return contract as
12
- * cold boot: the RP stores CSRF/destination state in sessionStorage, navigates
13
- * to the central IdP, receives only an opaque one-time code in the URL fragment,
14
- * and the provider's `sso-return` step exchanges that code for the real session.
15
- */
16
- export declare function OxyServicesRedirectAuthMixin<T extends typeof OxyServicesBase>(Base: T): {
17
- new (...args: any[]): {
18
- /**
19
- * Start a full-page redirect through the central SSO flow.
20
- *
21
- * No access token, refresh token, or session id is ever put in the URL or
22
- * localStorage. The caller's provider must run `consumeSsoReturn` on startup
23
- * to complete the code exchange and commit the session.
24
- */
25
- signInWithRedirect(options?: RedirectAuthOptions): void;
26
- signUpWithRedirect(options?: RedirectAuthOptions): void;
27
- /**
28
- * Legacy token-query callbacks are intentionally rejected. Modern providers
29
- * complete redirect auth through `consumeSsoReturn`, which accepts only
30
- * `#oxy_sso=ok&code=...`.
31
- */
32
- handleAuthCallback(): SessionLoginResponse | null;
33
- restoreSession(): boolean;
34
- clearStoredSession(): void;
35
- getStoredSessionId(): string | null;
36
- generateState(): string;
37
- generateNonce(): string;
38
- cleanAuthCallbackUrl(url: URL): void;
39
- httpService: import("../HttpService").HttpService;
40
- cloudURL: string;
41
- config: import("../OxyServices.base").OxyConfig;
42
- __resetTokensForTests(): void;
43
- makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
44
- getBaseURL(): string;
45
- getSessionBaseUrl(): string;
46
- getClient(): import("../HttpService").HttpService;
47
- createLinkedClient(config: import("../OxyServices.base").OxyConfig): import("..").LinkedHttpClient;
48
- getMetrics(): {
49
- totalRequests: number;
50
- successfulRequests: number;
51
- failedRequests: number;
52
- cacheHits: number;
53
- cacheMisses: number;
54
- averageResponseTime: number;
55
- };
56
- clearCache(): void;
57
- clearCacheEntry(key: string): void;
58
- clearCacheByPrefix(prefix: string): number;
59
- getCacheStats(): {
60
- size: number;
61
- hits: number;
62
- misses: number;
63
- hitRate: number;
64
- };
65
- getCloudURL(): string;
66
- setTokens(accessToken: string): void;
67
- clearTokens(): void;
68
- onTokensChanged(listener: (accessToken: string | null) => void): () => void;
69
- _cachedUserId: string | null | undefined;
70
- _cachedAccessToken: string | null;
71
- getCurrentUserId(): string | null;
72
- hasValidToken(): boolean;
73
- getAccessToken(): string | null;
74
- establishDeviceRefreshSlot(): Promise<number | null>;
75
- getAccessTokenExpiry(): number | null;
76
- waitForAuth(timeoutMs?: number): Promise<boolean>;
77
- withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
78
- maxRetries?: number;
79
- retryDelay?: number;
80
- authTimeoutMs?: number;
81
- }): Promise<T_1>;
82
- validate(): Promise<boolean>;
83
- handleError(error: unknown): Error;
84
- healthCheck(): Promise<{
85
- status: string;
86
- users?: number;
87
- timestamp?: string;
88
- [key: string]: any;
89
- }>;
90
- };
91
- } & T;
92
- export { OxyServicesRedirectAuthMixin as RedirectAuthMixin };
@@ -1,132 +0,0 @@
1
- import type { OxyServicesBase } from "../OxyServices.base";
2
- import type { SessionLoginResponse } from "../models/session";
3
- export interface SilentAuthOptions {
4
- timeout?: number;
5
- /**
6
- * Override the auth-web (IdP) origin used for the silent iframe, instead of
7
- * the instance's configured `resolveAuthUrl()`.
8
- *
9
- * Why this exists: an instance configured with the CENTRAL IdP
10
- * (`authWebUrl=https://auth.oxy.so`, for the opaque-code `/sso` bounce and
11
- * FedCM) cannot read the DURABLE per-apex `fedcm_session` cookie via the
12
- * central host — that cookie is first-party only on `auth.<rp-apex>` (e.g.
13
- * `auth.mention.earth`). The cross-domain reload-restore path must point the
14
- * `/auth/silent` iframe at the PER-APEX host so the cookie is same-site to
15
- * the RP page (first-party under Safari ITP / Firefox TCP) and the restore
16
- * is NOT a top-level navigation (no flash, works in a backgrounded tab).
17
- *
18
- * When provided this value is used BOTH for the iframe `src` AND for the
19
- * `postMessage` origin validation in {@link waitForIframeAuth}, so the
20
- * security check still matches the exact origin the iframe was loaded from.
21
- * Must be an absolute origin (`https://auth.<apex>`); ignored if empty.
22
- */
23
- authWebUrlOverride?: string;
24
- }
25
- /**
26
- * Cross-domain silent browser auth helpers.
27
- *
28
- * The clean session model supports FedCM, tokenless redirect SSO, and silent
29
- * iframe SSO. Bearer-token callback URLs are not part of this surface.
30
- */
31
- export declare function OxyServicesSilentAuthMixin<T extends typeof OxyServicesBase>(Base: T): {
32
- new (...args: any[]): {
33
- /** Resolve auth URL from config or static default (method, not getter — getters break in TS mixins) */
34
- resolveAuthUrl(): string;
35
- /**
36
- * Silent sign-in using hidden iframe
37
- *
38
- * Attempts to automatically re-authenticate the user without any UI.
39
- * This is what enables seamless SSO across all Oxy domains.
40
- *
41
- * How it works:
42
- * 1. Creates hidden iframe pointing to auth.oxy.so/silent-auth
43
- * 2. If user has valid session at auth.oxy.so, it exchanges an opaque SSO code
44
- * 3. If not, iframe responds with null (no error thrown)
45
- *
46
- * This should be called on app startup to check for existing sessions.
47
- *
48
- * @param options - Silent auth options
49
- * @returns Session if user is signed in, null otherwise
50
- *
51
- * @example
52
- * ```typescript
53
- * useEffect(() => {
54
- * const checkAuth = async () => {
55
- * const session = await oxyServices.silentSignIn();
56
- * if (session) {
57
- * setUser(session.user);
58
- * }
59
- * };
60
- * checkAuth();
61
- * }, []);
62
- * ```
63
- */
64
- silentSignIn(options?: SilentAuthOptions): Promise<SessionLoginResponse | null>;
65
- /**
66
- * Wait for authentication response from iframe
67
- *
68
- * @private
69
- */
70
- waitForIframeAuth(iframe: HTMLIFrameElement, timeout: number, expectedOrigin: string): Promise<SessionLoginResponse | null>;
71
- /**
72
- * Generate nonce for replay attack prevention
73
- *
74
- * @private
75
- */
76
- generateNonce(): string;
77
- httpService: import("../HttpService").HttpService;
78
- cloudURL: string;
79
- config: import("../OxyServices.base").OxyConfig;
80
- __resetTokensForTests(): void;
81
- makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
82
- getBaseURL(): string;
83
- getSessionBaseUrl(): string;
84
- getClient(): import("../HttpService").HttpService;
85
- createLinkedClient(config: import("../OxyServices.base").OxyConfig): import("..").LinkedHttpClient;
86
- getMetrics(): {
87
- totalRequests: number;
88
- successfulRequests: number;
89
- failedRequests: number;
90
- cacheHits: number;
91
- cacheMisses: number;
92
- averageResponseTime: number;
93
- };
94
- clearCache(): void;
95
- clearCacheEntry(key: string): void;
96
- clearCacheByPrefix(prefix: string): number;
97
- getCacheStats(): {
98
- size: number;
99
- hits: number;
100
- misses: number;
101
- hitRate: number;
102
- };
103
- getCloudURL(): string;
104
- setTokens(accessToken: string): void;
105
- clearTokens(): void;
106
- onTokensChanged(listener: (accessToken: string | null) => void): () => void;
107
- _cachedUserId: string | null | undefined;
108
- _cachedAccessToken: string | null;
109
- getCurrentUserId(): string | null;
110
- hasValidToken(): boolean;
111
- getAccessToken(): string | null;
112
- establishDeviceRefreshSlot(): Promise<number | null>;
113
- getAccessTokenExpiry(): number | null;
114
- waitForAuth(timeoutMs?: number): Promise<boolean>;
115
- withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
116
- maxRetries?: number;
117
- retryDelay?: number;
118
- authTimeoutMs?: number;
119
- }): Promise<T_1>;
120
- validate(): Promise<boolean>;
121
- handleError(error: unknown): Error;
122
- healthCheck(): Promise<{
123
- status: string;
124
- users?: number;
125
- timestamp?: string;
126
- [key: string]: any;
127
- }>;
128
- };
129
- readonly DEFAULT_AUTH_URL: "https://auth.oxy.so";
130
- readonly SILENT_TIMEOUT: 5000;
131
- } & T;
132
- export { OxyServicesSilentAuthMixin as SilentAuthMixin };