@oxyhq/core 1.11.9 → 1.11.11

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 (63) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/AuthManager.js +158 -1
  3. package/dist/cjs/HttpService.js +13 -0
  4. package/dist/cjs/OxyServices.base.js +21 -0
  5. package/dist/cjs/crypto/keyManager.js +4 -6
  6. package/dist/cjs/crypto/polyfill.js +56 -12
  7. package/dist/cjs/crypto/signatureService.js +7 -4
  8. package/dist/cjs/mixins/OxyServices.fedcm.js +9 -4
  9. package/dist/cjs/mixins/OxyServices.managedAccounts.js +117 -0
  10. package/dist/cjs/mixins/OxyServices.popup.js +9 -5
  11. package/dist/cjs/mixins/OxyServices.utility.js +81 -2
  12. package/dist/cjs/mixins/index.js +2 -0
  13. package/dist/esm/.tsbuildinfo +1 -1
  14. package/dist/esm/AuthManager.js +158 -1
  15. package/dist/esm/HttpService.js +13 -0
  16. package/dist/esm/OxyServices.base.js +21 -0
  17. package/dist/esm/crypto/keyManager.js +4 -6
  18. package/dist/esm/crypto/polyfill.js +23 -12
  19. package/dist/esm/crypto/signatureService.js +7 -4
  20. package/dist/esm/mixins/OxyServices.fedcm.js +9 -4
  21. package/dist/esm/mixins/OxyServices.managedAccounts.js +114 -0
  22. package/dist/esm/mixins/OxyServices.popup.js +9 -5
  23. package/dist/esm/mixins/OxyServices.utility.js +81 -2
  24. package/dist/esm/mixins/index.js +2 -0
  25. package/dist/types/.tsbuildinfo +1 -1
  26. package/dist/types/AuthManager.d.ts +21 -0
  27. package/dist/types/HttpService.d.ts +3 -0
  28. package/dist/types/OxyServices.base.d.ts +17 -0
  29. package/dist/types/index.d.ts +1 -0
  30. package/dist/types/mixins/OxyServices.analytics.d.ts +2 -0
  31. package/dist/types/mixins/OxyServices.assets.d.ts +2 -0
  32. package/dist/types/mixins/OxyServices.auth.d.ts +2 -0
  33. package/dist/types/mixins/OxyServices.developer.d.ts +2 -0
  34. package/dist/types/mixins/OxyServices.devices.d.ts +2 -0
  35. package/dist/types/mixins/OxyServices.features.d.ts +5 -1
  36. package/dist/types/mixins/OxyServices.fedcm.d.ts +3 -0
  37. package/dist/types/mixins/OxyServices.karma.d.ts +2 -0
  38. package/dist/types/mixins/OxyServices.language.d.ts +2 -0
  39. package/dist/types/mixins/OxyServices.location.d.ts +2 -0
  40. package/dist/types/mixins/OxyServices.managedAccounts.d.ts +125 -0
  41. package/dist/types/mixins/OxyServices.payment.d.ts +2 -0
  42. package/dist/types/mixins/OxyServices.popup.d.ts +4 -0
  43. package/dist/types/mixins/OxyServices.privacy.d.ts +2 -0
  44. package/dist/types/mixins/OxyServices.redirect.d.ts +2 -0
  45. package/dist/types/mixins/OxyServices.security.d.ts +2 -0
  46. package/dist/types/mixins/OxyServices.topics.d.ts +2 -0
  47. package/dist/types/mixins/OxyServices.user.d.ts +2 -0
  48. package/dist/types/mixins/OxyServices.utility.d.ts +22 -0
  49. package/dist/types/models/interfaces.d.ts +2 -0
  50. package/package.json +1 -1
  51. package/src/AuthManager.ts +186 -4
  52. package/src/HttpService.ts +17 -0
  53. package/src/OxyServices.base.ts +23 -0
  54. package/src/crypto/keyManager.ts +4 -6
  55. package/src/crypto/polyfill.ts +23 -12
  56. package/src/crypto/signatureService.ts +7 -4
  57. package/src/index.ts +1 -0
  58. package/src/mixins/OxyServices.fedcm.ts +11 -4
  59. package/src/mixins/OxyServices.managedAccounts.ts +147 -0
  60. package/src/mixins/OxyServices.popup.ts +11 -5
  61. package/src/mixins/OxyServices.utility.ts +103 -2
  62. package/src/mixins/index.ts +2 -0
  63. package/src/models/interfaces.ts +3 -0
@@ -46,6 +46,41 @@ function OxyServicesUtilityMixin(Base) {
46
46
  return class extends Base {
47
47
  constructor(...args) {
48
48
  super(...args);
49
+ /** @internal In-memory cache for acting-as verification results (TTL: 5 min) */
50
+ this._actingAsCache = new Map();
51
+ }
52
+ /**
53
+ * Verify that a user is authorized to act as a managed account.
54
+ * Results are cached in-memory for 5 minutes to avoid repeated API calls.
55
+ *
56
+ * @internal Used by the auth() middleware — not part of the public API
57
+ */
58
+ async verifyActingAs(userId, accountId) {
59
+ const cacheKey = `${userId}:${accountId}`;
60
+ const now = Date.now();
61
+ // Check cache
62
+ const cached = this._actingAsCache.get(cacheKey);
63
+ if (cached && cached.expiresAt > now) {
64
+ return cached.result;
65
+ }
66
+ // Query the API
67
+ try {
68
+ const result = await this.makeRequest('GET', '/managed-accounts/verify', { accountId, userId }, { cache: false, retry: false, timeout: 5000 });
69
+ // Cache successful result for 5 minutes
70
+ this._actingAsCache.set(cacheKey, {
71
+ result: result && result.authorized ? result : null,
72
+ expiresAt: now + 5 * 60 * 1000,
73
+ });
74
+ return result && result.authorized ? result : null;
75
+ }
76
+ catch {
77
+ // Cache negative result for 1 minute to avoid hammering on transient errors
78
+ this._actingAsCache.set(cacheKey, {
79
+ result: null,
80
+ expiresAt: now + 1 * 60 * 1000,
81
+ });
82
+ return null;
83
+ }
49
84
  }
50
85
  /**
51
86
  * Fetch link metadata
@@ -108,6 +143,45 @@ function OxyServicesUtilityMixin(Base) {
108
143
  const oxyInstance = this;
109
144
  // Return an async middleware function
110
145
  return async (req, res, next) => {
146
+ // Process X-Acting-As header for managed account identity delegation.
147
+ // Called after successful authentication, before next(). If the header
148
+ // is present, verifies authorization and swaps the request identity to
149
+ // the managed account, preserving the original user for audit trails.
150
+ const processActingAs = async () => {
151
+ const actingAsUserId = req.headers['x-acting-as'];
152
+ if (!actingAsUserId)
153
+ return true; // No header, proceed normally
154
+ const verification = await oxyInstance.verifyActingAs(req.userId, actingAsUserId);
155
+ if (!verification) {
156
+ const error = {
157
+ error: 'ACTING_AS_UNAUTHORIZED',
158
+ message: 'Not authorized to act as this account',
159
+ code: 'ACTING_AS_UNAUTHORIZED',
160
+ status: 403,
161
+ };
162
+ if (onError) {
163
+ onError(error);
164
+ }
165
+ else {
166
+ res.status(403).json(error);
167
+ }
168
+ return false;
169
+ }
170
+ // Preserve original user for audit trails
171
+ req.originalUser = { id: req.userId, ...req.user };
172
+ req.actingAs = { userId: actingAsUserId, role: verification.role };
173
+ // Swap user identity to the managed account
174
+ req.userId = actingAsUserId;
175
+ req.user = { id: actingAsUserId };
176
+ // Also set _id for routes that use Pattern B (req.user._id)
177
+ if (req.user) {
178
+ req.user._id = actingAsUserId;
179
+ }
180
+ if (debug) {
181
+ console.log(`[oxy.auth] Acting as ${actingAsUserId} (role=${verification.role}) original=${req.originalUser.id}`);
182
+ }
183
+ return true;
184
+ };
111
185
  try {
112
186
  // Extract token from Authorization header or query params
113
187
  const authHeader = req.headers['authorization'];
@@ -330,7 +404,10 @@ function OxyServicesUtilityMixin(Base) {
330
404
  if (debug) {
331
405
  console.log(`[oxy.auth] OK user=${userId} session=${decoded.sessionId}`);
332
406
  }
333
- return next();
407
+ // Process X-Acting-As header before proceeding
408
+ if (await processActingAs())
409
+ return next();
410
+ return;
334
411
  }
335
412
  catch (validationError) {
336
413
  if (debug) {
@@ -381,7 +458,9 @@ function OxyServicesUtilityMixin(Base) {
381
458
  if (debug) {
382
459
  console.log(`[oxy.auth] OK user=${userId} (no session)`);
383
460
  }
384
- next();
461
+ // Process X-Acting-As header before proceeding
462
+ if (await processActingAs())
463
+ next();
385
464
  }
386
465
  catch (error) {
387
466
  const apiError = oxyInstance.handleError(error);
@@ -27,6 +27,7 @@ const OxyServices_security_1 = require("./OxyServices.security");
27
27
  const OxyServices_utility_1 = require("./OxyServices.utility");
28
28
  const OxyServices_features_1 = require("./OxyServices.features");
29
29
  const OxyServices_topics_1 = require("./OxyServices.topics");
30
+ const OxyServices_managedAccounts_1 = require("./OxyServices.managedAccounts");
30
31
  /**
31
32
  * Mixin pipeline - applied in order from first to last.
32
33
  *
@@ -64,6 +65,7 @@ const MIXIN_PIPELINE = [
64
65
  OxyServices_security_1.OxyServicesSecurityMixin,
65
66
  OxyServices_features_1.OxyServicesFeaturesMixin,
66
67
  OxyServices_topics_1.OxyServicesTopicsMixin,
68
+ OxyServices_managedAccounts_1.OxyServicesManagedAccountsMixin,
67
69
  // Utility (last, can use all above)
68
70
  OxyServices_utility_1.OxyServicesUtilityMixin,
69
71
  ];