@oxyhq/core 1.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 (277) hide show
  1. package/README.md +50 -0
  2. package/dist/cjs/AuthManager.js +361 -0
  3. package/dist/cjs/CrossDomainAuth.js +258 -0
  4. package/dist/cjs/HttpService.js +618 -0
  5. package/dist/cjs/OxyServices.base.js +263 -0
  6. package/dist/cjs/OxyServices.errors.js +22 -0
  7. package/dist/cjs/OxyServices.js +63 -0
  8. package/dist/cjs/constants/version.js +16 -0
  9. package/dist/cjs/crypto/index.js +20 -0
  10. package/dist/cjs/crypto/keyManager.js +887 -0
  11. package/dist/cjs/crypto/polyfill.js +64 -0
  12. package/dist/cjs/crypto/recoveryPhrase.js +169 -0
  13. package/dist/cjs/crypto/signatureService.js +296 -0
  14. package/dist/cjs/i18n/index.js +73 -0
  15. package/dist/cjs/i18n/locales/ar-SA.json +120 -0
  16. package/dist/cjs/i18n/locales/ca-ES.json +120 -0
  17. package/dist/cjs/i18n/locales/de-DE.json +120 -0
  18. package/dist/cjs/i18n/locales/en-US.json +956 -0
  19. package/dist/cjs/i18n/locales/es-ES.json +944 -0
  20. package/dist/cjs/i18n/locales/fr-FR.json +120 -0
  21. package/dist/cjs/i18n/locales/it-IT.json +120 -0
  22. package/dist/cjs/i18n/locales/ja-JP.json +119 -0
  23. package/dist/cjs/i18n/locales/ko-KR.json +120 -0
  24. package/dist/cjs/i18n/locales/locales/ar-SA.json +120 -0
  25. package/dist/cjs/i18n/locales/locales/ca-ES.json +120 -0
  26. package/dist/cjs/i18n/locales/locales/de-DE.json +120 -0
  27. package/dist/cjs/i18n/locales/locales/en-US.json +956 -0
  28. package/dist/cjs/i18n/locales/locales/es-ES.json +944 -0
  29. package/dist/cjs/i18n/locales/locales/fr-FR.json +120 -0
  30. package/dist/cjs/i18n/locales/locales/it-IT.json +120 -0
  31. package/dist/cjs/i18n/locales/locales/ja-JP.json +119 -0
  32. package/dist/cjs/i18n/locales/locales/ko-KR.json +120 -0
  33. package/dist/cjs/i18n/locales/locales/pt-PT.json +120 -0
  34. package/dist/cjs/i18n/locales/locales/zh-CN.json +120 -0
  35. package/dist/cjs/i18n/locales/pt-PT.json +120 -0
  36. package/dist/cjs/i18n/locales/zh-CN.json +120 -0
  37. package/dist/cjs/index.js +153 -0
  38. package/dist/cjs/mixins/OxyServices.analytics.js +49 -0
  39. package/dist/cjs/mixins/OxyServices.assets.js +380 -0
  40. package/dist/cjs/mixins/OxyServices.auth.js +259 -0
  41. package/dist/cjs/mixins/OxyServices.developer.js +97 -0
  42. package/dist/cjs/mixins/OxyServices.devices.js +116 -0
  43. package/dist/cjs/mixins/OxyServices.features.js +309 -0
  44. package/dist/cjs/mixins/OxyServices.fedcm.js +435 -0
  45. package/dist/cjs/mixins/OxyServices.karma.js +108 -0
  46. package/dist/cjs/mixins/OxyServices.language.js +154 -0
  47. package/dist/cjs/mixins/OxyServices.location.js +43 -0
  48. package/dist/cjs/mixins/OxyServices.payment.js +158 -0
  49. package/dist/cjs/mixins/OxyServices.popup.js +371 -0
  50. package/dist/cjs/mixins/OxyServices.privacy.js +162 -0
  51. package/dist/cjs/mixins/OxyServices.redirect.js +345 -0
  52. package/dist/cjs/mixins/OxyServices.security.js +81 -0
  53. package/dist/cjs/mixins/OxyServices.user.js +355 -0
  54. package/dist/cjs/mixins/OxyServices.utility.js +156 -0
  55. package/dist/cjs/mixins/index.js +79 -0
  56. package/dist/cjs/mixins/mixinHelpers.js +53 -0
  57. package/dist/cjs/models/interfaces.js +20 -0
  58. package/dist/cjs/models/session.js +2 -0
  59. package/dist/cjs/shared/index.js +70 -0
  60. package/dist/cjs/shared/utils/colorUtils.js +153 -0
  61. package/dist/cjs/shared/utils/debugUtils.js +73 -0
  62. package/dist/cjs/shared/utils/errorUtils.js +183 -0
  63. package/dist/cjs/shared/utils/index.js +49 -0
  64. package/dist/cjs/shared/utils/networkUtils.js +183 -0
  65. package/dist/cjs/shared/utils/themeUtils.js +106 -0
  66. package/dist/cjs/utils/apiUtils.js +61 -0
  67. package/dist/cjs/utils/asyncUtils.js +194 -0
  68. package/dist/cjs/utils/cache.js +226 -0
  69. package/dist/cjs/utils/deviceManager.js +205 -0
  70. package/dist/cjs/utils/errorUtils.js +154 -0
  71. package/dist/cjs/utils/index.js +26 -0
  72. package/dist/cjs/utils/languageUtils.js +165 -0
  73. package/dist/cjs/utils/loggerUtils.js +126 -0
  74. package/dist/cjs/utils/platform.js +144 -0
  75. package/dist/cjs/utils/requestUtils.js +209 -0
  76. package/dist/cjs/utils/sessionUtils.js +181 -0
  77. package/dist/cjs/utils/validationUtils.js +173 -0
  78. package/dist/esm/AuthManager.js +356 -0
  79. package/dist/esm/CrossDomainAuth.js +253 -0
  80. package/dist/esm/HttpService.js +614 -0
  81. package/dist/esm/OxyServices.base.js +259 -0
  82. package/dist/esm/OxyServices.errors.js +17 -0
  83. package/dist/esm/OxyServices.js +59 -0
  84. package/dist/esm/constants/version.js +13 -0
  85. package/dist/esm/crypto/index.js +13 -0
  86. package/dist/esm/crypto/keyManager.js +850 -0
  87. package/dist/esm/crypto/polyfill.js +61 -0
  88. package/dist/esm/crypto/recoveryPhrase.js +132 -0
  89. package/dist/esm/crypto/signatureService.js +259 -0
  90. package/dist/esm/i18n/index.js +69 -0
  91. package/dist/esm/i18n/locales/ar-SA.json +120 -0
  92. package/dist/esm/i18n/locales/ca-ES.json +120 -0
  93. package/dist/esm/i18n/locales/de-DE.json +120 -0
  94. package/dist/esm/i18n/locales/en-US.json +956 -0
  95. package/dist/esm/i18n/locales/es-ES.json +944 -0
  96. package/dist/esm/i18n/locales/fr-FR.json +120 -0
  97. package/dist/esm/i18n/locales/it-IT.json +120 -0
  98. package/dist/esm/i18n/locales/ja-JP.json +119 -0
  99. package/dist/esm/i18n/locales/ko-KR.json +120 -0
  100. package/dist/esm/i18n/locales/locales/ar-SA.json +120 -0
  101. package/dist/esm/i18n/locales/locales/ca-ES.json +120 -0
  102. package/dist/esm/i18n/locales/locales/de-DE.json +120 -0
  103. package/dist/esm/i18n/locales/locales/en-US.json +956 -0
  104. package/dist/esm/i18n/locales/locales/es-ES.json +944 -0
  105. package/dist/esm/i18n/locales/locales/fr-FR.json +120 -0
  106. package/dist/esm/i18n/locales/locales/it-IT.json +120 -0
  107. package/dist/esm/i18n/locales/locales/ja-JP.json +119 -0
  108. package/dist/esm/i18n/locales/locales/ko-KR.json +120 -0
  109. package/dist/esm/i18n/locales/locales/pt-PT.json +120 -0
  110. package/dist/esm/i18n/locales/locales/zh-CN.json +120 -0
  111. package/dist/esm/i18n/locales/pt-PT.json +120 -0
  112. package/dist/esm/i18n/locales/zh-CN.json +120 -0
  113. package/dist/esm/index.js +55 -0
  114. package/dist/esm/mixins/OxyServices.analytics.js +46 -0
  115. package/dist/esm/mixins/OxyServices.assets.js +377 -0
  116. package/dist/esm/mixins/OxyServices.auth.js +256 -0
  117. package/dist/esm/mixins/OxyServices.developer.js +94 -0
  118. package/dist/esm/mixins/OxyServices.devices.js +113 -0
  119. package/dist/esm/mixins/OxyServices.features.js +306 -0
  120. package/dist/esm/mixins/OxyServices.fedcm.js +433 -0
  121. package/dist/esm/mixins/OxyServices.karma.js +105 -0
  122. package/dist/esm/mixins/OxyServices.language.js +118 -0
  123. package/dist/esm/mixins/OxyServices.location.js +40 -0
  124. package/dist/esm/mixins/OxyServices.payment.js +155 -0
  125. package/dist/esm/mixins/OxyServices.popup.js +369 -0
  126. package/dist/esm/mixins/OxyServices.privacy.js +159 -0
  127. package/dist/esm/mixins/OxyServices.redirect.js +343 -0
  128. package/dist/esm/mixins/OxyServices.security.js +78 -0
  129. package/dist/esm/mixins/OxyServices.user.js +352 -0
  130. package/dist/esm/mixins/OxyServices.utility.js +153 -0
  131. package/dist/esm/mixins/index.js +76 -0
  132. package/dist/esm/mixins/mixinHelpers.js +48 -0
  133. package/dist/esm/models/interfaces.js +17 -0
  134. package/dist/esm/models/session.js +1 -0
  135. package/dist/esm/shared/index.js +31 -0
  136. package/dist/esm/shared/utils/colorUtils.js +143 -0
  137. package/dist/esm/shared/utils/debugUtils.js +65 -0
  138. package/dist/esm/shared/utils/errorUtils.js +170 -0
  139. package/dist/esm/shared/utils/index.js +15 -0
  140. package/dist/esm/shared/utils/networkUtils.js +173 -0
  141. package/dist/esm/shared/utils/themeUtils.js +98 -0
  142. package/dist/esm/utils/apiUtils.js +55 -0
  143. package/dist/esm/utils/asyncUtils.js +179 -0
  144. package/dist/esm/utils/cache.js +218 -0
  145. package/dist/esm/utils/deviceManager.js +168 -0
  146. package/dist/esm/utils/errorUtils.js +146 -0
  147. package/dist/esm/utils/index.js +7 -0
  148. package/dist/esm/utils/languageUtils.js +158 -0
  149. package/dist/esm/utils/loggerUtils.js +115 -0
  150. package/dist/esm/utils/platform.js +102 -0
  151. package/dist/esm/utils/requestUtils.js +203 -0
  152. package/dist/esm/utils/sessionUtils.js +171 -0
  153. package/dist/esm/utils/validationUtils.js +153 -0
  154. package/dist/types/AuthManager.d.ts +143 -0
  155. package/dist/types/CrossDomainAuth.d.ts +160 -0
  156. package/dist/types/HttpService.d.ts +163 -0
  157. package/dist/types/OxyServices.base.d.ts +126 -0
  158. package/dist/types/OxyServices.d.ts +81 -0
  159. package/dist/types/OxyServices.errors.d.ts +11 -0
  160. package/dist/types/constants/version.d.ts +13 -0
  161. package/dist/types/crypto/index.d.ts +11 -0
  162. package/dist/types/crypto/keyManager.d.ts +189 -0
  163. package/dist/types/crypto/polyfill.d.ts +11 -0
  164. package/dist/types/crypto/recoveryPhrase.d.ts +58 -0
  165. package/dist/types/crypto/signatureService.d.ts +86 -0
  166. package/dist/types/i18n/index.d.ts +3 -0
  167. package/dist/types/index.d.ts +50 -0
  168. package/dist/types/mixins/OxyServices.analytics.d.ts +66 -0
  169. package/dist/types/mixins/OxyServices.assets.d.ts +135 -0
  170. package/dist/types/mixins/OxyServices.auth.d.ts +186 -0
  171. package/dist/types/mixins/OxyServices.developer.d.ts +99 -0
  172. package/dist/types/mixins/OxyServices.devices.d.ts +96 -0
  173. package/dist/types/mixins/OxyServices.features.d.ts +228 -0
  174. package/dist/types/mixins/OxyServices.fedcm.d.ts +200 -0
  175. package/dist/types/mixins/OxyServices.karma.d.ts +85 -0
  176. package/dist/types/mixins/OxyServices.language.d.ts +81 -0
  177. package/dist/types/mixins/OxyServices.location.d.ts +64 -0
  178. package/dist/types/mixins/OxyServices.payment.d.ts +111 -0
  179. package/dist/types/mixins/OxyServices.popup.d.ts +205 -0
  180. package/dist/types/mixins/OxyServices.privacy.d.ts +122 -0
  181. package/dist/types/mixins/OxyServices.redirect.d.ts +245 -0
  182. package/dist/types/mixins/OxyServices.security.d.ts +78 -0
  183. package/dist/types/mixins/OxyServices.user.d.ts +182 -0
  184. package/dist/types/mixins/OxyServices.utility.d.ts +93 -0
  185. package/dist/types/mixins/index.d.ts +30 -0
  186. package/dist/types/mixins/mixinHelpers.d.ts +31 -0
  187. package/dist/types/models/interfaces.d.ts +415 -0
  188. package/dist/types/models/session.d.ts +27 -0
  189. package/dist/types/shared/index.d.ts +28 -0
  190. package/dist/types/shared/utils/colorUtils.d.ts +104 -0
  191. package/dist/types/shared/utils/debugUtils.d.ts +48 -0
  192. package/dist/types/shared/utils/errorUtils.d.ts +97 -0
  193. package/dist/types/shared/utils/index.d.ts +13 -0
  194. package/dist/types/shared/utils/networkUtils.d.ts +139 -0
  195. package/dist/types/shared/utils/themeUtils.d.ts +90 -0
  196. package/dist/types/utils/apiUtils.d.ts +53 -0
  197. package/dist/types/utils/asyncUtils.d.ts +58 -0
  198. package/dist/types/utils/cache.d.ts +127 -0
  199. package/dist/types/utils/deviceManager.d.ts +65 -0
  200. package/dist/types/utils/errorUtils.d.ts +46 -0
  201. package/dist/types/utils/index.d.ts +6 -0
  202. package/dist/types/utils/languageUtils.d.ts +37 -0
  203. package/dist/types/utils/loggerUtils.d.ts +48 -0
  204. package/dist/types/utils/platform.d.ts +40 -0
  205. package/dist/types/utils/requestUtils.d.ts +123 -0
  206. package/dist/types/utils/sessionUtils.d.ts +54 -0
  207. package/dist/types/utils/validationUtils.d.ts +85 -0
  208. package/package.json +84 -0
  209. package/src/AuthManager.ts +436 -0
  210. package/src/CrossDomainAuth.ts +307 -0
  211. package/src/HttpService.ts +752 -0
  212. package/src/OxyServices.base.ts +334 -0
  213. package/src/OxyServices.errors.ts +26 -0
  214. package/src/OxyServices.ts +129 -0
  215. package/src/constants/version.ts +15 -0
  216. package/src/crypto/index.ts +25 -0
  217. package/src/crypto/keyManager.ts +962 -0
  218. package/src/crypto/polyfill.ts +70 -0
  219. package/src/crypto/recoveryPhrase.ts +166 -0
  220. package/src/crypto/signatureService.ts +323 -0
  221. package/src/i18n/index.ts +75 -0
  222. package/src/i18n/locales/ar-SA.json +120 -0
  223. package/src/i18n/locales/ca-ES.json +120 -0
  224. package/src/i18n/locales/de-DE.json +120 -0
  225. package/src/i18n/locales/en-US.json +956 -0
  226. package/src/i18n/locales/es-ES.json +944 -0
  227. package/src/i18n/locales/fr-FR.json +120 -0
  228. package/src/i18n/locales/it-IT.json +120 -0
  229. package/src/i18n/locales/ja-JP.json +119 -0
  230. package/src/i18n/locales/ko-KR.json +120 -0
  231. package/src/i18n/locales/pt-PT.json +120 -0
  232. package/src/i18n/locales/zh-CN.json +120 -0
  233. package/src/index.ts +153 -0
  234. package/src/mixins/OxyServices.analytics.ts +53 -0
  235. package/src/mixins/OxyServices.assets.ts +412 -0
  236. package/src/mixins/OxyServices.auth.ts +358 -0
  237. package/src/mixins/OxyServices.developer.ts +114 -0
  238. package/src/mixins/OxyServices.devices.ts +119 -0
  239. package/src/mixins/OxyServices.features.ts +428 -0
  240. package/src/mixins/OxyServices.fedcm.ts +494 -0
  241. package/src/mixins/OxyServices.karma.ts +111 -0
  242. package/src/mixins/OxyServices.language.ts +127 -0
  243. package/src/mixins/OxyServices.location.ts +46 -0
  244. package/src/mixins/OxyServices.payment.ts +163 -0
  245. package/src/mixins/OxyServices.popup.ts +443 -0
  246. package/src/mixins/OxyServices.privacy.ts +182 -0
  247. package/src/mixins/OxyServices.redirect.ts +397 -0
  248. package/src/mixins/OxyServices.security.ts +103 -0
  249. package/src/mixins/OxyServices.user.ts +392 -0
  250. package/src/mixins/OxyServices.utility.ts +191 -0
  251. package/src/mixins/index.ts +91 -0
  252. package/src/mixins/mixinHelpers.ts +69 -0
  253. package/src/models/interfaces.ts +511 -0
  254. package/src/models/session.ts +30 -0
  255. package/src/shared/index.ts +82 -0
  256. package/src/shared/utils/colorUtils.ts +155 -0
  257. package/src/shared/utils/debugUtils.ts +73 -0
  258. package/src/shared/utils/errorUtils.ts +181 -0
  259. package/src/shared/utils/index.ts +59 -0
  260. package/src/shared/utils/networkUtils.ts +248 -0
  261. package/src/shared/utils/themeUtils.ts +115 -0
  262. package/src/types/bip39.d.ts +32 -0
  263. package/src/types/buffer.d.ts +97 -0
  264. package/src/types/color.d.ts +20 -0
  265. package/src/types/elliptic.d.ts +62 -0
  266. package/src/utils/apiUtils.ts +88 -0
  267. package/src/utils/asyncUtils.ts +252 -0
  268. package/src/utils/cache.ts +264 -0
  269. package/src/utils/deviceManager.ts +198 -0
  270. package/src/utils/errorUtils.ts +216 -0
  271. package/src/utils/index.ts +21 -0
  272. package/src/utils/languageUtils.ts +174 -0
  273. package/src/utils/loggerUtils.ts +153 -0
  274. package/src/utils/platform.ts +117 -0
  275. package/src/utils/requestUtils.ts +237 -0
  276. package/src/utils/sessionUtils.ts +206 -0
  277. package/src/utils/validationUtils.ts +174 -0
@@ -0,0 +1,371 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OxyServicesPopupAuthMixin = OxyServicesPopupAuthMixin;
4
+ exports.PopupAuthMixin = OxyServicesPopupAuthMixin;
5
+ const OxyServices_errors_1 = require("../OxyServices.errors");
6
+ const debugUtils_1 = require("../shared/utils/debugUtils");
7
+ const debug = (0, debugUtils_1.createDebugLogger)('PopupAuth');
8
+ /**
9
+ * Popup-based Cross-Domain Authentication Mixin
10
+ *
11
+ * Implements OAuth2-style authentication using popup windows and postMessage.
12
+ * This is the primary authentication method for modern browsers, providing a
13
+ * Google-like experience without full page redirects.
14
+ *
15
+ * Flow:
16
+ * 1. Opens small popup window to auth.oxy.so
17
+ * 2. User signs in (auth.oxy.so sets its own first-party cookie)
18
+ * 3. auth.oxy.so sends token back via postMessage
19
+ * 4. Popup closes, parent app has the session
20
+ *
21
+ * Features:
22
+ * - No full page redirect (preserves app state)
23
+ * - Works across different domains (homiio.com, mention.earth, etc.)
24
+ * - Silent refresh using hidden iframe for seamless SSO
25
+ * - CSRF protection via state parameter
26
+ * - XSS protection via origin validation
27
+ *
28
+ * Browser Support: All modern browsers (IE11+)
29
+ */
30
+ function OxyServicesPopupAuthMixin(Base) {
31
+ var _a;
32
+ return _a = class extends Base {
33
+ constructor(...args) {
34
+ super(...args);
35
+ }
36
+ /**
37
+ * Sign in using popup window
38
+ *
39
+ * Opens a centered popup window to auth.oxy.so where the user can sign in.
40
+ * The popup automatically closes after successful authentication and the
41
+ * session is returned to the parent window.
42
+ *
43
+ * @param options - Popup configuration options
44
+ * @returns Session with access token and user data
45
+ * @throws {OxyAuthenticationError} If popup is blocked or auth fails
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const handleSignIn = async () => {
50
+ * try {
51
+ * const session = await oxyServices.signInWithPopup();
52
+ * console.log('Signed in:', session.user);
53
+ * } catch (error) {
54
+ * if (error.message.includes('blocked')) {
55
+ * alert('Please allow popups for this site');
56
+ * }
57
+ * }
58
+ * };
59
+ * ```
60
+ */
61
+ async signInWithPopup(options = {}) {
62
+ if (typeof window === 'undefined') {
63
+ throw new OxyServices_errors_1.OxyAuthenticationError('Popup authentication requires browser environment');
64
+ }
65
+ const state = this.generateState();
66
+ const nonce = this.generateNonce();
67
+ // Store state for CSRF protection
68
+ this.storeAuthState(state, nonce);
69
+ const width = options.width || this.constructor.POPUP_WIDTH;
70
+ const height = options.height || this.constructor.POPUP_HEIGHT;
71
+ const timeout = options.timeout || this.constructor.POPUP_TIMEOUT;
72
+ const mode = options.mode || 'login';
73
+ const authUrl = this.buildAuthUrl({
74
+ mode,
75
+ state,
76
+ nonce,
77
+ clientId: window.location.origin,
78
+ redirectUri: `${this.constructor.AUTH_URL}/auth/callback`,
79
+ });
80
+ const popup = this.openCenteredPopup(authUrl, 'Oxy Sign In', width, height);
81
+ if (!popup) {
82
+ throw new OxyServices_errors_1.OxyAuthenticationError('Popup blocked. Please allow popups for this site and try again.');
83
+ }
84
+ try {
85
+ const session = await this.waitForPopupAuth(popup, state, timeout);
86
+ // Store access token if present
87
+ if (session && session.accessToken) {
88
+ this.httpService.setTokens(session.accessToken);
89
+ }
90
+ // Fetch user data using the session ID
91
+ // The callback page only sends sessionId/accessToken, not user data
92
+ if (session && session.sessionId && !session.user) {
93
+ try {
94
+ const userData = await this.makeRequest('GET', `/api/session/user/${session.sessionId}`, undefined, { cache: false });
95
+ if (userData) {
96
+ session.user = userData;
97
+ }
98
+ }
99
+ catch (userError) {
100
+ debug.warn('Failed to fetch user data:', userError);
101
+ // Continue without user data - caller can fetch separately
102
+ }
103
+ }
104
+ return session;
105
+ }
106
+ catch (error) {
107
+ throw error;
108
+ }
109
+ finally {
110
+ this.clearAuthState(state);
111
+ }
112
+ }
113
+ /**
114
+ * Sign up using popup window
115
+ *
116
+ * Same as signInWithPopup but opens the signup page by default.
117
+ *
118
+ * @param options - Popup configuration options
119
+ * @returns Session with access token and user data
120
+ */
121
+ async signUpWithPopup(options = {}) {
122
+ return this.signInWithPopup({ ...options, mode: 'signup' });
123
+ }
124
+ /**
125
+ * Silent sign-in using hidden iframe
126
+ *
127
+ * Attempts to automatically re-authenticate the user without any UI.
128
+ * This is what enables seamless SSO across all Oxy domains.
129
+ *
130
+ * How it works:
131
+ * 1. Creates hidden iframe pointing to auth.oxy.so/silent-auth
132
+ * 2. If user has valid session at auth.oxy.so, it sends token via postMessage
133
+ * 3. If not, iframe responds with null (no error thrown)
134
+ *
135
+ * This should be called on app startup to check for existing sessions.
136
+ *
137
+ * @param options - Silent auth options
138
+ * @returns Session if user is signed in, null otherwise
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * useEffect(() => {
143
+ * const checkAuth = async () => {
144
+ * const session = await oxyServices.silentSignIn();
145
+ * if (session) {
146
+ * setUser(session.user);
147
+ * }
148
+ * };
149
+ * checkAuth();
150
+ * }, []);
151
+ * ```
152
+ */
153
+ async silentSignIn(options = {}) {
154
+ if (typeof window === 'undefined') {
155
+ return null;
156
+ }
157
+ const timeout = options.timeout || this.constructor.SILENT_TIMEOUT;
158
+ const nonce = this.generateNonce();
159
+ const clientId = window.location.origin;
160
+ const iframe = document.createElement('iframe');
161
+ iframe.style.display = 'none';
162
+ iframe.style.position = 'absolute';
163
+ iframe.style.width = '0';
164
+ iframe.style.height = '0';
165
+ iframe.style.border = 'none';
166
+ const silentUrl = `${this.constructor.AUTH_URL}/auth/silent?` + `client_id=${encodeURIComponent(clientId)}&` + `nonce=${nonce}`;
167
+ iframe.src = silentUrl;
168
+ document.body.appendChild(iframe);
169
+ try {
170
+ const session = await this.waitForIframeAuth(iframe, timeout, clientId);
171
+ if (session && session.accessToken) {
172
+ this.httpService.setTokens(session.accessToken);
173
+ }
174
+ return session;
175
+ }
176
+ catch (error) {
177
+ return null;
178
+ }
179
+ finally {
180
+ document.body.removeChild(iframe);
181
+ }
182
+ }
183
+ /**
184
+ * Open a centered popup window
185
+ *
186
+ * @private
187
+ */
188
+ openCenteredPopup(url, title, width, height) {
189
+ const left = window.screenX + (window.outerWidth - width) / 2;
190
+ const top = window.screenY + (window.outerHeight - height) / 2;
191
+ const features = [
192
+ `width=${width}`,
193
+ `height=${height}`,
194
+ `left=${left}`,
195
+ `top=${top}`,
196
+ 'toolbar=no',
197
+ 'menubar=no',
198
+ 'scrollbars=yes',
199
+ 'resizable=yes',
200
+ 'status=no',
201
+ 'location=no',
202
+ ].join(',');
203
+ return window.open(url, title, features);
204
+ }
205
+ /**
206
+ * Wait for authentication response from popup
207
+ *
208
+ * @private
209
+ */
210
+ async waitForPopupAuth(popup, expectedState, timeout) {
211
+ return new Promise((resolve, reject) => {
212
+ const timeoutId = setTimeout(() => {
213
+ cleanup();
214
+ reject(new OxyServices_errors_1.OxyAuthenticationError('Authentication timeout'));
215
+ }, timeout);
216
+ const messageHandler = (event) => {
217
+ const authUrl = this.constructor.AUTH_URL;
218
+ // Log all messages for debugging
219
+ if (event.data && typeof event.data === 'object' && event.data.type) {
220
+ debug.log('Message received:', {
221
+ origin: event.origin,
222
+ expectedOrigin: authUrl,
223
+ type: event.data.type,
224
+ hasSession: !!event.data.session,
225
+ hasError: !!event.data.error,
226
+ });
227
+ }
228
+ // CRITICAL: Verify origin to prevent XSS attacks
229
+ if (event.origin !== authUrl) {
230
+ return;
231
+ }
232
+ const { type, state, session, error } = event.data;
233
+ if (type !== 'oxy_auth_response') {
234
+ return;
235
+ }
236
+ debug.log('Valid auth response:', { state, expectedState, hasSession: !!session, error });
237
+ // Verify state parameter to prevent CSRF attacks
238
+ if (state !== expectedState) {
239
+ cleanup();
240
+ debug.error('State mismatch');
241
+ reject(new OxyServices_errors_1.OxyAuthenticationError('Invalid state parameter. Possible CSRF attack.'));
242
+ return;
243
+ }
244
+ cleanup();
245
+ if (error) {
246
+ debug.error('Auth error:', error);
247
+ reject(new OxyServices_errors_1.OxyAuthenticationError(error));
248
+ }
249
+ else if (session) {
250
+ debug.log('Session received successfully');
251
+ resolve(session);
252
+ }
253
+ else {
254
+ debug.error('No session in response');
255
+ reject(new OxyServices_errors_1.OxyAuthenticationError('No session received from authentication server'));
256
+ }
257
+ };
258
+ // Poll to detect if user closed the popup
259
+ const pollInterval = setInterval(() => {
260
+ if (popup.closed) {
261
+ cleanup();
262
+ reject(new OxyServices_errors_1.OxyAuthenticationError('Authentication cancelled by user'));
263
+ }
264
+ }, 500);
265
+ const cleanup = () => {
266
+ clearTimeout(timeoutId);
267
+ clearInterval(pollInterval);
268
+ window.removeEventListener('message', messageHandler);
269
+ if (!popup.closed) {
270
+ popup.close();
271
+ }
272
+ };
273
+ window.addEventListener('message', messageHandler);
274
+ });
275
+ }
276
+ /**
277
+ * Wait for authentication response from iframe
278
+ *
279
+ * @private
280
+ */
281
+ async waitForIframeAuth(iframe, timeout, expectedOrigin) {
282
+ return new Promise((resolve) => {
283
+ const timeoutId = setTimeout(() => {
284
+ cleanup();
285
+ resolve(null); // Silent failure - don't throw
286
+ }, timeout);
287
+ const messageHandler = (event) => {
288
+ // Verify origin
289
+ if (event.origin !== this.constructor.AUTH_URL) {
290
+ return;
291
+ }
292
+ const { type, session } = event.data;
293
+ if (type !== 'oxy_silent_auth') {
294
+ return;
295
+ }
296
+ cleanup();
297
+ resolve(session || null);
298
+ };
299
+ const cleanup = () => {
300
+ clearTimeout(timeoutId);
301
+ window.removeEventListener('message', messageHandler);
302
+ };
303
+ window.addEventListener('message', messageHandler);
304
+ });
305
+ }
306
+ /**
307
+ * Build authentication URL with query parameters
308
+ *
309
+ * @private
310
+ */
311
+ buildAuthUrl(params) {
312
+ const url = new URL(`${this.constructor.AUTH_URL}/${params.mode}`);
313
+ url.searchParams.set('response_type', 'token');
314
+ url.searchParams.set('client_id', params.clientId);
315
+ url.searchParams.set('redirect_uri', params.redirectUri);
316
+ url.searchParams.set('state', params.state);
317
+ url.searchParams.set('nonce', params.nonce);
318
+ return url.toString();
319
+ }
320
+ /**
321
+ * Generate cryptographically secure state for CSRF protection
322
+ *
323
+ * @private
324
+ */
325
+ generateState() {
326
+ if (typeof window !== 'undefined' && window.crypto && window.crypto.randomUUID) {
327
+ return window.crypto.randomUUID();
328
+ }
329
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
330
+ }
331
+ /**
332
+ * Generate nonce for replay attack prevention
333
+ *
334
+ * @private
335
+ */
336
+ generateNonce() {
337
+ if (typeof window !== 'undefined' && window.crypto && window.crypto.randomUUID) {
338
+ return window.crypto.randomUUID();
339
+ }
340
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
341
+ }
342
+ /**
343
+ * Store auth state in session storage
344
+ *
345
+ * @private
346
+ */
347
+ storeAuthState(state, nonce) {
348
+ if (typeof window !== 'undefined' && window.sessionStorage) {
349
+ sessionStorage.setItem(`oxy_auth_state_${state}`, JSON.stringify({ nonce, timestamp: Date.now() }));
350
+ }
351
+ }
352
+ /**
353
+ * Clear auth state from session storage
354
+ *
355
+ * @private
356
+ */
357
+ clearAuthState(state) {
358
+ if (typeof window !== 'undefined' && window.sessionStorage) {
359
+ sessionStorage.removeItem(`oxy_auth_state_${state}`);
360
+ }
361
+ }
362
+ },
363
+ _a.AUTH_URL = 'https://auth.oxy.so',
364
+ _a.POPUP_WIDTH = 500,
365
+ _a.POPUP_HEIGHT = 700,
366
+ _a.POPUP_TIMEOUT = 60000 // 1 minute
367
+ ,
368
+ _a.SILENT_TIMEOUT = 5000 // 5 seconds
369
+ ,
370
+ _a;
371
+ }
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OxyServicesPrivacyMixin = OxyServicesPrivacyMixin;
4
+ function OxyServicesPrivacyMixin(Base) {
5
+ return class extends Base {
6
+ constructor(...args) {
7
+ super(...args);
8
+ }
9
+ /**
10
+ * Extract user ID from blocked/restricted user object
11
+ */
12
+ extractUserId(userIdField) {
13
+ return typeof userIdField === 'string' ? userIdField : userIdField._id;
14
+ }
15
+ /**
16
+ * Check if a user is in a list (blocked or restricted)
17
+ */
18
+ async isUserInList(userId, getUserList, getIdField) {
19
+ try {
20
+ if (!userId) {
21
+ return false;
22
+ }
23
+ const users = await getUserList();
24
+ return users.some(item => {
25
+ const itemId = this.extractUserId(getIdField(item));
26
+ return itemId === userId;
27
+ });
28
+ }
29
+ catch (error) {
30
+ // If there's an error, assume not in list to avoid breaking functionality
31
+ if (__DEV__) {
32
+ console.warn('Error checking user list:', error);
33
+ }
34
+ return false;
35
+ }
36
+ }
37
+ // ============================================================================
38
+ // BLOCKED USERS METHODS
39
+ // ============================================================================
40
+ /**
41
+ * Get list of blocked users
42
+ * @returns Array of blocked users
43
+ */
44
+ async getBlockedUsers() {
45
+ try {
46
+ return await this.makeRequest('GET', '/api/privacy/blocked', undefined, {
47
+ cache: true,
48
+ cacheTTL: 1 * 60 * 1000, // 1 minute cache
49
+ });
50
+ }
51
+ catch (error) {
52
+ throw this.handleError(error);
53
+ }
54
+ }
55
+ /**
56
+ * Block a user
57
+ * @param userId - The user ID to block
58
+ * @returns Success message
59
+ */
60
+ async blockUser(userId) {
61
+ try {
62
+ if (!userId) {
63
+ throw new Error('User ID is required');
64
+ }
65
+ return await this.makeRequest('POST', `/api/privacy/blocked/${userId}`, undefined, {
66
+ cache: false,
67
+ });
68
+ }
69
+ catch (error) {
70
+ throw this.handleError(error);
71
+ }
72
+ }
73
+ /**
74
+ * Unblock a user
75
+ * @param userId - The user ID to unblock
76
+ * @returns Success message
77
+ */
78
+ async unblockUser(userId) {
79
+ try {
80
+ if (!userId) {
81
+ throw new Error('User ID is required');
82
+ }
83
+ return await this.makeRequest('DELETE', `/api/privacy/blocked/${userId}`, undefined, {
84
+ cache: false,
85
+ });
86
+ }
87
+ catch (error) {
88
+ throw this.handleError(error);
89
+ }
90
+ }
91
+ /**
92
+ * Check if a user is blocked
93
+ * @param userId - The user ID to check
94
+ * @returns True if the user is blocked, false otherwise
95
+ */
96
+ async isUserBlocked(userId) {
97
+ return this.isUserInList(userId, () => this.getBlockedUsers(), (block) => block.blockedId);
98
+ }
99
+ // ============================================================================
100
+ // RESTRICTED USERS METHODS
101
+ // ============================================================================
102
+ /**
103
+ * Get list of restricted users
104
+ * @returns Array of restricted users
105
+ */
106
+ async getRestrictedUsers() {
107
+ try {
108
+ return await this.makeRequest('GET', '/api/privacy/restricted', undefined, {
109
+ cache: true,
110
+ cacheTTL: 1 * 60 * 1000, // 1 minute cache
111
+ });
112
+ }
113
+ catch (error) {
114
+ throw this.handleError(error);
115
+ }
116
+ }
117
+ /**
118
+ * Restrict a user (limit their interactions without fully blocking)
119
+ * @param userId - The user ID to restrict
120
+ * @returns Success message
121
+ */
122
+ async restrictUser(userId) {
123
+ try {
124
+ if (!userId) {
125
+ throw new Error('User ID is required');
126
+ }
127
+ return await this.makeRequest('POST', `/api/privacy/restricted/${userId}`, undefined, {
128
+ cache: false,
129
+ });
130
+ }
131
+ catch (error) {
132
+ throw this.handleError(error);
133
+ }
134
+ }
135
+ /**
136
+ * Unrestrict a user
137
+ * @param userId - The user ID to unrestrict
138
+ * @returns Success message
139
+ */
140
+ async unrestrictUser(userId) {
141
+ try {
142
+ if (!userId) {
143
+ throw new Error('User ID is required');
144
+ }
145
+ return await this.makeRequest('DELETE', `/api/privacy/restricted/${userId}`, undefined, {
146
+ cache: false,
147
+ });
148
+ }
149
+ catch (error) {
150
+ throw this.handleError(error);
151
+ }
152
+ }
153
+ /**
154
+ * Check if a user is restricted
155
+ * @param userId - The user ID to check
156
+ * @returns True if the user is restricted, false otherwise
157
+ */
158
+ async isUserRestricted(userId) {
159
+ return this.isUserInList(userId, () => this.getRestrictedUsers(), (restrict) => restrict.restrictedId);
160
+ }
161
+ };
162
+ }