@oxyhq/services 5.7.2 → 5.7.4
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/README.md +287 -80
- package/lib/commonjs/core/index.js +0 -57
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/node/index.js +49 -2
- package/lib/commonjs/node/index.js.map +1 -1
- package/lib/commonjs/node/middleware.js +227 -0
- package/lib/commonjs/node/middleware.js.map +1 -0
- package/lib/commonjs/ui/context/OxyContext.js +9 -29
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +1 -4
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/commonjs/ui/index.js +16 -1
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/zero-config/index.js +25 -0
- package/lib/commonjs/ui/zero-config/index.js.map +1 -0
- package/lib/commonjs/ui/zero-config/provider.js +278 -0
- package/lib/commonjs/ui/zero-config/provider.js.map +1 -0
- package/lib/module/core/index.js +0 -57
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/node/index.js +11 -1
- package/lib/module/node/index.js.map +1 -1
- package/lib/module/node/middleware.js +199 -0
- package/lib/module/node/middleware.js.map +1 -0
- package/lib/module/ui/context/OxyContext.js +9 -29
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/useSessionSocket.js +1 -4
- package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/module/ui/index.js +16 -1
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/zero-config/index.js +8 -0
- package/lib/module/ui/zero-config/index.js.map +1 -0
- package/lib/module/ui/zero-config/provider.js +270 -0
- package/lib/module/ui/zero-config/provider.js.map +1 -0
- package/lib/typescript/core/index.d.ts +0 -6
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/node/index.d.ts +7 -1
- package/lib/typescript/node/index.d.ts.map +1 -1
- package/lib/typescript/node/middleware.d.ts +92 -0
- package/lib/typescript/node/middleware.d.ts.map +1 -0
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
- package/lib/typescript/ui/index.d.ts +2 -1
- package/lib/typescript/ui/index.d.ts.map +1 -1
- package/lib/typescript/ui/zero-config/index.d.ts +5 -0
- package/lib/typescript/ui/zero-config/index.d.ts.map +1 -0
- package/lib/typescript/ui/zero-config/provider.d.ts +84 -0
- package/lib/typescript/ui/zero-config/provider.d.ts.map +1 -0
- package/package.json +6 -1
- package/src/core/index.ts +0 -60
- package/src/node/index.ts +17 -1
- package/src/node/middleware.ts +234 -0
- package/src/ui/context/OxyContext.tsx +9 -29
- package/src/ui/hooks/useSessionSocket.ts +1 -4
- package/src/ui/index.ts +19 -1
- package/src/ui/zero-config/index.ts +11 -0
- package/src/ui/zero-config/provider.tsx +310 -0
package/README.md
CHANGED
|
@@ -1,137 +1,347 @@
|
|
|
1
1
|
# OxyHQServices
|
|
2
2
|
|
|
3
|
-
A TypeScript client library for the Oxy API providing authentication, user management, and UI components for React and React Native applications.
|
|
3
|
+
A TypeScript client library for the Oxy API providing **zero-config** authentication, user management, and UI components for React and React Native applications.
|
|
4
|
+
|
|
5
|
+
## ✨ Zero-Config Quick Start
|
|
6
|
+
|
|
7
|
+
### Frontend (React/Next.js) - 2 lines of code:
|
|
8
|
+
|
|
9
|
+
```jsx
|
|
10
|
+
import { OxyZeroConfigProvider, useOxyZeroConfig } from '@oxyhq/services/ui';
|
|
11
|
+
|
|
12
|
+
// 1. Wrap your app
|
|
13
|
+
function App() {
|
|
14
|
+
return (
|
|
15
|
+
<OxyZeroConfigProvider>
|
|
16
|
+
<YourApp />
|
|
17
|
+
</OxyZeroConfigProvider>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 2. Use authentication anywhere
|
|
22
|
+
function Dashboard() {
|
|
23
|
+
const { user, login, logout, isAuthenticated } = useOxyZeroConfig();
|
|
24
|
+
|
|
25
|
+
if (isAuthenticated) {
|
|
26
|
+
return <div>Welcome {user.username}! <button onClick={logout}>Logout</button></div>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return <button onClick={() => login('user', 'password')}>Login</button>;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Backend (Express.js) - 1 line of code:
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import express from 'express';
|
|
37
|
+
import { createOxyAuth } from '@oxyhq/services/node';
|
|
38
|
+
|
|
39
|
+
const app = express();
|
|
40
|
+
|
|
41
|
+
// Zero-config auth - req.user automatically available
|
|
42
|
+
app.use('/api', createOxyAuth());
|
|
43
|
+
|
|
44
|
+
app.get('/api/profile', (req, res) => {
|
|
45
|
+
res.json({ user: req.user }); // req.user populated automatically!
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**That's it!** No complex configuration, no manual token management, no middleware setup.
|
|
4
50
|
|
|
5
51
|
## Table of Contents
|
|
6
52
|
|
|
53
|
+
- [Zero-Config Guide](#-zero-config-quick-start)
|
|
7
54
|
- [Features](#features)
|
|
8
|
-
- [
|
|
55
|
+
- [Installation](#installation)
|
|
56
|
+
- [Complete Examples](#complete-examples)
|
|
57
|
+
- [Advanced Usage](#advanced-usage)
|
|
9
58
|
- [Documentation](#documentation)
|
|
10
|
-
- [
|
|
11
|
-
- [Package Exports](#package-exports)
|
|
12
|
-
- [Requirements](#requirements)
|
|
13
|
-
- [Development](#development)
|
|
14
|
-
- [Integration](#integration)
|
|
15
|
-
- [License](#license)
|
|
59
|
+
- [Migration Guide](#migration-guide)
|
|
16
60
|
|
|
17
61
|
## Features
|
|
18
62
|
|
|
19
|
-
-
|
|
63
|
+
- 🚀 **Zero-Config**: Get authentication working in 2-3 lines of code
|
|
64
|
+
- 🔐 **Automatic Token Management**: Tokens saved, restored, and refreshed automatically
|
|
20
65
|
- 👥 **User Management**: Profile operations and social features
|
|
21
|
-
- 🎨 **UI Components**: Pre-built React components for common functionality
|
|
66
|
+
- 🎨 **UI Components**: Pre-built React components for common functionality
|
|
22
67
|
- 📱 **Cross-Platform**: Works in React Native and web applications
|
|
23
68
|
- 🔧 **TypeScript**: Full type safety and IntelliSense support
|
|
69
|
+
- 🔄 **Auto Backend Integration**: Frontend automatically sends tokens to backend
|
|
70
|
+
- 📦 **Express Middleware**: One-line backend authentication with `req.user` support
|
|
24
71
|
|
|
25
|
-
##
|
|
72
|
+
## Installation
|
|
26
73
|
|
|
27
74
|
```bash
|
|
28
75
|
npm install @oxyhq/services
|
|
29
76
|
```
|
|
30
77
|
|
|
31
|
-
|
|
32
|
-
|
|
78
|
+
## Complete Examples
|
|
79
|
+
|
|
80
|
+
### React Application
|
|
81
|
+
|
|
82
|
+
**App.js**
|
|
83
|
+
```jsx
|
|
84
|
+
import React from 'react';
|
|
85
|
+
import { OxyZeroConfigProvider } from '@oxyhq/services/ui';
|
|
86
|
+
import Dashboard from './Dashboard';
|
|
87
|
+
|
|
88
|
+
export default function App() {
|
|
89
|
+
return (
|
|
90
|
+
<OxyZeroConfigProvider>
|
|
91
|
+
<Dashboard />
|
|
92
|
+
</OxyZeroConfigProvider>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Dashboard.js**
|
|
98
|
+
```jsx
|
|
99
|
+
import React from 'react';
|
|
100
|
+
import { useOxyZeroConfig } from '@oxyhq/services/ui';
|
|
101
|
+
|
|
102
|
+
export default function Dashboard() {
|
|
103
|
+
const { user, login, logout, isAuthenticated, isLoading } = useOxyZeroConfig();
|
|
104
|
+
|
|
105
|
+
if (isLoading) return <div>Loading...</div>;
|
|
106
|
+
|
|
107
|
+
if (!isAuthenticated) {
|
|
108
|
+
return (
|
|
109
|
+
<div>
|
|
110
|
+
<h1>Please log in</h1>
|
|
111
|
+
<button onClick={() => login('demo', 'password')}>Login</button>
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div>
|
|
118
|
+
<h1>Welcome, {user.username}!</h1>
|
|
119
|
+
<button onClick={logout}>Logout</button>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Express.js Backend
|
|
126
|
+
|
|
127
|
+
**server.js**
|
|
128
|
+
```js
|
|
129
|
+
import express from 'express';
|
|
130
|
+
import { createOxyAuth } from '@oxyhq/services/node';
|
|
33
131
|
|
|
34
|
-
const
|
|
35
|
-
|
|
132
|
+
const app = express();
|
|
133
|
+
app.use(express.json());
|
|
134
|
+
|
|
135
|
+
// Public routes
|
|
136
|
+
app.get('/', (req, res) => {
|
|
137
|
+
res.json({ message: 'Public endpoint' });
|
|
36
138
|
});
|
|
37
139
|
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
140
|
+
// Protected routes - zero config!
|
|
141
|
+
app.use('/api', createOxyAuth());
|
|
142
|
+
|
|
143
|
+
// req.user is automatically available
|
|
144
|
+
app.get('/api/profile', (req, res) => {
|
|
145
|
+
res.json({
|
|
146
|
+
message: `Hello ${req.user.username}!`,
|
|
147
|
+
user: req.user
|
|
148
|
+
});
|
|
42
149
|
});
|
|
43
150
|
|
|
44
|
-
|
|
45
|
-
const user = await oxy.users.getCurrentUser();
|
|
151
|
+
app.listen(3000, () => console.log('Server running on port 3000'));
|
|
46
152
|
```
|
|
47
153
|
|
|
48
|
-
|
|
154
|
+
### Next.js Full-Stack
|
|
49
155
|
|
|
50
|
-
|
|
156
|
+
**pages/_app.js**
|
|
157
|
+
```jsx
|
|
158
|
+
import { OxyZeroConfigProvider } from '@oxyhq/services/ui';
|
|
51
159
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
160
|
+
export default function App({ Component, pageProps }) {
|
|
161
|
+
return (
|
|
162
|
+
<OxyZeroConfigProvider>
|
|
163
|
+
<Component {...pageProps} />
|
|
164
|
+
</OxyZeroConfigProvider>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
```
|
|
56
168
|
|
|
57
|
-
|
|
169
|
+
**pages/api/user.js**
|
|
170
|
+
```js
|
|
171
|
+
import { createOxyAuth } from '@oxyhq/services/node';
|
|
172
|
+
|
|
173
|
+
const auth = createOxyAuth();
|
|
174
|
+
|
|
175
|
+
export default async function handler(req, res) {
|
|
176
|
+
// Apply authentication
|
|
177
|
+
await new Promise((resolve, reject) => {
|
|
178
|
+
auth(req, res, (err) => {
|
|
179
|
+
if (err) reject(err);
|
|
180
|
+
else resolve();
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// req.user is now available
|
|
185
|
+
res.json({ user: req.user });
|
|
186
|
+
}
|
|
187
|
+
```
|
|
58
188
|
|
|
59
|
-
|
|
189
|
+
## Advanced Usage
|
|
60
190
|
|
|
61
|
-
|
|
62
|
-
|
|
191
|
+
### Configuration Options
|
|
192
|
+
|
|
193
|
+
**Frontend**
|
|
194
|
+
```jsx
|
|
195
|
+
<OxyZeroConfigProvider
|
|
196
|
+
apiUrl="https://your-api.com"
|
|
197
|
+
onAuthChange={(user) => console.log('Auth changed:', user)}
|
|
198
|
+
>
|
|
199
|
+
<App />
|
|
200
|
+
</OxyZeroConfigProvider>
|
|
63
201
|
```
|
|
64
202
|
|
|
65
|
-
|
|
203
|
+
**Backend**
|
|
204
|
+
```js
|
|
205
|
+
app.use('/api', createOxyAuth({
|
|
206
|
+
baseURL: 'https://your-oxy-api.com',
|
|
207
|
+
loadUser: true,
|
|
208
|
+
publicPaths: ['/api/health'],
|
|
209
|
+
onError: (error, req, res) => {
|
|
210
|
+
res.status(error.status).json({ error: error.message });
|
|
211
|
+
}
|
|
212
|
+
}));
|
|
213
|
+
```
|
|
66
214
|
|
|
67
|
-
|
|
215
|
+
### Direct API Access
|
|
68
216
|
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
|
|
217
|
+
```jsx
|
|
218
|
+
import { useOxyApi } from '@oxyhq/services/ui';
|
|
219
|
+
|
|
220
|
+
function ProfileForm() {
|
|
221
|
+
const api = useOxyApi();
|
|
72
222
|
|
|
73
|
-
|
|
74
|
-
|
|
223
|
+
const updateProfile = async (data) => {
|
|
224
|
+
const user = await api.updateProfile(data);
|
|
225
|
+
// Token automatically included in request
|
|
226
|
+
};
|
|
75
227
|
|
|
76
|
-
|
|
77
|
-
|
|
228
|
+
return <button onClick={() => updateProfile({ name: 'New Name' })}>Update</button>;
|
|
229
|
+
}
|
|
78
230
|
```
|
|
79
231
|
|
|
80
|
-
|
|
232
|
+
### Optional Authentication
|
|
81
233
|
|
|
82
|
-
|
|
234
|
+
```js
|
|
235
|
+
import { createOptionalOxyAuth } from '@oxyhq/services/node';
|
|
83
236
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
import { createAuth } from '@oxyhq/services/core';
|
|
237
|
+
// Works with or without authentication
|
|
238
|
+
app.use('/api/content', createOptionalOxyAuth());
|
|
87
239
|
|
|
88
|
-
|
|
89
|
-
|
|
240
|
+
app.get('/api/content', (req, res) => {
|
|
241
|
+
if (req.user) {
|
|
242
|
+
res.json({ content: 'personalized', user: req.user });
|
|
243
|
+
} else {
|
|
244
|
+
res.json({ content: 'public' });
|
|
245
|
+
}
|
|
246
|
+
});
|
|
90
247
|
```
|
|
91
248
|
|
|
92
|
-
|
|
249
|
+
## Documentation
|
|
93
250
|
|
|
94
|
-
|
|
251
|
+
### Zero-Config Guide
|
|
252
|
+
- **[🚀 Zero-Config Setup Guide](./docs/zero-config.md)** - Complete guide with examples
|
|
95
253
|
|
|
96
|
-
|
|
97
|
-
- **
|
|
98
|
-
- **
|
|
99
|
-
- **
|
|
254
|
+
### Advanced Documentation
|
|
255
|
+
- **[📚 Full Documentation](./docs/README.md)** - Complete system documentation
|
|
256
|
+
- **[🚀 Quick Start Guide](./docs/quick-start.md)** - Traditional setup guide
|
|
257
|
+
- **[🔐 Core API Reference](./docs/core-api.md)** - Detailed API documentation
|
|
258
|
+
- **[💼 Integration Examples](./docs/examples/)** - More integration examples
|
|
100
259
|
|
|
101
|
-
|
|
260
|
+
### UI Components
|
|
261
|
+
- **[🎨 UI Components Guide](./docs/ui-components.md)** - React/RN component usage
|
|
102
262
|
|
|
103
|
-
|
|
263
|
+
## Migration Guide
|
|
104
264
|
|
|
105
|
-
|
|
265
|
+
### From Complex Setup
|
|
106
266
|
|
|
107
|
-
**
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
267
|
+
**Before (complex setup):**
|
|
268
|
+
```jsx
|
|
269
|
+
import { OxyProvider, useOxy } from '@oxyhq/services/ui';
|
|
270
|
+
import { OxyServices } from '@oxyhq/services';
|
|
111
271
|
|
|
112
|
-
|
|
272
|
+
const oxy = new OxyServices({ baseURL: 'http://localhost:3001' });
|
|
113
273
|
|
|
114
|
-
|
|
274
|
+
function App() {
|
|
275
|
+
return (
|
|
276
|
+
<OxyProvider oxyServices={oxy}>
|
|
277
|
+
<Dashboard />
|
|
278
|
+
</OxyProvider>
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
```
|
|
115
282
|
|
|
116
|
-
|
|
117
|
-
|
|
283
|
+
**After (zero-config):**
|
|
284
|
+
```jsx
|
|
285
|
+
import { OxyZeroConfigProvider, useOxyZeroConfig } from '@oxyhq/services/ui';
|
|
286
|
+
|
|
287
|
+
function App() {
|
|
288
|
+
return (
|
|
289
|
+
<OxyZeroConfigProvider>
|
|
290
|
+
<Dashboard />
|
|
291
|
+
</OxyZeroConfigProvider>
|
|
292
|
+
);
|
|
293
|
+
}
|
|
118
294
|
```
|
|
119
295
|
|
|
120
|
-
|
|
296
|
+
Just change the provider and hook names - the API is nearly identical!
|
|
121
297
|
|
|
122
|
-
|
|
298
|
+
### Package Exports
|
|
123
299
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
```
|
|
300
|
+
The library provides multiple entry points for different use cases:
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
// Zero-config frontend
|
|
304
|
+
import { OxyZeroConfigProvider, useOxyZeroConfig } from '@oxyhq/services/ui';
|
|
127
305
|
|
|
128
|
-
|
|
306
|
+
// Zero-config backend
|
|
307
|
+
import { createOxyAuth } from '@oxyhq/services/node';
|
|
129
308
|
|
|
309
|
+
// Core services only (traditional)
|
|
310
|
+
import { OxyServices } from '@oxyhq/services';
|
|
311
|
+
|
|
312
|
+
// Full package (Core + UI + Node)
|
|
313
|
+
import { OxyServices, OxyProvider, createOxyAuth } from '@oxyhq/services/full';
|
|
130
314
|
```
|
|
131
|
-
|
|
315
|
+
|
|
316
|
+
## Requirements
|
|
317
|
+
|
|
318
|
+
- **Node.js** 16+ (for backend usage)
|
|
319
|
+
- **React** 16.8+ (for React components)
|
|
320
|
+
- **React Native** 0.60+ (for mobile components)
|
|
321
|
+
- **TypeScript** 4.0+ (optional but recommended)
|
|
322
|
+
|
|
323
|
+
## Troubleshooting
|
|
324
|
+
|
|
325
|
+
### Common Issues
|
|
326
|
+
|
|
327
|
+
**"useOxyZeroConfig must be used within an OxyZeroConfigProvider"**
|
|
328
|
+
- Make sure your component is wrapped with `<OxyZeroConfigProvider>`
|
|
329
|
+
|
|
330
|
+
**"req.user is undefined"**
|
|
331
|
+
- Ensure the middleware is applied: `app.use('/api', createOxyAuth())`
|
|
332
|
+
- Check that the client sends `Authorization: Bearer <token>` header
|
|
333
|
+
|
|
334
|
+
**FormData Issues in React Native/Expo**
|
|
335
|
+
Add this import as the first line of your app entry file:
|
|
336
|
+
```js
|
|
337
|
+
import 'react-native-url-polyfill/auto';
|
|
132
338
|
```
|
|
133
339
|
|
|
134
|
-
|
|
340
|
+
### Getting Help
|
|
341
|
+
|
|
342
|
+
1. Check the [Zero-Config Guide](./docs/zero-config.md) for complete examples
|
|
343
|
+
2. Review [Troubleshooting Guide](./docs/troubleshooting.md) for common issues
|
|
344
|
+
3. Open an issue on [GitHub](https://github.com/oxyhq/services/issues)
|
|
135
345
|
|
|
136
346
|
## Development
|
|
137
347
|
|
|
@@ -142,20 +352,17 @@ npm install
|
|
|
142
352
|
# Build the library
|
|
143
353
|
npm run build
|
|
144
354
|
|
|
145
|
-
# Run tests
|
|
355
|
+
# Run tests
|
|
146
356
|
npm test
|
|
147
|
-
|
|
148
|
-
# Development mode
|
|
149
|
-
npm run dev
|
|
150
357
|
```
|
|
151
358
|
|
|
152
359
|
## Integration
|
|
153
360
|
|
|
154
361
|
This library works with:
|
|
155
|
-
- **[Oxy API](../
|
|
156
|
-
- **Express.js** - Built-in middleware support
|
|
157
|
-
- **React/React Native** - UI components and hooks
|
|
158
|
-
- **Next.js** - SSR/SSG authentication
|
|
362
|
+
- **[Oxy API](../api/)** - The companion authentication server
|
|
363
|
+
- **Express.js** - Built-in zero-config middleware support
|
|
364
|
+
- **React/React Native** - Zero-config UI components and hooks
|
|
365
|
+
- **Next.js** - SSR/SSG authentication support
|
|
159
366
|
|
|
160
367
|
## License
|
|
161
368
|
|
|
@@ -1396,22 +1396,6 @@ class OxyServices {
|
|
|
1396
1396
|
});
|
|
1397
1397
|
}
|
|
1398
1398
|
|
|
1399
|
-
// Validate JWT format before attempting to decode
|
|
1400
|
-
if (!this.isValidJwtFormat(token)) {
|
|
1401
|
-
const error = {
|
|
1402
|
-
message: 'Invalid token format',
|
|
1403
|
-
code: 'INVALID_TOKEN_FORMAT',
|
|
1404
|
-
status: 401
|
|
1405
|
-
};
|
|
1406
|
-
if (onError) {
|
|
1407
|
-
return onError(error);
|
|
1408
|
-
}
|
|
1409
|
-
return res.status(401).json({
|
|
1410
|
-
message: 'Invalid token format',
|
|
1411
|
-
code: 'INVALID_TOKEN_FORMAT'
|
|
1412
|
-
});
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
1399
|
// Create a temporary OxyServices instance with the token to validate it
|
|
1416
1400
|
const tempOxyServices = new OxyServices({
|
|
1417
1401
|
baseURL: this.client.defaults.baseURL || ''
|
|
@@ -1441,8 +1425,6 @@ class OxyServices {
|
|
|
1441
1425
|
const decoded = (0, _jwtDecode.jwtDecode)(token);
|
|
1442
1426
|
userId = decoded.userId || decoded.id;
|
|
1443
1427
|
} catch (decodeError) {
|
|
1444
|
-
console.error('JWT decode error:', decodeError);
|
|
1445
|
-
console.error('Token being decoded:', token.substring(0, 20) + '...');
|
|
1446
1428
|
const error = {
|
|
1447
1429
|
message: 'Invalid token payload',
|
|
1448
1430
|
code: 'INVALID_PAYLOAD',
|
|
@@ -1520,14 +1502,6 @@ class OxyServices {
|
|
|
1520
1502
|
};
|
|
1521
1503
|
}
|
|
1522
1504
|
|
|
1523
|
-
// Validate JWT format before attempting to decode
|
|
1524
|
-
if (!this.isValidJwtFormat(token)) {
|
|
1525
|
-
return {
|
|
1526
|
-
valid: false,
|
|
1527
|
-
error: 'Invalid token format'
|
|
1528
|
-
};
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
1505
|
// Create a temporary OxyServices instance with the token
|
|
1532
1506
|
const tempOxyServices = new OxyServices({
|
|
1533
1507
|
baseURL: this.client.defaults.baseURL || ''
|
|
@@ -1584,37 +1558,6 @@ class OxyServices {
|
|
|
1584
1558
|
}
|
|
1585
1559
|
}
|
|
1586
1560
|
|
|
1587
|
-
/**
|
|
1588
|
-
* Validate JWT token format
|
|
1589
|
-
* @param token - The token to validate
|
|
1590
|
-
* @returns Boolean indicating if the token has valid JWT format
|
|
1591
|
-
*/
|
|
1592
|
-
isValidJwtFormat(token) {
|
|
1593
|
-
if (!token || typeof token !== 'string') {
|
|
1594
|
-
return false;
|
|
1595
|
-
}
|
|
1596
|
-
|
|
1597
|
-
// JWT tokens should have 3 parts separated by dots
|
|
1598
|
-
const parts = token.split('.');
|
|
1599
|
-
if (parts.length !== 3) {
|
|
1600
|
-
return false;
|
|
1601
|
-
}
|
|
1602
|
-
|
|
1603
|
-
// Each part should be a valid base64 string
|
|
1604
|
-
try {
|
|
1605
|
-
parts.forEach(part => {
|
|
1606
|
-
if (!part || part.trim() === '') {
|
|
1607
|
-
throw new Error('Empty part');
|
|
1608
|
-
}
|
|
1609
|
-
// Try to decode base64 (this will throw if invalid)
|
|
1610
|
-
Buffer.from(part, 'base64');
|
|
1611
|
-
});
|
|
1612
|
-
return true;
|
|
1613
|
-
} catch (error) {
|
|
1614
|
-
return false;
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
|
|
1618
1561
|
/**
|
|
1619
1562
|
* Centralized error handling
|
|
1620
1563
|
* @private
|