@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
@@ -10,6 +10,41 @@ export function OxyServicesUtilityMixin(Base) {
10
10
  return class extends Base {
11
11
  constructor(...args) {
12
12
  super(...args);
13
+ /** @internal In-memory cache for acting-as verification results (TTL: 5 min) */
14
+ this._actingAsCache = new Map();
15
+ }
16
+ /**
17
+ * Verify that a user is authorized to act as a managed account.
18
+ * Results are cached in-memory for 5 minutes to avoid repeated API calls.
19
+ *
20
+ * @internal Used by the auth() middleware — not part of the public API
21
+ */
22
+ async verifyActingAs(userId, accountId) {
23
+ const cacheKey = `${userId}:${accountId}`;
24
+ const now = Date.now();
25
+ // Check cache
26
+ const cached = this._actingAsCache.get(cacheKey);
27
+ if (cached && cached.expiresAt > now) {
28
+ return cached.result;
29
+ }
30
+ // Query the API
31
+ try {
32
+ const result = await this.makeRequest('GET', '/managed-accounts/verify', { accountId, userId }, { cache: false, retry: false, timeout: 5000 });
33
+ // Cache successful result for 5 minutes
34
+ this._actingAsCache.set(cacheKey, {
35
+ result: result && result.authorized ? result : null,
36
+ expiresAt: now + 5 * 60 * 1000,
37
+ });
38
+ return result && result.authorized ? result : null;
39
+ }
40
+ catch {
41
+ // Cache negative result for 1 minute to avoid hammering on transient errors
42
+ this._actingAsCache.set(cacheKey, {
43
+ result: null,
44
+ expiresAt: now + 1 * 60 * 1000,
45
+ });
46
+ return null;
47
+ }
13
48
  }
14
49
  /**
15
50
  * Fetch link metadata
@@ -72,6 +107,45 @@ export function OxyServicesUtilityMixin(Base) {
72
107
  const oxyInstance = this;
73
108
  // Return an async middleware function
74
109
  return async (req, res, next) => {
110
+ // Process X-Acting-As header for managed account identity delegation.
111
+ // Called after successful authentication, before next(). If the header
112
+ // is present, verifies authorization and swaps the request identity to
113
+ // the managed account, preserving the original user for audit trails.
114
+ const processActingAs = async () => {
115
+ const actingAsUserId = req.headers['x-acting-as'];
116
+ if (!actingAsUserId)
117
+ return true; // No header, proceed normally
118
+ const verification = await oxyInstance.verifyActingAs(req.userId, actingAsUserId);
119
+ if (!verification) {
120
+ const error = {
121
+ error: 'ACTING_AS_UNAUTHORIZED',
122
+ message: 'Not authorized to act as this account',
123
+ code: 'ACTING_AS_UNAUTHORIZED',
124
+ status: 403,
125
+ };
126
+ if (onError) {
127
+ onError(error);
128
+ }
129
+ else {
130
+ res.status(403).json(error);
131
+ }
132
+ return false;
133
+ }
134
+ // Preserve original user for audit trails
135
+ req.originalUser = { id: req.userId, ...req.user };
136
+ req.actingAs = { userId: actingAsUserId, role: verification.role };
137
+ // Swap user identity to the managed account
138
+ req.userId = actingAsUserId;
139
+ req.user = { id: actingAsUserId };
140
+ // Also set _id for routes that use Pattern B (req.user._id)
141
+ if (req.user) {
142
+ req.user._id = actingAsUserId;
143
+ }
144
+ if (debug) {
145
+ console.log(`[oxy.auth] Acting as ${actingAsUserId} (role=${verification.role}) original=${req.originalUser.id}`);
146
+ }
147
+ return true;
148
+ };
75
149
  try {
76
150
  // Extract token from Authorization header or query params
77
151
  const authHeader = req.headers['authorization'];
@@ -294,7 +368,10 @@ export function OxyServicesUtilityMixin(Base) {
294
368
  if (debug) {
295
369
  console.log(`[oxy.auth] OK user=${userId} session=${decoded.sessionId}`);
296
370
  }
297
- return next();
371
+ // Process X-Acting-As header before proceeding
372
+ if (await processActingAs())
373
+ return next();
374
+ return;
298
375
  }
299
376
  catch (validationError) {
300
377
  if (debug) {
@@ -345,7 +422,9 @@ export function OxyServicesUtilityMixin(Base) {
345
422
  if (debug) {
346
423
  console.log(`[oxy.auth] OK user=${userId} (no session)`);
347
424
  }
348
- next();
425
+ // Process X-Acting-As header before proceeding
426
+ if (await processActingAs())
427
+ next();
349
428
  }
350
429
  catch (error) {
351
430
  const apiError = oxyInstance.handleError(error);
@@ -23,6 +23,7 @@ import { OxyServicesSecurityMixin } from './OxyServices.security.js';
23
23
  import { OxyServicesUtilityMixin } from './OxyServices.utility.js';
24
24
  import { OxyServicesFeaturesMixin } from './OxyServices.features.js';
25
25
  import { OxyServicesTopicsMixin } from './OxyServices.topics.js';
26
+ import { OxyServicesManagedAccountsMixin } from './OxyServices.managedAccounts.js';
26
27
  /**
27
28
  * Mixin pipeline - applied in order from first to last.
28
29
  *
@@ -60,6 +61,7 @@ const MIXIN_PIPELINE = [
60
61
  OxyServicesSecurityMixin,
61
62
  OxyServicesFeaturesMixin,
62
63
  OxyServicesTopicsMixin,
64
+ OxyServicesManagedAccountsMixin,
63
65
  // Utility (last, can use all above)
64
66
  OxyServicesUtilityMixin,
65
67
  ];