@oxyhq/services 5.8.10 → 5.9.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.
- package/lib/commonjs/core/index.js +207 -283
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/node/index.js +0 -9
- package/lib/commonjs/node/index.js.map +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js +0 -4
- package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/RecoverAccountScreen.js +0 -4
- package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +16 -27
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +4 -18
- package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/commonjs/ui/styles/authStyles.js +1 -2
- package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
- package/lib/module/core/index.js +207 -283
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/node/index.js +0 -4
- package/lib/module/node/index.js.map +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js +0 -4
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/module/ui/screens/RecoverAccountScreen.js +0 -4
- package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +16 -27
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +4 -18
- package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/module/ui/styles/authStyles.js +1 -2
- package/lib/module/ui/styles/authStyles.js.map +1 -1
- package/lib/typescript/core/index.d.ts +29 -79
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/node/index.d.ts +0 -2
- package/lib/typescript/node/index.d.ts.map +1 -1
- package/lib/typescript/ui/screens/FeedbackScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
- package/lib/typescript/ui/styles/authStyles.d.ts +0 -1
- package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/core/index.ts +213 -254
- package/src/node/index.ts +0 -4
- package/src/ui/screens/FeedbackScreen.tsx +0 -4
- package/src/ui/screens/RecoverAccountScreen.tsx +0 -4
- package/src/ui/screens/SignInScreen.tsx +16 -20
- package/src/ui/screens/SignUpScreen.tsx +4 -14
- package/src/ui/styles/authStyles.ts +0 -1
- package/lib/commonjs/node/createAuth.js +0 -95
- package/lib/commonjs/node/createAuth.js.map +0 -1
- package/lib/module/node/createAuth.js +0 -90
- package/lib/module/node/createAuth.js.map +0 -1
- package/lib/typescript/node/createAuth.d.ts +0 -7
- package/lib/typescript/node/createAuth.d.ts.map +0 -1
- package/src/node/createAuth.ts +0 -116
package/lib/module/core/index.js
CHANGED
|
@@ -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
|
-
}
|
|
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
|
-
|
|
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.
|
|
74
|
+
if (error.response?.status === 401 && this.accessToken && originalRequest && !originalRequest.headers?.['X-Retry-After-Refresh']) {
|
|
65
75
|
try {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
newRequest
|
|
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
|
-
*
|
|
109
|
-
* @
|
|
110
|
-
|
|
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
|
|
124
|
+
* Set authentication tokens manually
|
|
125
|
+
* @param accessToken - The access token
|
|
126
|
+
* @param refreshToken - The refresh token (optional for session-based auth)
|
|
128
127
|
*/
|
|
129
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
153
|
-
* @
|
|
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
|
|
186
|
-
*/
|
|
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
|
|
142
|
+
* Get the current user ID from the stored token
|
|
143
|
+
* @returns User ID or null if not authenticated
|
|
212
144
|
*/
|
|
213
|
-
|
|
214
|
-
if (!this.
|
|
145
|
+
getCurrentUserId() {
|
|
146
|
+
if (!this.accessToken) return null;
|
|
215
147
|
try {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
});
|
|
148
|
+
const decoded = jwtDecode(this.accessToken);
|
|
149
|
+
return decoded.userId || decoded.id || null;
|
|
219
150
|
} catch (error) {
|
|
220
|
-
|
|
221
|
-
} finally {
|
|
222
|
-
this.accessToken = null;
|
|
223
|
-
this.refreshToken = null;
|
|
151
|
+
return null;
|
|
224
152
|
}
|
|
225
153
|
}
|
|
226
154
|
|
|
227
155
|
/**
|
|
228
|
-
*
|
|
229
|
-
* @
|
|
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
|
-
|
|
232
|
-
|
|
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
|
-
*
|
|
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
|
|
1164
|
-
* @param deviceFingerprint -
|
|
1165
|
-
* @returns
|
|
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 {
|
|
@@ -1370,34 +1265,42 @@ export class OxyServices {
|
|
|
1370
1265
|
});
|
|
1371
1266
|
}
|
|
1372
1267
|
|
|
1373
|
-
//
|
|
1374
|
-
|
|
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'
|
|
1393
|
-
});
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
// Get user ID from token using JWT decode instead of relying on getCurrentUserId
|
|
1268
|
+
// Check if token contains sessionId (new session-based system)
|
|
1269
|
+
let isValid = false;
|
|
1397
1270
|
let userId = null;
|
|
1398
1271
|
try {
|
|
1399
1272
|
const decoded = jwtDecode(token);
|
|
1400
1273
|
userId = decoded.userId || decoded.id;
|
|
1274
|
+
if (decoded.sessionId) {
|
|
1275
|
+
// Use session-based validation
|
|
1276
|
+
const tempOxyServices = new OxyServices({
|
|
1277
|
+
baseURL: this.client.defaults.baseURL || ''
|
|
1278
|
+
});
|
|
1279
|
+
tempOxyServices.setTokens(token, '');
|
|
1280
|
+
const validation = await tempOxyServices.validateSession(decoded.sessionId);
|
|
1281
|
+
isValid = validation.valid;
|
|
1282
|
+
if (isValid && loadFullUser) {
|
|
1283
|
+
req.user = validation.user;
|
|
1284
|
+
}
|
|
1285
|
+
} else {
|
|
1286
|
+
// Use old validation method
|
|
1287
|
+
const tempOxyServices = new OxyServices({
|
|
1288
|
+
baseURL: this.client.defaults.baseURL || ''
|
|
1289
|
+
});
|
|
1290
|
+
tempOxyServices.setTokens(token, '');
|
|
1291
|
+
isValid = await tempOxyServices.validate();
|
|
1292
|
+
if (isValid && loadFullUser) {
|
|
1293
|
+
try {
|
|
1294
|
+
const userProfile = await tempOxyServices.getUserById(userId);
|
|
1295
|
+
req.user = userProfile;
|
|
1296
|
+
} catch (userError) {
|
|
1297
|
+
// If we can't load user, continue with just ID
|
|
1298
|
+
req.user = {
|
|
1299
|
+
id: userId
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1401
1304
|
} catch (decodeError) {
|
|
1402
1305
|
const error = {
|
|
1403
1306
|
message: 'Invalid token payload',
|
|
@@ -1412,6 +1315,20 @@ export class OxyServices {
|
|
|
1412
1315
|
code: 'INVALID_PAYLOAD'
|
|
1413
1316
|
});
|
|
1414
1317
|
}
|
|
1318
|
+
if (!isValid) {
|
|
1319
|
+
const error = {
|
|
1320
|
+
message: 'Invalid or expired token',
|
|
1321
|
+
code: 'INVALID_TOKEN',
|
|
1322
|
+
status: 403
|
|
1323
|
+
};
|
|
1324
|
+
if (onError) {
|
|
1325
|
+
return onError(error);
|
|
1326
|
+
}
|
|
1327
|
+
return res.status(403).json({
|
|
1328
|
+
message: 'Invalid or expired token',
|
|
1329
|
+
code: 'INVALID_TOKEN'
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1415
1332
|
if (!userId) {
|
|
1416
1333
|
const error = {
|
|
1417
1334
|
message: 'Invalid token payload',
|
|
@@ -1431,18 +1348,8 @@ export class OxyServices {
|
|
|
1431
1348
|
req.userId = userId;
|
|
1432
1349
|
req.accessToken = token;
|
|
1433
1350
|
|
|
1434
|
-
//
|
|
1435
|
-
if (
|
|
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 {
|
|
1351
|
+
// Set user object if not already set by session validation
|
|
1352
|
+
if (!req.user) {
|
|
1446
1353
|
req.user = {
|
|
1447
1354
|
id: userId
|
|
1448
1355
|
};
|
|
@@ -1476,54 +1383,71 @@ export class OxyServices {
|
|
|
1476
1383
|
};
|
|
1477
1384
|
}
|
|
1478
1385
|
|
|
1479
|
-
//
|
|
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;
|
|
1386
|
+
// Check if token contains sessionId (new session-based system)
|
|
1496
1387
|
try {
|
|
1497
1388
|
const decoded = jwtDecode(token);
|
|
1498
|
-
userId = decoded.userId || decoded.id;
|
|
1389
|
+
const userId = decoded.userId || decoded.id;
|
|
1390
|
+
if (decoded.sessionId) {
|
|
1391
|
+
// Use session-based validation
|
|
1392
|
+
const tempOxyServices = new OxyServices({
|
|
1393
|
+
baseURL: this.client.defaults.baseURL || ''
|
|
1394
|
+
});
|
|
1395
|
+
tempOxyServices.setTokens(token, '');
|
|
1396
|
+
const validation = await tempOxyServices.validateSession(decoded.sessionId);
|
|
1397
|
+
if (validation.valid) {
|
|
1398
|
+
return {
|
|
1399
|
+
valid: true,
|
|
1400
|
+
userId,
|
|
1401
|
+
user: validation.user
|
|
1402
|
+
};
|
|
1403
|
+
} else {
|
|
1404
|
+
return {
|
|
1405
|
+
valid: false,
|
|
1406
|
+
error: 'Invalid or expired session'
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
} else {
|
|
1410
|
+
// Use old validation method
|
|
1411
|
+
const tempOxyServices = new OxyServices({
|
|
1412
|
+
baseURL: this.client.defaults.baseURL || ''
|
|
1413
|
+
});
|
|
1414
|
+
tempOxyServices.setTokens(token, '');
|
|
1415
|
+
const isValid = await tempOxyServices.validate();
|
|
1416
|
+
if (!isValid) {
|
|
1417
|
+
return {
|
|
1418
|
+
valid: false,
|
|
1419
|
+
error: 'Invalid or expired token'
|
|
1420
|
+
};
|
|
1421
|
+
}
|
|
1422
|
+
if (!userId) {
|
|
1423
|
+
return {
|
|
1424
|
+
valid: false,
|
|
1425
|
+
error: 'Invalid token payload'
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
// Try to get user profile
|
|
1430
|
+
let user;
|
|
1431
|
+
try {
|
|
1432
|
+
user = await tempOxyServices.getUserById(userId);
|
|
1433
|
+
} catch (error) {
|
|
1434
|
+
// Continue without full user data
|
|
1435
|
+
user = {
|
|
1436
|
+
id: userId
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
return {
|
|
1440
|
+
valid: true,
|
|
1441
|
+
userId,
|
|
1442
|
+
user
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1499
1445
|
} catch (decodeError) {
|
|
1500
1446
|
return {
|
|
1501
1447
|
valid: false,
|
|
1502
1448
|
error: 'Invalid token payload'
|
|
1503
1449
|
};
|
|
1504
1450
|
}
|
|
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
1451
|
} catch (error) {
|
|
1528
1452
|
return {
|
|
1529
1453
|
valid: false,
|