@oxyhq/services 5.7.4 → 5.7.5
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 +121 -264
- package/lib/commonjs/core/auth-manager.js +440 -0
- package/lib/commonjs/core/auth-manager.js.map +1 -0
- package/lib/commonjs/core/index.js +102 -5
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/core/use-auth.js +244 -0
- package/lib/commonjs/core/use-auth.js.map +1 -0
- package/lib/commonjs/node/index.js +2 -49
- package/lib/commonjs/node/index.js.map +1 -1
- package/lib/commonjs/ui/index.js +1 -16
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/module/core/auth-manager.js +432 -0
- package/lib/module/core/auth-manager.js.map +1 -0
- package/lib/module/core/index.js +41 -5
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/core/use-auth.js +235 -0
- package/lib/module/core/use-auth.js.map +1 -0
- package/lib/module/node/index.js +1 -11
- package/lib/module/node/index.js.map +1 -1
- package/lib/module/ui/index.js +1 -16
- package/lib/module/ui/index.js.map +1 -1
- package/lib/typescript/core/auth-manager.d.ts +136 -0
- package/lib/typescript/core/auth-manager.d.ts.map +1 -0
- package/lib/typescript/core/index.d.ts +24 -1
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/core/use-auth.d.ts +79 -0
- package/lib/typescript/core/use-auth.d.ts.map +1 -0
- package/lib/typescript/node/index.d.ts +1 -7
- package/lib/typescript/node/index.d.ts.map +1 -1
- package/lib/typescript/ui/index.d.ts +1 -2
- package/lib/typescript/ui/index.d.ts.map +1 -1
- package/package.json +4 -6
- package/src/__tests__/zero-config-auth.test.ts +607 -0
- package/src/core/auth-manager.ts +500 -0
- package/src/core/index.ts +41 -6
- package/src/core/use-auth.tsx +245 -0
- package/src/node/index.ts +1 -17
- package/src/ui/index.ts +1 -19
- package/lib/commonjs/node/middleware.js +0 -227
- package/lib/commonjs/node/middleware.js.map +0 -1
- package/lib/commonjs/ui/zero-config/index.js +0 -25
- package/lib/commonjs/ui/zero-config/index.js.map +0 -1
- package/lib/commonjs/ui/zero-config/provider.js +0 -278
- package/lib/commonjs/ui/zero-config/provider.js.map +0 -1
- package/lib/module/node/middleware.js +0 -199
- package/lib/module/node/middleware.js.map +0 -1
- package/lib/module/ui/zero-config/index.js +0 -8
- package/lib/module/ui/zero-config/index.js.map +0 -1
- package/lib/module/ui/zero-config/provider.js +0 -270
- package/lib/module/ui/zero-config/provider.js.map +0 -1
- package/lib/typescript/node/middleware.d.ts +0 -92
- package/lib/typescript/node/middleware.d.ts.map +0 -1
- package/lib/typescript/ui/zero-config/index.d.ts +0 -5
- package/lib/typescript/ui/zero-config/index.d.ts.map +0 -1
- package/lib/typescript/ui/zero-config/provider.d.ts +0 -84
- package/lib/typescript/ui/zero-config/provider.d.ts.map +0 -1
- package/src/node/middleware.ts +0 -234
- package/src/ui/zero-config/index.ts +0 -11
- package/src/ui/zero-config/provider.tsx +0 -310
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-Config Authentication Hook for React/React Native
|
|
3
|
+
*
|
|
4
|
+
* Provides automatic authentication state management with minimal setup required.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useState, useEffect, useCallback, useContext, createContext, ReactNode } from 'react';
|
|
8
|
+
import { AuthenticationManager, getAuthManager, initializeAuth } from './auth-manager';
|
|
9
|
+
|
|
10
|
+
interface AuthState {
|
|
11
|
+
isAuthenticated: boolean;
|
|
12
|
+
isLoading: boolean;
|
|
13
|
+
user: any | null;
|
|
14
|
+
error: string | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface AuthContextValue extends AuthState {
|
|
18
|
+
login: (username: string, password: string) => Promise<void>;
|
|
19
|
+
register: (username: string, email: string, password: string) => Promise<void>;
|
|
20
|
+
logout: () => Promise<void>;
|
|
21
|
+
getCurrentUser: () => Promise<any>;
|
|
22
|
+
checkUsernameAvailability: (username: string) => Promise<{ available: boolean; message: string }>;
|
|
23
|
+
checkEmailAvailability: (email: string) => Promise<{ available: boolean; message: string }>;
|
|
24
|
+
clearError: () => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const AuthContext = createContext<AuthContextValue | null>(null);
|
|
28
|
+
|
|
29
|
+
interface AuthProviderProps {
|
|
30
|
+
children: ReactNode;
|
|
31
|
+
baseURL?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Authentication Provider Component
|
|
36
|
+
*
|
|
37
|
+
* Wrap your app with this provider to enable zero-config authentication.
|
|
38
|
+
* All authentication state will be automatically managed.
|
|
39
|
+
*/
|
|
40
|
+
export function AuthProvider({ children, baseURL = 'https://api.oxy.so' }: AuthProviderProps) {
|
|
41
|
+
const [state, setState] = useState<AuthState>({
|
|
42
|
+
isAuthenticated: false,
|
|
43
|
+
isLoading: true,
|
|
44
|
+
user: null,
|
|
45
|
+
error: null,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const authManager = initializeAuth(baseURL);
|
|
49
|
+
|
|
50
|
+
// Update state when auth manager state changes
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
const unsubscribe = authManager.onAuthStateChange((authState) => {
|
|
53
|
+
setState(prevState => ({
|
|
54
|
+
...prevState,
|
|
55
|
+
isAuthenticated: authState.isAuthenticated,
|
|
56
|
+
user: authState.user,
|
|
57
|
+
isLoading: false,
|
|
58
|
+
}));
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return unsubscribe;
|
|
62
|
+
}, [authManager]);
|
|
63
|
+
|
|
64
|
+
const login = useCallback(async (username: string, password: string) => {
|
|
65
|
+
setState(prev => ({ ...prev, isLoading: true, error: null }));
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
await authManager.login({ username, password });
|
|
69
|
+
// State will be updated via the auth state change listener
|
|
70
|
+
} catch (error) {
|
|
71
|
+
setState(prev => ({
|
|
72
|
+
...prev,
|
|
73
|
+
isLoading: false,
|
|
74
|
+
error: error instanceof Error ? error.message : 'Login failed',
|
|
75
|
+
}));
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}, [authManager]);
|
|
79
|
+
|
|
80
|
+
const register = useCallback(async (username: string, email: string, password: string) => {
|
|
81
|
+
setState(prev => ({ ...prev, isLoading: true, error: null }));
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
await authManager.register({ username, email, password });
|
|
85
|
+
// State will be updated via the auth state change listener
|
|
86
|
+
} catch (error) {
|
|
87
|
+
setState(prev => ({
|
|
88
|
+
...prev,
|
|
89
|
+
isLoading: false,
|
|
90
|
+
error: error instanceof Error ? error.message : 'Registration failed',
|
|
91
|
+
}));
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}, [authManager]);
|
|
95
|
+
|
|
96
|
+
const logout = useCallback(async () => {
|
|
97
|
+
setState(prev => ({ ...prev, isLoading: true, error: null }));
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
await authManager.logout();
|
|
101
|
+
// State will be updated via the auth state change listener
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error('Logout error:', error);
|
|
104
|
+
setState(prev => ({
|
|
105
|
+
...prev,
|
|
106
|
+
isLoading: false,
|
|
107
|
+
error: error instanceof Error ? error.message : 'Logout failed',
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
}, [authManager]);
|
|
111
|
+
|
|
112
|
+
const getCurrentUser = useCallback(async () => {
|
|
113
|
+
try {
|
|
114
|
+
return await authManager.getCurrentUser();
|
|
115
|
+
} catch (error) {
|
|
116
|
+
setState(prev => ({
|
|
117
|
+
...prev,
|
|
118
|
+
error: error instanceof Error ? error.message : 'Failed to get current user',
|
|
119
|
+
}));
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}, [authManager]);
|
|
123
|
+
|
|
124
|
+
const checkUsernameAvailability = useCallback(async (username: string) => {
|
|
125
|
+
return await authManager.checkUsernameAvailability(username);
|
|
126
|
+
}, [authManager]);
|
|
127
|
+
|
|
128
|
+
const checkEmailAvailability = useCallback(async (email: string) => {
|
|
129
|
+
return await authManager.checkEmailAvailability(email);
|
|
130
|
+
}, [authManager]);
|
|
131
|
+
|
|
132
|
+
const clearError = useCallback(() => {
|
|
133
|
+
setState(prev => ({ ...prev, error: null }));
|
|
134
|
+
}, []);
|
|
135
|
+
|
|
136
|
+
const contextValue: AuthContextValue = {
|
|
137
|
+
...state,
|
|
138
|
+
login,
|
|
139
|
+
register,
|
|
140
|
+
logout,
|
|
141
|
+
getCurrentUser,
|
|
142
|
+
checkUsernameAvailability,
|
|
143
|
+
checkEmailAvailability,
|
|
144
|
+
clearError,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<AuthContext.Provider value={contextValue}>
|
|
149
|
+
{children}
|
|
150
|
+
</AuthContext.Provider>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Authentication Hook
|
|
156
|
+
*
|
|
157
|
+
* Use this hook in any component to access authentication state and methods.
|
|
158
|
+
* No additional setup required - just wrap your app with AuthProvider.
|
|
159
|
+
*/
|
|
160
|
+
export function useAuth(): AuthContextValue {
|
|
161
|
+
const context = useContext(AuthContext);
|
|
162
|
+
|
|
163
|
+
if (!context) {
|
|
164
|
+
throw new Error('useAuth must be used within an AuthProvider');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return context;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Higher-Order Component for authentication
|
|
172
|
+
*
|
|
173
|
+
* Wraps a component to ensure user is authenticated before rendering.
|
|
174
|
+
* Automatically redirects to login if not authenticated.
|
|
175
|
+
*/
|
|
176
|
+
export function withAuth<P extends object>(
|
|
177
|
+
Component: React.ComponentType<P>,
|
|
178
|
+
options: {
|
|
179
|
+
redirectTo?: () => void;
|
|
180
|
+
LoadingComponent?: React.ComponentType;
|
|
181
|
+
requireAuth?: boolean;
|
|
182
|
+
} = {}
|
|
183
|
+
) {
|
|
184
|
+
const {
|
|
185
|
+
redirectTo,
|
|
186
|
+
LoadingComponent = () => null,
|
|
187
|
+
requireAuth = true,
|
|
188
|
+
} = options;
|
|
189
|
+
|
|
190
|
+
return function AuthenticatedComponent(props: P) {
|
|
191
|
+
const { isAuthenticated, isLoading } = useAuth();
|
|
192
|
+
|
|
193
|
+
if (isLoading) {
|
|
194
|
+
return <LoadingComponent />;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (requireAuth && !isAuthenticated) {
|
|
198
|
+
if (redirectTo) {
|
|
199
|
+
redirectTo();
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Default behavior - render nothing if not authenticated
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (!requireAuth && isAuthenticated) {
|
|
208
|
+
// Component should only be shown to non-authenticated users
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return <Component {...props} />;
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Hook for authenticated API calls
|
|
218
|
+
*
|
|
219
|
+
* Returns an authenticated HTTP client that automatically handles tokens.
|
|
220
|
+
*/
|
|
221
|
+
export function useOxyClient() {
|
|
222
|
+
const authManager = getAuthManager();
|
|
223
|
+
return authManager.getClient();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Hook for authentication status only (minimal re-renders)
|
|
228
|
+
*/
|
|
229
|
+
export function useAuthStatus(): { isAuthenticated: boolean; isLoading: boolean } {
|
|
230
|
+
const { isAuthenticated, isLoading } = useAuth();
|
|
231
|
+
return { isAuthenticated, isLoading };
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Hook for current user data
|
|
236
|
+
*/
|
|
237
|
+
export function useCurrentUser(): { user: any | null; isLoading: boolean; refetch: () => Promise<any> } {
|
|
238
|
+
const { user, isLoading, getCurrentUser } = useAuth();
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
user,
|
|
242
|
+
isLoading,
|
|
243
|
+
refetch: getCurrentUser,
|
|
244
|
+
};
|
|
245
|
+
}
|
package/src/node/index.ts
CHANGED
|
@@ -1,19 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Node.js
|
|
3
|
-
*
|
|
4
|
-
* This module provides zero-config Express.js middleware and utilities
|
|
5
|
-
* for backend integration with OxyHQ Services.
|
|
2
|
+
* OxyHQServices Node.js Entry Point
|
|
6
3
|
*/
|
|
7
4
|
|
|
8
|
-
// Export the zero-config middleware
|
|
9
|
-
export {
|
|
10
|
-
createOxyAuth,
|
|
11
|
-
createOptionalOxyAuth,
|
|
12
|
-
createOxyExpressApp,
|
|
13
|
-
type OxyAuthConfig,
|
|
14
|
-
type AuthenticatedRequest
|
|
15
|
-
} from './middleware';
|
|
16
|
-
|
|
17
5
|
// ------------- Core Imports -------------
|
|
18
6
|
import { OxyServices, OXY_CLOUD_URL } from '../core'; // Adjusted path
|
|
19
7
|
import { createAuth } from './createAuth';
|
|
@@ -28,10 +16,6 @@ export { createAuth };
|
|
|
28
16
|
// ------------- Model Exports -------------
|
|
29
17
|
export { Models }; // Export all models as a namespace
|
|
30
18
|
export * from '../models/interfaces'; // Export all models directly
|
|
31
|
-
export * from '../models/secureSession';
|
|
32
|
-
|
|
33
|
-
// Re-export utilities
|
|
34
|
-
export { DeviceManager } from '../utils/deviceManager';
|
|
35
19
|
|
|
36
20
|
// Default export for consistency or specific use cases if needed
|
|
37
21
|
export default OxyServices;
|
package/src/ui/index.ts
CHANGED
|
@@ -9,9 +9,6 @@ import isFrontend from './isFrontend';
|
|
|
9
9
|
// Real UI exports
|
|
10
10
|
let OxyProvider, OxySignInButton, OxyLogo, Avatar, FollowButton, OxyPayButton, FontLoader, setupFonts, OxyIcon, useOxy, useOxyAuth, useOxyUser, useOxyKarma, useOxyPayments, useOxyDevices, useOxyNotifications, useOxySocket, useOxyQR, useOxyIAP, OxyContextProvider, OxyContextState, OxyContextProviderProps, useFollow, ProfileScreen, OxyRouter, useAuthStore, fontFamilies, fontStyles, toast;
|
|
11
11
|
|
|
12
|
-
// Zero-config exports
|
|
13
|
-
let OxyZeroConfigProvider, useOxyZeroConfig, useOxyApi;
|
|
14
|
-
|
|
15
12
|
if (isFrontend) {
|
|
16
13
|
OxyProvider = require('./components/OxyProvider').default;
|
|
17
14
|
OxySignInButton = require('./components/OxySignInButton').default;
|
|
@@ -33,11 +30,6 @@ if (isFrontend) {
|
|
|
33
30
|
fontFamilies = require('./styles/fonts').fontFamilies;
|
|
34
31
|
fontStyles = require('./styles/fonts').fontStyles;
|
|
35
32
|
toast = require('../lib/sonner').toast;
|
|
36
|
-
|
|
37
|
-
// Zero-config components
|
|
38
|
-
OxyZeroConfigProvider = require('./zero-config').OxyZeroConfigProvider;
|
|
39
|
-
useOxyZeroConfig = require('./zero-config').useOxyZeroConfig;
|
|
40
|
-
useOxyApi = require('./zero-config').useOxyApi;
|
|
41
33
|
} else {
|
|
42
34
|
// Backend: no-op fallbacks
|
|
43
35
|
const noopComponent = () => null;
|
|
@@ -62,11 +54,6 @@ if (isFrontend) {
|
|
|
62
54
|
fontFamilies = {};
|
|
63
55
|
fontStyles = {};
|
|
64
56
|
toast = () => {};
|
|
65
|
-
|
|
66
|
-
// Zero-config no-ops
|
|
67
|
-
OxyZeroConfigProvider = noopComponent;
|
|
68
|
-
useOxyZeroConfig = noopHook;
|
|
69
|
-
useOxyApi = () => ({});
|
|
70
57
|
}
|
|
71
58
|
|
|
72
59
|
export {
|
|
@@ -89,12 +76,7 @@ export {
|
|
|
89
76
|
useAuthStore,
|
|
90
77
|
fontFamilies,
|
|
91
78
|
fontStyles,
|
|
92
|
-
toast
|
|
93
|
-
|
|
94
|
-
// Zero-config exports
|
|
95
|
-
OxyZeroConfigProvider,
|
|
96
|
-
useOxyZeroConfig,
|
|
97
|
-
useOxyApi
|
|
79
|
+
toast
|
|
98
80
|
};
|
|
99
81
|
|
|
100
82
|
// Re-export core services for convenience in UI context
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
var _exportNames = {
|
|
7
|
-
createOxyAuth: true,
|
|
8
|
-
createOptionalOxyAuth: true,
|
|
9
|
-
createOxyExpressApp: true,
|
|
10
|
-
OxyServices: true
|
|
11
|
-
};
|
|
12
|
-
Object.defineProperty(exports, "OxyServices", {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function () {
|
|
15
|
-
return _core.OxyServices;
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
exports.createOptionalOxyAuth = createOptionalOxyAuth;
|
|
19
|
-
exports.createOxyAuth = createOxyAuth;
|
|
20
|
-
exports.createOxyExpressApp = createOxyExpressApp;
|
|
21
|
-
var _core = require("../core");
|
|
22
|
-
var _interfaces = require("../models/interfaces");
|
|
23
|
-
Object.keys(_interfaces).forEach(function (key) {
|
|
24
|
-
if (key === "default" || key === "__esModule") return;
|
|
25
|
-
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
26
|
-
if (key in exports && exports[key] === _interfaces[key]) return;
|
|
27
|
-
Object.defineProperty(exports, key, {
|
|
28
|
-
enumerable: true,
|
|
29
|
-
get: function () {
|
|
30
|
-
return _interfaces[key];
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
/**
|
|
35
|
-
* Zero-config Express middleware for OxyHQ Services authentication
|
|
36
|
-
*
|
|
37
|
-
* This provides a simple, one-line solution for adding authentication to Express apps.
|
|
38
|
-
* Simply import and use: app.use('/api', createOxyAuth())
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Creates zero-config authentication middleware for Express.js
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* ```typescript
|
|
46
|
-
* import express from 'express';
|
|
47
|
-
* import { createOxyAuth } from '@oxyhq/services/node';
|
|
48
|
-
*
|
|
49
|
-
* const app = express();
|
|
50
|
-
*
|
|
51
|
-
* // Zero-config auth for all /api routes
|
|
52
|
-
* app.use('/api', createOxyAuth());
|
|
53
|
-
*
|
|
54
|
-
* // Now all routes under /api automatically have req.user available
|
|
55
|
-
* app.get('/api/profile', (req, res) => {
|
|
56
|
-
* res.json({ user: req.user }); // req.user is automatically available
|
|
57
|
-
* });
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
function createOxyAuth(config = {}) {
|
|
61
|
-
const {
|
|
62
|
-
baseURL = process.env.OXY_API_URL || 'http://localhost:3001',
|
|
63
|
-
loadUser = true,
|
|
64
|
-
publicPaths = [],
|
|
65
|
-
onError
|
|
66
|
-
} = config;
|
|
67
|
-
const oxy = new _core.OxyServices({
|
|
68
|
-
baseURL
|
|
69
|
-
});
|
|
70
|
-
return async (req, res, next) => {
|
|
71
|
-
// Check if this is a public path
|
|
72
|
-
const isPublicPath = publicPaths.some(path => req.path === path || req.path.startsWith(path + '/'));
|
|
73
|
-
if (isPublicPath) {
|
|
74
|
-
return next();
|
|
75
|
-
}
|
|
76
|
-
try {
|
|
77
|
-
const authHeader = req.headers['authorization'];
|
|
78
|
-
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
|
79
|
-
|
|
80
|
-
if (!token) {
|
|
81
|
-
const error = {
|
|
82
|
-
message: 'Access token required',
|
|
83
|
-
code: 'MISSING_TOKEN',
|
|
84
|
-
status: 401
|
|
85
|
-
};
|
|
86
|
-
if (onError) {
|
|
87
|
-
return onError(error, req, res);
|
|
88
|
-
}
|
|
89
|
-
return res.status(401).json({
|
|
90
|
-
error: 'Access token required',
|
|
91
|
-
code: 'MISSING_TOKEN'
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Validate token using the OxyServices client
|
|
96
|
-
const authResult = await oxy.authenticateToken(token);
|
|
97
|
-
if (!authResult.valid) {
|
|
98
|
-
const error = {
|
|
99
|
-
message: authResult.error || 'Invalid token',
|
|
100
|
-
code: 'INVALID_TOKEN',
|
|
101
|
-
status: 403
|
|
102
|
-
};
|
|
103
|
-
if (onError) {
|
|
104
|
-
return onError(error, req, res);
|
|
105
|
-
}
|
|
106
|
-
return res.status(403).json({
|
|
107
|
-
error: authResult.error || 'Invalid token',
|
|
108
|
-
code: 'INVALID_TOKEN'
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Attach user data to request
|
|
113
|
-
req.userId = authResult.userId;
|
|
114
|
-
req.accessToken = token;
|
|
115
|
-
if (loadUser && authResult.user) {
|
|
116
|
-
req.user = authResult.user;
|
|
117
|
-
} else {
|
|
118
|
-
req.user = {
|
|
119
|
-
id: authResult.userId
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
next();
|
|
123
|
-
} catch (error) {
|
|
124
|
-
const apiError = {
|
|
125
|
-
message: error.message || 'Authentication failed',
|
|
126
|
-
code: error.code || 'AUTH_ERROR',
|
|
127
|
-
status: error.status || 500
|
|
128
|
-
};
|
|
129
|
-
if (onError) {
|
|
130
|
-
return onError(apiError, req, res);
|
|
131
|
-
}
|
|
132
|
-
res.status(apiError.status).json({
|
|
133
|
-
error: apiError.message,
|
|
134
|
-
code: apiError.code
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Creates optional authentication middleware
|
|
142
|
-
* This middleware will attach user data if a valid token is present, but won't fail if missing
|
|
143
|
-
*
|
|
144
|
-
* @example
|
|
145
|
-
* ```typescript
|
|
146
|
-
* import { createOptionalOxyAuth } from '@oxyhq/services/node';
|
|
147
|
-
*
|
|
148
|
-
* app.use('/api', createOptionalOxyAuth());
|
|
149
|
-
*
|
|
150
|
-
* app.get('/api/content', (req, res) => {
|
|
151
|
-
* if (req.user) {
|
|
152
|
-
* // User is authenticated, show personalized content
|
|
153
|
-
* res.json({ content: 'personalized', user: req.user });
|
|
154
|
-
* } else {
|
|
155
|
-
* // Anonymous user, show public content
|
|
156
|
-
* res.json({ content: 'public' });
|
|
157
|
-
* }
|
|
158
|
-
* });
|
|
159
|
-
* ```
|
|
160
|
-
*/
|
|
161
|
-
function createOptionalOxyAuth(config = {}) {
|
|
162
|
-
const {
|
|
163
|
-
baseURL = process.env.OXY_API_URL || 'http://localhost:3001',
|
|
164
|
-
loadUser = true
|
|
165
|
-
} = config;
|
|
166
|
-
const oxy = new _core.OxyServices({
|
|
167
|
-
baseURL
|
|
168
|
-
});
|
|
169
|
-
return async (req, res, next) => {
|
|
170
|
-
try {
|
|
171
|
-
const authHeader = req.headers['authorization'];
|
|
172
|
-
const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
|
|
173
|
-
|
|
174
|
-
if (!token) {
|
|
175
|
-
// No token provided, continue without authentication
|
|
176
|
-
return next();
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Validate token using the OxyServices client
|
|
180
|
-
const authResult = await oxy.authenticateToken(token);
|
|
181
|
-
if (authResult.valid) {
|
|
182
|
-
// Attach user data to request if token is valid
|
|
183
|
-
req.userId = authResult.userId;
|
|
184
|
-
req.accessToken = token;
|
|
185
|
-
if (loadUser && authResult.user) {
|
|
186
|
-
req.user = authResult.user;
|
|
187
|
-
} else {
|
|
188
|
-
req.user = {
|
|
189
|
-
id: authResult.userId
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
next();
|
|
194
|
-
} catch (error) {
|
|
195
|
-
// If there's an error, continue without authentication
|
|
196
|
-
// This makes the middleware truly optional
|
|
197
|
-
next();
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Utility function to quickly set up a complete Express app with authentication
|
|
204
|
-
*
|
|
205
|
-
* @example
|
|
206
|
-
* ```typescript
|
|
207
|
-
* import { createOxyExpressApp } from '@oxyhq/services/node';
|
|
208
|
-
*
|
|
209
|
-
* const app = createOxyExpressApp();
|
|
210
|
-
*
|
|
211
|
-
* // All routes automatically have authentication and req.user available
|
|
212
|
-
* app.get('/api/profile', (req, res) => {
|
|
213
|
-
* res.json({ user: req.user });
|
|
214
|
-
* });
|
|
215
|
-
*
|
|
216
|
-
* app.listen(3000);
|
|
217
|
-
* ```
|
|
218
|
-
*/
|
|
219
|
-
function createOxyExpressApp(config = {}) {
|
|
220
|
-
// This is a lightweight helper - users should import express themselves
|
|
221
|
-
// We'll provide the middleware setup instructions instead
|
|
222
|
-
|
|
223
|
-
throw new Error('createOxyExpressApp is not implemented yet. Please use createOxyAuth() middleware with your existing Express app.');
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Re-export for convenience
|
|
227
|
-
//# sourceMappingURL=middleware.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_core","require","_interfaces","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","createOxyAuth","config","baseURL","process","env","OXY_API_URL","loadUser","publicPaths","onError","oxy","OxyServices","req","res","next","isPublicPath","some","path","startsWith","authHeader","headers","token","split","error","message","code","status","json","authResult","authenticateToken","valid","userId","accessToken","user","id","apiError","createOptionalOxyAuth","createOxyExpressApp","Error"],"sourceRoot":"../../../src","sources":["node/middleware.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;AAOA,IAAAA,KAAA,GAAAC,OAAA;AAkOA,IAAAC,WAAA,GAAAD,OAAA;AAAAE,MAAA,CAAAC,IAAA,CAAAF,WAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,WAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,WAAA,CAAAI,GAAA;IAAA;EAAA;AAAA;AAzOA;AACA;AACA;AACA;AACA;AACA;;AAsBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASS,aAAaA,CAACC,MAAqB,GAAG,CAAC,CAAC,EAAE;EACxD,MAAM;IACJC,OAAO,GAAGC,OAAO,CAACC,GAAG,CAACC,WAAW,IAAI,uBAAuB;IAC5DC,QAAQ,GAAG,IAAI;IACfC,WAAW,GAAG,EAAE;IAChBC;EACF,CAAC,GAAGP,MAAM;EAEV,MAAMQ,GAAG,GAAG,IAAIC,iBAAW,CAAC;IAAER;EAAQ,CAAC,CAAC;EAExC,OAAO,OAAOS,GAAQ,EAAEC,GAAQ,EAAEC,IAAS,KAAK;IAC9C;IACA,MAAMC,YAAY,GAAGP,WAAW,CAACQ,IAAI,CAACC,IAAI,IACxCL,GAAG,CAACK,IAAI,KAAKA,IAAI,IAAIL,GAAG,CAACK,IAAI,CAACC,UAAU,CAACD,IAAI,GAAG,GAAG,CACrD,CAAC;IAED,IAAIF,YAAY,EAAE;MAChB,OAAOD,IAAI,CAAC,CAAC;IACf;IAEA,IAAI;MACF,MAAMK,UAAU,GAAGP,GAAG,CAACQ,OAAO,CAAC,eAAe,CAAC;MAC/C,MAAMC,KAAK,GAAGF,UAAU,IAAIA,UAAU,CAACG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;;MAEtD,IAAI,CAACD,KAAK,EAAE;QACV,MAAME,KAAe,GAAG;UACtBC,OAAO,EAAE,uBAAuB;UAChCC,IAAI,EAAE,eAAe;UACrBC,MAAM,EAAE;QACV,CAAC;QAED,IAAIjB,OAAO,EAAE;UACX,OAAOA,OAAO,CAACc,KAAK,EAAEX,GAAG,EAAEC,GAAG,CAAC;QACjC;QAEA,OAAOA,GAAG,CAACa,MAAM,CAAC,GAAG,CAAC,CAACC,IAAI,CAAC;UAC1BJ,KAAK,EAAE,uBAAuB;UAC9BE,IAAI,EAAE;QACR,CAAC,CAAC;MACJ;;MAEA;MACA,MAAMG,UAAU,GAAG,MAAMlB,GAAG,CAACmB,iBAAiB,CAACR,KAAK,CAAC;MAErD,IAAI,CAACO,UAAU,CAACE,KAAK,EAAE;QACrB,MAAMP,KAAe,GAAG;UACtBC,OAAO,EAAEI,UAAU,CAACL,KAAK,IAAI,eAAe;UAC5CE,IAAI,EAAE,eAAe;UACrBC,MAAM,EAAE;QACV,CAAC;QAED,IAAIjB,OAAO,EAAE;UACX,OAAOA,OAAO,CAACc,KAAK,EAAEX,GAAG,EAAEC,GAAG,CAAC;QACjC;QAEA,OAAOA,GAAG,CAACa,MAAM,CAAC,GAAG,CAAC,CAACC,IAAI,CAAC;UAC1BJ,KAAK,EAAEK,UAAU,CAACL,KAAK,IAAI,eAAe;UAC1CE,IAAI,EAAE;QACR,CAAC,CAAC;MACJ;;MAEA;MACAb,GAAG,CAACmB,MAAM,GAAGH,UAAU,CAACG,MAAM;MAC9BnB,GAAG,CAACoB,WAAW,GAAGX,KAAK;MAEvB,IAAId,QAAQ,IAAIqB,UAAU,CAACK,IAAI,EAAE;QAC/BrB,GAAG,CAACqB,IAAI,GAAGL,UAAU,CAACK,IAAI;MAC5B,CAAC,MAAM;QACLrB,GAAG,CAACqB,IAAI,GAAG;UAAEC,EAAE,EAAEN,UAAU,CAACG;QAAO,CAAC;MACtC;MAEAjB,IAAI,CAAC,CAAC;IACR,CAAC,CAAC,OAAOS,KAAU,EAAE;MACnB,MAAMY,QAAkB,GAAG;QACzBX,OAAO,EAAED,KAAK,CAACC,OAAO,IAAI,uBAAuB;QACjDC,IAAI,EAAEF,KAAK,CAACE,IAAI,IAAI,YAAY;QAChCC,MAAM,EAAEH,KAAK,CAACG,MAAM,IAAI;MAC1B,CAAC;MAED,IAAIjB,OAAO,EAAE;QACX,OAAOA,OAAO,CAAC0B,QAAQ,EAAEvB,GAAG,EAAEC,GAAG,CAAC;MACpC;MAEAA,GAAG,CAACa,MAAM,CAACS,QAAQ,CAACT,MAAM,CAAC,CAACC,IAAI,CAAC;QAC/BJ,KAAK,EAAEY,QAAQ,CAACX,OAAO;QACvBC,IAAI,EAAEU,QAAQ,CAACV;MACjB,CAAC,CAAC;IACJ;EACF,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASW,qBAAqBA,CAAClC,MAAqB,GAAG,CAAC,CAAC,EAAE;EAChE,MAAM;IACJC,OAAO,GAAGC,OAAO,CAACC,GAAG,CAACC,WAAW,IAAI,uBAAuB;IAC5DC,QAAQ,GAAG;EACb,CAAC,GAAGL,MAAM;EAEV,MAAMQ,GAAG,GAAG,IAAIC,iBAAW,CAAC;IAAER;EAAQ,CAAC,CAAC;EAExC,OAAO,OAAOS,GAAQ,EAAEC,GAAQ,EAAEC,IAAS,KAAK;IAC9C,IAAI;MACF,MAAMK,UAAU,GAAGP,GAAG,CAACQ,OAAO,CAAC,eAAe,CAAC;MAC/C,MAAMC,KAAK,GAAGF,UAAU,IAAIA,UAAU,CAACG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;;MAEtD,IAAI,CAACD,KAAK,EAAE;QACV;QACA,OAAOP,IAAI,CAAC,CAAC;MACf;;MAEA;MACA,MAAMc,UAAU,GAAG,MAAMlB,GAAG,CAACmB,iBAAiB,CAACR,KAAK,CAAC;MAErD,IAAIO,UAAU,CAACE,KAAK,EAAE;QACpB;QACAlB,GAAG,CAACmB,MAAM,GAAGH,UAAU,CAACG,MAAM;QAC9BnB,GAAG,CAACoB,WAAW,GAAGX,KAAK;QAEvB,IAAId,QAAQ,IAAIqB,UAAU,CAACK,IAAI,EAAE;UAC/BrB,GAAG,CAACqB,IAAI,GAAGL,UAAU,CAACK,IAAI;QAC5B,CAAC,MAAM;UACLrB,GAAG,CAACqB,IAAI,GAAG;YAAEC,EAAE,EAAEN,UAAU,CAACG;UAAO,CAAC;QACtC;MACF;MAEAjB,IAAI,CAAC,CAAC;IACR,CAAC,CAAC,OAAOS,KAAK,EAAE;MACd;MACA;MACAT,IAAI,CAAC,CAAC;IACR;EACF,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASuB,mBAAmBA,CAACnC,MAOnC,GAAG,CAAC,CAAC,EAAE;EACN;EACA;;EAEA,MAAM,IAAIoC,KAAK,CAAC,mHAAmH,CAAC;AACtI;;AAEA","ignoreList":[]}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
Object.defineProperty(exports, "OxyZeroConfigProvider", {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: function () {
|
|
9
|
-
return _provider.OxyZeroConfigProvider;
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
|
-
Object.defineProperty(exports, "useOxyApi", {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function () {
|
|
15
|
-
return _provider.useOxyApi;
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
Object.defineProperty(exports, "useOxyZeroConfig", {
|
|
19
|
-
enumerable: true,
|
|
20
|
-
get: function () {
|
|
21
|
-
return _provider.useOxyZeroConfig;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
var _provider = require("./provider");
|
|
25
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_provider","require"],"sourceRoot":"../../../../src","sources":["ui/zero-config/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAIA,IAAAA,SAAA,GAAAC,OAAA","ignoreList":[]}
|