@olane/o-server 0.8.4 → 0.8.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"o-server.d.ts","sourceRoot":"","sources":["../../src/o-server.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,YAAY,EACZ,cAAc,EACf,MAAM,yCAAyC,CAAC;AAiBjD,wBAAgB,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAgR5D"}
1
+ {"version":3,"file":"o-server.d.ts","sourceRoot":"","sources":["../../src/o-server.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,YAAY,EACZ,cAAc,EACf,MAAM,yCAAyC,CAAC;AAiBjD,wBAAgB,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAoW5D"}
@@ -4,13 +4,57 @@ import { errorHandler } from './middleware/error-handler.js';
4
4
  import { authMiddleware } from './middleware/auth.js';
5
5
  import { createJwtMiddleware } from './middleware/jwt-auth.js';
6
6
  import { ServerLogger } from './utils/logger.js';
7
- import { oAddress } from '@olane/o-core';
7
+ import { oAddress, oRequestContext } from '@olane/o-core';
8
8
  import { validateAddress, validateMethod, sanitizeParams, validateRequest, useRequestSchema, streamRequestSchema, } from './validation/index.js';
9
9
  export function oServer(config) {
10
10
  const { node, port = 3000, basePath = '/api/v1', cors: corsConfig, authenticate, jwtAuth, debug = false, } = config;
11
11
  const app = express();
12
12
  const logger = new ServerLogger(debug);
13
13
  let server = null;
14
+ /**
15
+ * Build auth context from a JWT-verified Express request.
16
+ * Returns undefined if no JWT is present (e.g. JWT auth is disabled).
17
+ */
18
+ function buildAuthFromRequest(req) {
19
+ if (!req.jwt)
20
+ return undefined;
21
+ // Extract raw token from Authorization header
22
+ const authHeader = req.headers.authorization;
23
+ const token = authHeader?.startsWith('Bearer ')
24
+ ? authHeader.slice(7)
25
+ : '';
26
+ return {
27
+ token,
28
+ claims: req.jwt,
29
+ };
30
+ }
31
+ /**
32
+ * Remove any client-injected _auth from params (anti-spoofing).
33
+ * Server-verified auth is injected separately.
34
+ */
35
+ function stripClientAuth(params) {
36
+ if (!params || typeof params !== 'object')
37
+ return params;
38
+ const { _auth, ...rest } = params;
39
+ return rest;
40
+ }
41
+ /**
42
+ * Deep-strip _auth from response data before sending to HTTP client.
43
+ * Prevents leaking tokens in response payloads.
44
+ */
45
+ function stripAuthFromResponse(obj) {
46
+ if (obj === null || obj === undefined || typeof obj !== 'object')
47
+ return obj;
48
+ if (Array.isArray(obj))
49
+ return obj.map(stripAuthFromResponse);
50
+ const result = {};
51
+ for (const key of Object.keys(obj)) {
52
+ if (key === '_auth')
53
+ continue;
54
+ result[key] = stripAuthFromResponse(obj[key]);
55
+ }
56
+ return result;
57
+ }
14
58
  // Middleware
15
59
  app.use(express.json());
16
60
  if (corsConfig) {
@@ -53,18 +97,25 @@ export function oServer(config) {
53
97
  validateAddress(addressStr);
54
98
  // Validate method
55
99
  validateMethod(method);
100
+ // Strip client-injected _auth before sanitization (anti-spoofing)
101
+ const strippedParams = stripClientAuth(params);
56
102
  // Sanitize params
57
- const sanitizedParams = sanitizeParams(params);
103
+ const sanitizedParams = sanitizeParams(strippedParams);
104
+ // Build server-verified auth from JWT
105
+ const auth = buildAuthFromRequest(req);
106
+ // Inject _auth into params if JWT is present
107
+ const finalParams = auth
108
+ ? { ...sanitizedParams, _auth: auth }
109
+ : sanitizedParams;
58
110
  logger.debugLog(`Calling use with address ${addressStr}, method: ${method}`);
59
111
  const address = new oAddress(addressStr);
60
- const result = await node.use(address, {
61
- method,
62
- params: sanitizedParams,
63
- id,
64
- });
112
+ // Wrap in request context for AsyncLocalStorage propagation
113
+ const result = await (auth
114
+ ? oRequestContext.run({ auth }, () => node.use(address, { method, params: finalParams, id }))
115
+ : node.use(address, { method, params: finalParams, id }));
65
116
  const response = {
66
117
  success: true,
67
- data: result.result,
118
+ data: stripAuthFromResponse(result.result),
68
119
  };
69
120
  res.json(response);
70
121
  }
@@ -84,17 +135,25 @@ export function oServer(config) {
84
135
  validateAddress(addressStr);
85
136
  // Validate method
86
137
  validateMethod(method);
138
+ // Strip client-injected _auth before sanitization (anti-spoofing)
139
+ const strippedParams = stripClientAuth(params);
87
140
  // Sanitize params
88
- const sanitizedParams = sanitizeParams(params);
141
+ const sanitizedParams = sanitizeParams(strippedParams);
142
+ // Build server-verified auth from JWT
143
+ const auth = buildAuthFromRequest(req);
144
+ // Inject _auth into params if JWT is present
145
+ const finalParams = auth
146
+ ? { ...sanitizedParams, _auth: auth }
147
+ : sanitizedParams;
89
148
  logger.debugLog(`Calling method ${method} on ${addressParam} with params:`, sanitizedParams);
90
149
  const address = new oAddress(addressStr);
91
- const result = await node.use(address, {
92
- method,
93
- params: sanitizedParams,
94
- });
150
+ // Wrap in request context for AsyncLocalStorage propagation
151
+ const result = await (auth
152
+ ? oRequestContext.run({ auth }, () => node.use(address, { method, params: finalParams }))
153
+ : node.use(address, { method, params: finalParams }));
95
154
  const response = {
96
155
  success: true,
97
- data: result.result,
156
+ data: stripAuthFromResponse(result.result),
98
157
  };
99
158
  res.json(response);
100
159
  }
@@ -112,8 +171,16 @@ export function oServer(config) {
112
171
  validateAddress(addressStr);
113
172
  // Validate method
114
173
  validateMethod(method);
174
+ // Strip client-injected _auth before sanitization (anti-spoofing)
175
+ const strippedParams = stripClientAuth(params);
115
176
  // Sanitize params
116
- const sanitizedParams = sanitizeParams(params);
177
+ const sanitizedParams = sanitizeParams(strippedParams);
178
+ // Build server-verified auth from JWT
179
+ const auth = buildAuthFromRequest(req);
180
+ // Inject _auth into params if JWT is present
181
+ const finalParams = auth
182
+ ? { ...sanitizedParams, _auth: auth }
183
+ : sanitizedParams;
117
184
  logger.debugLog(`Streaming use call to ${addressStr}, method: ${method}`);
118
185
  // Set headers for Server-Sent Events
119
186
  res.setHeader('Content-Type', 'text/event-stream');
@@ -123,13 +190,12 @@ export function oServer(config) {
123
190
  try {
124
191
  // TODO: Implement actual streaming support when available
125
192
  // For now, execute and return result
126
- const result = await node.use(address, {
127
- method,
128
- params: sanitizedParams,
129
- });
193
+ const result = await (auth
194
+ ? oRequestContext.run({ auth }, () => node.use(address, { method, params: finalParams }))
195
+ : node.use(address, { method, params: finalParams }));
130
196
  res.write(`data: ${JSON.stringify({
131
197
  type: 'complete',
132
- result: result.result,
198
+ result: stripAuthFromResponse(result.result),
133
199
  })}\n\n`);
134
200
  res.end();
135
201
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olane/o-server",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "type": "module",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -61,7 +61,7 @@
61
61
  "typescript": "5.4.5"
62
62
  },
63
63
  "dependencies": {
64
- "@olane/o-core": "0.8.4",
64
+ "@olane/o-core": "0.8.6",
65
65
  "cors": "^2.8.5",
66
66
  "debug": "^4.4.1",
67
67
  "dotenv": "^16.5.0",
@@ -69,5 +69,5 @@
69
69
  "jsonwebtoken": "^9.0.3",
70
70
  "zod": "^3.25.76"
71
71
  },
72
- "gitHead": "b53623b1ad4365133911722f80d5597a72b65bf2"
72
+ "gitHead": "530f7e3c8576d9427f4181b91bdfb6ae1843cffa"
73
73
  }