@oxyhq/services 5.8.11 → 5.9.1

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 (73) hide show
  1. package/lib/commonjs/core/index.js +192 -346
  2. package/lib/commonjs/core/index.js.map +1 -1
  3. package/lib/commonjs/index.js +6 -0
  4. package/lib/commonjs/index.js.map +1 -1
  5. package/lib/commonjs/node/index.js +0 -9
  6. package/lib/commonjs/node/index.js.map +1 -1
  7. package/lib/commonjs/types/middleware.js +6 -0
  8. package/lib/commonjs/types/middleware.js.map +1 -0
  9. package/lib/commonjs/ui/components/OxyProvider.js +3 -9
  10. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  11. package/lib/commonjs/ui/screens/FeedbackScreen.js +0 -4
  12. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  13. package/lib/commonjs/ui/screens/RecoverAccountScreen.js +0 -4
  14. package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
  15. package/lib/commonjs/ui/screens/SignInScreen.js +16 -27
  16. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  17. package/lib/commonjs/ui/screens/SignUpScreen.js +4 -18
  18. package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
  19. package/lib/commonjs/ui/styles/authStyles.js +1 -2
  20. package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
  21. package/lib/module/core/index.js +190 -345
  22. package/lib/module/core/index.js.map +1 -1
  23. package/lib/module/index.js +4 -0
  24. package/lib/module/index.js.map +1 -1
  25. package/lib/module/node/index.js +0 -4
  26. package/lib/module/node/index.js.map +1 -1
  27. package/lib/module/types/middleware.js +4 -0
  28. package/lib/module/types/middleware.js.map +1 -0
  29. package/lib/module/ui/components/OxyProvider.js +3 -9
  30. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  31. package/lib/module/ui/screens/FeedbackScreen.js +0 -4
  32. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  33. package/lib/module/ui/screens/RecoverAccountScreen.js +0 -4
  34. package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
  35. package/lib/module/ui/screens/SignInScreen.js +16 -27
  36. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  37. package/lib/module/ui/screens/SignUpScreen.js +4 -18
  38. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  39. package/lib/module/ui/styles/authStyles.js +1 -2
  40. package/lib/module/ui/styles/authStyles.js.map +1 -1
  41. package/lib/typescript/core/index.d.ts +34 -86
  42. package/lib/typescript/core/index.d.ts.map +1 -1
  43. package/lib/typescript/index.d.ts +2 -0
  44. package/lib/typescript/index.d.ts.map +1 -1
  45. package/lib/typescript/node/index.d.ts +0 -2
  46. package/lib/typescript/node/index.d.ts.map +1 -1
  47. package/lib/typescript/types/middleware.d.ts +19 -0
  48. package/lib/typescript/types/middleware.d.ts.map +1 -0
  49. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  50. package/lib/typescript/ui/screens/FeedbackScreen.d.ts.map +1 -1
  51. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
  52. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  53. package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
  54. package/lib/typescript/ui/styles/authStyles.d.ts +0 -1
  55. package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
  56. package/package.json +6 -6
  57. package/src/core/index.ts +196 -328
  58. package/src/index.ts +4 -0
  59. package/src/node/index.ts +0 -4
  60. package/src/types/middleware.ts +20 -0
  61. package/src/ui/components/OxyProvider.tsx +3 -9
  62. package/src/ui/screens/FeedbackScreen.tsx +0 -4
  63. package/src/ui/screens/RecoverAccountScreen.tsx +0 -4
  64. package/src/ui/screens/SignInScreen.tsx +16 -20
  65. package/src/ui/screens/SignUpScreen.tsx +4 -14
  66. package/src/ui/styles/authStyles.ts +0 -1
  67. package/lib/commonjs/node/createAuth.js +0 -95
  68. package/lib/commonjs/node/createAuth.js.map +0 -1
  69. package/lib/module/node/createAuth.js +0 -90
  70. package/lib/module/node/createAuth.js.map +0 -1
  71. package/lib/typescript/node/createAuth.d.ts +0 -7
  72. package/lib/typescript/node/createAuth.d.ts.map +0 -1
  73. package/src/node/createAuth.ts +0 -116
@@ -23,7 +23,6 @@ export { DeviceManager } from '../utils/deviceManager';
23
23
  export class OxyServices {
24
24
  accessToken = null;
25
25
  refreshToken = null;
26
- refreshPromise = null;
27
26
 
28
27
  /**
29
28
  * Creates a new instance of the OxyServices client
@@ -39,14 +38,25 @@ export class OxyServices {
39
38
  this.client.interceptors.request.use(async req => {
40
39
  if (!this.accessToken) {
41
40
  return req;
42
- } // Check if token is expired and refresh if needed
41
+ }
42
+
43
+ // Check if token is expired and refresh if needed
43
44
  try {
44
45
  const decoded = jwtDecode(this.accessToken);
45
46
  const currentTime = Math.floor(Date.now() / 1000);
46
47
 
47
48
  // If token expires in less than 60 seconds, refresh it
48
49
  if (decoded.exp - currentTime < 60) {
49
- await this.refreshTokens();
50
+ // For session-based tokens, get a new token from the session
51
+ if (decoded.sessionId) {
52
+ try {
53
+ const res = await this.client.get(`/secure-session/token/${decoded.sessionId}`);
54
+ this.accessToken = res.data.accessToken;
55
+ } catch (refreshError) {
56
+ // If refresh fails, clear tokens
57
+ this.clearTokens();
58
+ }
59
+ }
50
60
  }
51
61
  } catch (error) {
52
62
  // If token can't be decoded, continue with request and let server handle it
@@ -61,18 +71,24 @@ export class OxyServices {
61
71
  this.client.interceptors.response.use(response => response, async error => {
62
72
  const originalRequest = error.config;
63
73
  // If the error is due to an expired token and we haven't tried refreshing yet
64
- if (error.response?.status === 401 && this.refreshToken && originalRequest && !originalRequest.headers?.['X-Retry-After-Refresh']) {
74
+ if (error.response?.status === 401 && this.accessToken && originalRequest && !originalRequest.headers?.['X-Retry-After-Refresh']) {
65
75
  try {
66
- await this.refreshTokens();
67
- // Retry the original request with new token
68
- const newRequest = {
69
- ...originalRequest
70
- };
71
- if (newRequest.headers) {
72
- newRequest.headers.Authorization = `Bearer ${this.accessToken}`;
73
- newRequest.headers['X-Retry-After-Refresh'] = 'true';
76
+ // Check if token is session-based and try to refresh
77
+ const decoded = jwtDecode(this.accessToken);
78
+ if (decoded.sessionId) {
79
+ const res = await this.client.get(`/secure-session/token/${decoded.sessionId}`);
80
+ this.accessToken = res.data.accessToken;
81
+
82
+ // Retry the original request with new token
83
+ const newRequest = {
84
+ ...originalRequest
85
+ };
86
+ if (newRequest.headers) {
87
+ newRequest.headers.Authorization = `Bearer ${this.accessToken}`;
88
+ newRequest.headers['X-Retry-After-Refresh'] = 'true';
89
+ }
90
+ return this.client(newRequest);
74
91
  }
75
- return this.client(newRequest);
76
92
  } catch (refreshError) {
77
93
  // If refresh fails, force user to login again
78
94
  this.clearTokens();
@@ -105,43 +121,17 @@ export class OxyServices {
105
121
  }
106
122
 
107
123
  /**
108
- * Gets the currently authenticated user ID from the token
109
- * @returns The user ID or null if not authenticated
124
+ * Set authentication tokens manually
125
+ * @param accessToken - The access token
126
+ * @param refreshToken - The refresh token (optional for session-based auth)
110
127
  */
111
- getCurrentUserId() {
112
- if (!this.accessToken) return null;
113
- try {
114
- const decoded = jwtDecode(this.accessToken);
115
-
116
- // Check for both userId (preferred) and id (fallback) for compatibility
117
- return decoded.userId || decoded.id || null;
118
- } catch (error) {
119
- return null;
120
- }
121
- }
122
-
123
- /**
124
- * Internal method to check if we have an access token
125
- * @private
126
- * @returns Boolean indicating if access token exists
127
- * @internal - Use `isAuthenticated` from useOxy() context in UI components instead
128
- */
129
- hasAccessToken() {
130
- return this.accessToken !== null;
131
- }
132
-
133
- /**
134
- * Sets authentication tokens directly (useful for initializing from storage)
135
- * @param accessToken - JWT access token
136
- * @param refreshToken - Refresh token for getting new access tokens
137
- */
138
- setTokens(accessToken, refreshToken) {
128
+ setTokens(accessToken, refreshToken = '') {
139
129
  this.accessToken = accessToken;
140
130
  this.refreshToken = refreshToken;
141
131
  }
142
132
 
143
133
  /**
144
- * Clears all authentication tokens
134
+ * Clear stored authentication tokens
145
135
  */
146
136
  clearTokens() {
147
137
  this.accessToken = null;
@@ -149,120 +139,27 @@ export class OxyServices {
149
139
  }
150
140
 
151
141
  /**
152
- * Sign up a new user
153
- * @param username - Desired username
154
- * @param email - User's email address
155
- * @param password - User's password
156
- * @returns Object containing the message, token and user data
157
- */
158
- async signUp(username, email, password) {
159
- try {
160
- const res = await this.client.post('/auth/signup', {
161
- username,
162
- email,
163
- password
164
- });
165
- const {
166
- message,
167
- token,
168
- user
169
- } = res.data;
170
- this.accessToken = token;
171
- return {
172
- message,
173
- token,
174
- user
175
- };
176
- } catch (error) {
177
- throw this.handleError(error);
178
- }
179
- }
180
-
181
- /**
182
- * Log in and store tokens
183
- * @param username - User's username or email
184
- * @param password - User's password
185
- * @returns Login response containing tokens and user data
142
+ * Get the current user ID from the stored token
143
+ * @returns User ID or null if not authenticated
186
144
  */
187
- async login(username, password) {
188
- try {
189
- const res = await this.client.post('/auth/login', {
190
- username,
191
- password
192
- });
193
- const {
194
- accessToken,
195
- refreshToken,
196
- user
197
- } = res.data;
198
- this.accessToken = accessToken;
199
- this.refreshToken = refreshToken;
200
- return {
201
- accessToken,
202
- refreshToken,
203
- user
204
- };
205
- } catch (error) {
206
- throw this.handleError(error);
207
- }
208
- }
209
-
210
- /**
211
- * Log out user
212
- */
213
- async logout() {
214
- if (!this.refreshToken) return;
145
+ getCurrentUserId() {
146
+ if (!this.accessToken) return null;
215
147
  try {
216
- await this.client.post('/auth/logout', {
217
- refreshToken: this.refreshToken
218
- });
148
+ const decoded = jwtDecode(this.accessToken);
149
+ return decoded.userId || decoded.id || null;
219
150
  } catch (error) {
220
- console.warn('Error during logout', error);
221
- } finally {
222
- this.accessToken = null;
223
- this.refreshToken = null;
151
+ return null;
224
152
  }
225
153
  }
226
154
 
227
155
  /**
228
- * Refresh access and refresh tokens
229
- * @returns New tokens
156
+ * Internal method to check if we have an access token
157
+ * @private
158
+ * @returns Boolean indicating if access token exists
159
+ * @internal - Use `isAuthenticated` from useOxy() context in UI components instead
230
160
  */
231
- async refreshTokens() {
232
- if (!this.refreshToken) {
233
- throw new Error('No refresh token available');
234
- }
235
-
236
- // If a refresh is already in progress, return that promise
237
- if (this.refreshPromise) {
238
- return this.refreshPromise;
239
- }
240
-
241
- // Create a new refresh promise
242
- this.refreshPromise = (async () => {
243
- try {
244
- const res = await this.client.post('/auth/refresh', {
245
- refreshToken: this.refreshToken
246
- });
247
- const {
248
- accessToken,
249
- refreshToken
250
- } = res.data;
251
- this.accessToken = accessToken;
252
- this.refreshToken = refreshToken;
253
- return {
254
- accessToken,
255
- refreshToken
256
- };
257
- } catch (error) {
258
- this.accessToken = null;
259
- this.refreshToken = null;
260
- throw this.handleError(error);
261
- } finally {
262
- this.refreshPromise = null;
263
- }
264
- })();
265
- return this.refreshPromise;
161
+ hasAccessToken() {
162
+ return this.accessToken !== null;
266
163
  }
267
164
 
268
165
  /**
@@ -271,6 +168,22 @@ export class OxyServices {
271
168
  */
272
169
  async validate() {
273
170
  try {
171
+ // Check if token contains sessionId (new session-based system)
172
+ if (this.accessToken) {
173
+ try {
174
+ const decoded = jwtDecode(this.accessToken);
175
+ if (decoded.sessionId) {
176
+ // Use session-based validation
177
+ const res = await this.client.get(`/secure-session/validate/${decoded.sessionId}`);
178
+ return res.data.valid;
179
+ }
180
+ } catch (decodeError) {
181
+ // If token can't be decoded, fall back to old validation
182
+ console.warn('Error decoding JWT token for session validation:', decodeError);
183
+ }
184
+ }
185
+
186
+ // Fall back to old validation method
274
187
  const res = await this.client.get('/auth/validate');
275
188
  return res.data.valid;
276
189
  } catch (error) {
@@ -280,59 +193,6 @@ export class OxyServices {
280
193
 
281
194
  /* Session Management Methods */
282
195
 
283
- /**
284
- * Get active sessions for the authenticated user
285
- * @returns Array of active session objects
286
- */
287
- async getUserSessions() {
288
- try {
289
- const res = await this.client.get('/sessions');
290
- return res.data;
291
- } catch (error) {
292
- throw this.handleError(error);
293
- }
294
- }
295
-
296
- /**
297
- * Logout from a specific session
298
- * @param sessionId - The session ID to logout from
299
- * @returns Success status
300
- */
301
- async logoutSession(sessionId) {
302
- try {
303
- const res = await this.client.delete(`/sessions/${sessionId}`);
304
- return res.data;
305
- } catch (error) {
306
- throw this.handleError(error);
307
- }
308
- }
309
-
310
- /**
311
- * Logout from all other sessions (keep current session active)
312
- * @returns Success status
313
- */
314
- async logoutOtherSessions() {
315
- try {
316
- const res = await this.client.post('/sessions/logout-others');
317
- return res.data;
318
- } catch (error) {
319
- throw this.handleError(error);
320
- }
321
- }
322
-
323
- /**
324
- * Logout from all sessions
325
- * @returns Success status
326
- */
327
- async logoutAllSessions() {
328
- try {
329
- const res = await this.client.post('/sessions/logout-all');
330
- return res.data;
331
- } catch (error) {
332
- throw this.handleError(error);
333
- }
334
- }
335
-
336
196
  /**
337
197
  * Get device sessions for a specific session ID
338
198
  * @param sessionId - The session ID to get device sessions for
@@ -1157,12 +1017,47 @@ export class OxyServices {
1157
1017
  }
1158
1018
 
1159
1019
  /**
1160
- * Secure login that returns only session data (no tokens stored locally)
1020
+ * Sign up a new user and create a session
1021
+ * @param username - Desired username
1022
+ * @param email - User's email address
1023
+ * @param password - User's password
1024
+ * @returns Object containing the message, token and user data
1025
+ */
1026
+ async signUp(username, email, password) {
1027
+ try {
1028
+ // First, create the user account
1029
+ const res = await this.client.post('/secure-session/register', {
1030
+ username,
1031
+ email,
1032
+ password
1033
+ });
1034
+ const {
1035
+ message,
1036
+ user
1037
+ } = res.data;
1038
+
1039
+ // Then log them in to create a session
1040
+ const loginRes = await this.secureLogin(username, password);
1041
+
1042
+ // Get the access token for the session
1043
+ const tokenRes = await this.getTokenBySession(loginRes.sessionId);
1044
+ return {
1045
+ message,
1046
+ token: tokenRes.accessToken,
1047
+ user: loginRes.user
1048
+ };
1049
+ } catch (error) {
1050
+ throw this.handleError(error);
1051
+ }
1052
+ }
1053
+
1054
+ /**
1055
+ * Secure login that creates a device-based session
1161
1056
  * @param username - User's username or email
1162
1057
  * @param password - User's password
1163
- * @param deviceName - Optional device name for session tracking
1164
- * @param deviceFingerprint - Device fingerprint for enhanced security
1165
- * @returns Secure login response with session data
1058
+ * @param deviceName - Optional device name
1059
+ * @param deviceFingerprint - Optional device fingerprint
1060
+ * @returns Login response with session data
1166
1061
  */
1167
1062
  async secureLogin(username, password, deviceName, deviceFingerprint) {
1168
1063
  try {
@@ -1340,122 +1235,47 @@ export class OxyServices {
1340
1235
  }
1341
1236
 
1342
1237
  /**
1343
- * Utility method to help implement authentication middleware in Express.js applications
1344
- * This creates a function that can be used as Express middleware to validate tokens
1345
- * @param options - Configuration options for the middleware
1238
+ * Create authentication middleware for Express.js applications
1239
+ * This is the recommended way to protect routes in server applications
1346
1240
  * @returns Express middleware function
1347
1241
  */
1348
- createAuthenticateTokenMiddleware(options = {}) {
1349
- const {
1350
- loadFullUser = true,
1351
- onError
1352
- } = options;
1242
+ createAuthMiddleware() {
1353
1243
  return async (req, res, next) => {
1354
1244
  try {
1355
- const authHeader = req.headers['authorization'];
1356
- const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
1357
-
1358
- if (!token) {
1359
- const error = {
1360
- message: 'Access token required',
1361
- code: 'MISSING_TOKEN',
1362
- status: 401
1363
- };
1364
- if (onError) {
1365
- return onError(error);
1366
- }
1245
+ const authHeader = req.headers.authorization;
1246
+ if (!authHeader?.startsWith('Bearer ')) {
1367
1247
  return res.status(401).json({
1368
- message: 'Access token required',
1369
- code: 'MISSING_TOKEN'
1370
- });
1371
- }
1372
-
1373
- // Create a temporary OxyServices instance with the token to validate it
1374
- const tempOxyServices = new OxyServices({
1375
- baseURL: this.client.defaults.baseURL || ''
1376
- });
1377
- tempOxyServices.setTokens(token, ''); // Set access token
1378
-
1379
- // Validate token using the validate method
1380
- const isValid = await tempOxyServices.validate();
1381
- if (!isValid) {
1382
- const error = {
1383
- message: 'Invalid or expired token',
1384
- code: 'INVALID_TOKEN',
1385
- status: 403
1386
- };
1387
- if (onError) {
1388
- return onError(error);
1389
- }
1390
- return res.status(403).json({
1391
- message: 'Invalid or expired token',
1392
- code: 'INVALID_TOKEN'
1248
+ error: 'Authentication required',
1249
+ message: 'Invalid or missing authorization header'
1393
1250
  });
1394
1251
  }
1252
+ const token = authHeader.split(' ')[1];
1395
1253
 
1396
- // Get user ID from token using JWT decode instead of relying on getCurrentUserId
1397
- let userId = null;
1398
- try {
1399
- const decoded = jwtDecode(token);
1400
- userId = decoded.userId || decoded.id;
1401
- } catch (decodeError) {
1402
- const error = {
1403
- message: 'Invalid token payload',
1404
- code: 'INVALID_PAYLOAD',
1405
- status: 403
1406
- };
1407
- if (onError) {
1408
- return onError(error);
1409
- }
1410
- return res.status(403).json({
1411
- message: 'Invalid token payload',
1412
- code: 'INVALID_PAYLOAD'
1413
- });
1414
- }
1415
- if (!userId) {
1416
- const error = {
1417
- message: 'Invalid token payload',
1418
- code: 'INVALID_PAYLOAD',
1419
- status: 403
1420
- };
1421
- if (onError) {
1422
- return onError(error);
1423
- }
1424
- return res.status(403).json({
1425
- message: 'Invalid token payload',
1426
- code: 'INVALID_PAYLOAD'
1254
+ // Use the authenticateToken method
1255
+ const result = await this.authenticateToken(token);
1256
+ if (!result.valid) {
1257
+ return res.status(401).json({
1258
+ error: 'Invalid token',
1259
+ message: result.error || 'The provided authentication token is invalid'
1427
1260
  });
1428
1261
  }
1429
1262
 
1430
1263
  // Set user information on request object
1431
- req.userId = userId;
1264
+ req.userId = result.userId || undefined;
1432
1265
  req.accessToken = token;
1433
-
1434
- // Optionally load full user data
1435
- if (loadFullUser) {
1436
- try {
1437
- const userProfile = await tempOxyServices.getUserById(userId);
1438
- req.user = userProfile;
1439
- } catch (userError) {
1440
- // If we can't load user, continue with just ID
1441
- req.user = {
1442
- id: userId
1443
- };
1444
- }
1445
- } else {
1266
+ if (result.user) {
1267
+ req.user = result.user;
1268
+ } else if (result.userId) {
1446
1269
  req.user = {
1447
- id: userId
1270
+ id: result.userId
1448
1271
  };
1449
1272
  }
1450
1273
  next();
1451
1274
  } catch (error) {
1452
- const apiError = this.handleError(error);
1453
- if (onError) {
1454
- return onError(apiError);
1455
- }
1456
- return res.status(apiError.status || 500).json({
1457
- message: apiError.message,
1458
- code: apiError.code
1275
+ console.error('Auth middleware error:', error);
1276
+ return res.status(500).json({
1277
+ error: 'Server error',
1278
+ message: 'An error occurred while authenticating your request'
1459
1279
  });
1460
1280
  }
1461
1281
  };
@@ -1476,54 +1296,71 @@ export class OxyServices {
1476
1296
  };
1477
1297
  }
1478
1298
 
1479
- // Create a temporary OxyServices instance with the token
1480
- const tempOxyServices = new OxyServices({
1481
- baseURL: this.client.defaults.baseURL || ''
1482
- });
1483
- tempOxyServices.setTokens(token, '');
1484
-
1485
- // Validate token
1486
- const isValid = await tempOxyServices.validate();
1487
- if (!isValid) {
1488
- return {
1489
- valid: false,
1490
- error: 'Invalid or expired token'
1491
- };
1492
- }
1493
-
1494
- // Get user ID from token using JWT decode
1495
- let userId = null;
1299
+ // Check if token contains sessionId (new session-based system)
1496
1300
  try {
1497
1301
  const decoded = jwtDecode(token);
1498
- userId = decoded.userId || decoded.id;
1302
+ const userId = decoded.userId || decoded.id;
1303
+ if (decoded.sessionId) {
1304
+ // Use session-based validation
1305
+ const tempOxyServices = new OxyServices({
1306
+ baseURL: this.client.defaults.baseURL || ''
1307
+ });
1308
+ tempOxyServices.setTokens(token, '');
1309
+ const validation = await tempOxyServices.validateSession(decoded.sessionId);
1310
+ if (validation.valid) {
1311
+ return {
1312
+ valid: true,
1313
+ userId,
1314
+ user: validation.user
1315
+ };
1316
+ } else {
1317
+ return {
1318
+ valid: false,
1319
+ error: 'Invalid or expired session'
1320
+ };
1321
+ }
1322
+ } else {
1323
+ // Use old validation method
1324
+ const tempOxyServices = new OxyServices({
1325
+ baseURL: this.client.defaults.baseURL || ''
1326
+ });
1327
+ tempOxyServices.setTokens(token, '');
1328
+ const isValid = await tempOxyServices.validate();
1329
+ if (!isValid) {
1330
+ return {
1331
+ valid: false,
1332
+ error: 'Invalid or expired token'
1333
+ };
1334
+ }
1335
+ if (!userId) {
1336
+ return {
1337
+ valid: false,
1338
+ error: 'Invalid token payload'
1339
+ };
1340
+ }
1341
+
1342
+ // Try to get user profile
1343
+ let user;
1344
+ try {
1345
+ user = await tempOxyServices.getUserById(userId);
1346
+ } catch (error) {
1347
+ // Continue without full user data
1348
+ user = {
1349
+ id: userId
1350
+ };
1351
+ }
1352
+ return {
1353
+ valid: true,
1354
+ userId,
1355
+ user
1356
+ };
1357
+ }
1499
1358
  } catch (decodeError) {
1500
1359
  return {
1501
1360
  valid: false,
1502
1361
  error: 'Invalid token payload'
1503
1362
  };
1504
1363
  }
1505
- if (!userId) {
1506
- return {
1507
- valid: false,
1508
- error: 'Invalid token payload'
1509
- };
1510
- }
1511
-
1512
- // Try to get user profile
1513
- let user;
1514
- try {
1515
- user = await tempOxyServices.getUserById(userId);
1516
- } catch (error) {
1517
- // Continue without full user data
1518
- user = {
1519
- id: userId
1520
- };
1521
- }
1522
- return {
1523
- valid: true,
1524
- userId,
1525
- user
1526
- };
1527
1364
  } catch (error) {
1528
1365
  return {
1529
1366
  valid: false,
@@ -1858,6 +1695,14 @@ export default OxyServices;
1858
1695
  // Re-export all models and types for convenience
1859
1696
  export * from '../models/interfaces';
1860
1697
  export * from '../models/secureSession';
1698
+
1699
+ // Clean middleware exports - these will be available for server-side use
1700
+ // Note: These require Express.js and are only for server-side applications
1701
+
1702
+ // Export a simple function to create auth middleware
1703
+ export const createAuthMiddleware = oxyServices => {
1704
+ return oxyServices.createAuthMiddleware();
1705
+ };
1861
1706
  if (typeof FormData === 'undefined') {
1862
1707
  console.warn('[OxyHQ/Services] FormData is not available. If you are using Hermes, add "import \'react-native-url-polyfill/auto\'" at the top of your app entry file.');
1863
1708
  }