@oxyhq/services 5.23.0 → 5.25.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/web/WebOxyContext.js +29 -101
- package/lib/commonjs/web/WebOxyContext.js.map +1 -1
- package/lib/module/web/WebOxyContext.js +30 -102
- package/lib/module/web/WebOxyContext.js.map +1 -1
- package/lib/typescript/commonjs/web/WebOxyContext.d.ts +6 -5
- package/lib/typescript/commonjs/web/WebOxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/web/index.d.ts +1 -1
- package/lib/typescript/commonjs/web/index.d.ts.map +1 -1
- package/lib/typescript/module/web/WebOxyContext.d.ts +6 -5
- package/lib/typescript/module/web/WebOxyContext.d.ts.map +1 -1
- package/lib/typescript/module/web/index.d.ts +1 -1
- package/lib/typescript/module/web/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/web/WebOxyContext.tsx +35 -112
- package/src/web/index.ts +1 -1
|
@@ -14,12 +14,13 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
14
14
|
/**
|
|
15
15
|
* Web-Only Oxy Context
|
|
16
16
|
* Clean implementation with ZERO React Native dependencies
|
|
17
|
+
* Uses CrossDomainAuth for proper SSO flow
|
|
17
18
|
*/
|
|
18
19
|
|
|
19
20
|
const WebOxyContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
20
21
|
/**
|
|
21
22
|
* Web-only Oxy Provider
|
|
22
|
-
*
|
|
23
|
+
* Uses CrossDomainAuth for automatic SSO with FedCM/Popup/Redirect fallback
|
|
23
24
|
*/
|
|
24
25
|
function WebOxyProvider({
|
|
25
26
|
children,
|
|
@@ -31,66 +32,26 @@ function WebOxyProvider({
|
|
|
31
32
|
baseURL,
|
|
32
33
|
authWebUrl
|
|
33
34
|
}));
|
|
35
|
+
const [crossDomainAuth] = (0, _react.useState)(() => (0, _index.createCrossDomainAuth)(oxyServices));
|
|
34
36
|
const [user, setUser] = (0, _react.useState)(null);
|
|
35
37
|
const [isLoading, setIsLoading] = (0, _react.useState)(true);
|
|
36
38
|
const [error, setError] = (0, _react.useState)(null);
|
|
37
39
|
const [queryClient] = (0, _react.useState)(() => (0, _queryClient.createQueryClient)());
|
|
38
40
|
const isAuthenticated = !!user;
|
|
39
41
|
|
|
40
|
-
// Initialize -
|
|
42
|
+
// Initialize - handle callbacks, restore session, try silent sign-in
|
|
41
43
|
(0, _react.useEffect)(() => {
|
|
42
44
|
let mounted = true;
|
|
43
45
|
const initAuth = async () => {
|
|
44
46
|
try {
|
|
45
|
-
//
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// Try to get user info from the active session's userId
|
|
51
|
-
if (activeSession && activeSession.userId) {
|
|
52
|
-
try {
|
|
53
|
-
const userProfile = await oxyServices.getProfile(activeSession.userId);
|
|
54
|
-
if (mounted && userProfile) {
|
|
55
|
-
setUser(userProfile);
|
|
56
|
-
setIsLoading(false);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
} catch (err) {
|
|
60
|
-
console.log('[WebOxy] Could not fetch user profile:', err);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// No active session - check for cross-domain SSO via FedCM
|
|
66
|
-
if (typeof window !== 'undefined' && 'IdentityCredential' in window) {
|
|
67
|
-
try {
|
|
68
|
-
const credential = await navigator.credentials.get({
|
|
69
|
-
// @ts-expect-error - FedCM identity property is not in standard types
|
|
70
|
-
identity: {
|
|
71
|
-
providers: [{
|
|
72
|
-
configURL: `${authWebUrl || 'https://auth.oxy.so'}/fedcm.json`,
|
|
73
|
-
clientId: window.location.origin
|
|
74
|
-
}]
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
if (credential && 'token' in credential) {
|
|
78
|
-
// Use the token to authenticate
|
|
79
|
-
const session = await oxyServices.authenticateWithToken(credential.token);
|
|
80
|
-
if (mounted && session.user) {
|
|
81
|
-
setUser(session.user);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
} catch (fedcmError) {
|
|
85
|
-
// FedCM not available or user cancelled - this is fine
|
|
86
|
-
console.log('[WebOxy] FedCM SSO not available:', fedcmError);
|
|
87
|
-
}
|
|
47
|
+
// Complete initialization: handles callbacks, restores session, tries silent sign-in
|
|
48
|
+
const session = await crossDomainAuth.initialize();
|
|
49
|
+
if (mounted && session?.user) {
|
|
50
|
+
setUser(session.user);
|
|
88
51
|
}
|
|
89
52
|
} catch (err) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
setError(err instanceof Error ? err.message : 'Failed to initialize auth');
|
|
93
|
-
}
|
|
53
|
+
// No active session - this is fine
|
|
54
|
+
console.log('[WebOxy] No active session');
|
|
94
55
|
} finally {
|
|
95
56
|
if (mounted) {
|
|
96
57
|
setIsLoading(false);
|
|
@@ -101,7 +62,7 @@ function WebOxyProvider({
|
|
|
101
62
|
return () => {
|
|
102
63
|
mounted = false;
|
|
103
64
|
};
|
|
104
|
-
}, [
|
|
65
|
+
}, [crossDomainAuth]);
|
|
105
66
|
|
|
106
67
|
// Notify parent of auth state changes
|
|
107
68
|
(0, _react.useEffect)(() => {
|
|
@@ -111,71 +72,38 @@ function WebOxyProvider({
|
|
|
111
72
|
setError(null);
|
|
112
73
|
setIsLoading(true);
|
|
113
74
|
try {
|
|
114
|
-
//
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
// Listen for message from popup
|
|
121
|
-
const handleMessage = async event => {
|
|
122
|
-
if (event.origin !== (authWebUrl || 'https://auth.oxy.so')) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if (event.data.type === 'oxy-auth-success') {
|
|
126
|
-
const {
|
|
127
|
-
sessionId,
|
|
128
|
-
accessToken,
|
|
129
|
-
user: authUser
|
|
130
|
-
} = event.data;
|
|
131
|
-
|
|
132
|
-
// Store session (note: user property doesn't exist in ClientSession type)
|
|
133
|
-
const session = {
|
|
134
|
-
sessionId,
|
|
135
|
-
deviceId: event.data.deviceId || '',
|
|
136
|
-
expiresAt: event.data.expiresAt || '',
|
|
137
|
-
lastActive: new Date().toISOString(),
|
|
138
|
-
userId: authUser.id,
|
|
139
|
-
isCurrent: true
|
|
140
|
-
};
|
|
141
|
-
await oxyServices.storeSession(session);
|
|
142
|
-
setUser(authUser);
|
|
143
|
-
setIsLoading(false);
|
|
144
|
-
window.removeEventListener('message', handleMessage);
|
|
145
|
-
popup.close();
|
|
146
|
-
} else if (event.data.type === 'oxy-auth-error') {
|
|
147
|
-
setError(event.data.error || 'Authentication failed');
|
|
148
|
-
setIsLoading(false);
|
|
149
|
-
window.removeEventListener('message', handleMessage);
|
|
150
|
-
popup.close();
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
window.addEventListener('message', handleMessage);
|
|
154
|
-
|
|
155
|
-
// Check if popup was closed
|
|
156
|
-
const checkClosed = setInterval(() => {
|
|
157
|
-
if (popup.closed) {
|
|
158
|
-
clearInterval(checkClosed);
|
|
159
|
-
window.removeEventListener('message', handleMessage);
|
|
160
|
-
setIsLoading(false);
|
|
75
|
+
// Sign in with automatic method selection (FedCM → Popup → Redirect)
|
|
76
|
+
const session = await crossDomainAuth.signIn({
|
|
77
|
+
method: 'auto',
|
|
78
|
+
// Automatic fallback
|
|
79
|
+
onMethodSelected: method => {
|
|
80
|
+
console.log('[WebOxy] Using auth method:', method);
|
|
161
81
|
}
|
|
162
|
-
}
|
|
82
|
+
});
|
|
83
|
+
if (session?.user) {
|
|
84
|
+
setUser(session.user);
|
|
85
|
+
}
|
|
163
86
|
} catch (err) {
|
|
164
87
|
console.error('[WebOxy] Sign in error:', err);
|
|
165
88
|
setError(err instanceof Error ? err.message : 'Sign in failed');
|
|
89
|
+
} finally {
|
|
166
90
|
setIsLoading(false);
|
|
167
91
|
}
|
|
168
|
-
}, [
|
|
92
|
+
}, [crossDomainAuth]);
|
|
169
93
|
const signOut = (0, _react.useCallback)(async () => {
|
|
170
94
|
setError(null);
|
|
171
95
|
try {
|
|
172
|
-
|
|
96
|
+
// Clear stored session
|
|
97
|
+
if (typeof window !== 'undefined') {
|
|
98
|
+
localStorage.removeItem('oxy-session');
|
|
99
|
+
localStorage.removeItem('oxy-access-token');
|
|
100
|
+
}
|
|
173
101
|
setUser(null);
|
|
174
102
|
} catch (err) {
|
|
175
103
|
console.error('[WebOxy] Sign out error:', err);
|
|
176
104
|
setError(err instanceof Error ? err.message : 'Sign out failed');
|
|
177
105
|
}
|
|
178
|
-
}, [
|
|
106
|
+
}, []);
|
|
179
107
|
const contextValue = {
|
|
180
108
|
user,
|
|
181
109
|
isAuthenticated,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_index","_reactQuery","_queryClient","_jsxRuntime","WebOxyContext","createContext","WebOxyProvider","children","baseURL","authWebUrl","onAuthStateChange","oxyServices","useState","OxyServices","user","setUser","isLoading","setIsLoading","error","setError","queryClient","createQueryClient","isAuthenticated","useEffect","mounted","initAuth","
|
|
1
|
+
{"version":3,"names":["_react","require","_index","_reactQuery","_queryClient","_jsxRuntime","WebOxyContext","createContext","WebOxyProvider","children","baseURL","authWebUrl","onAuthStateChange","oxyServices","useState","OxyServices","crossDomainAuth","createCrossDomainAuth","user","setUser","isLoading","setIsLoading","error","setError","queryClient","createQueryClient","isAuthenticated","useEffect","mounted","initAuth","session","initialize","err","console","log","signIn","useCallback","method","onMethodSelected","Error","message","signOut","window","localStorage","removeItem","contextValue","jsx","QueryClientProvider","client","Provider","value","useWebOxy","context","useContext","useAuth","isReady"],"sourceRoot":"../../../src","sources":["web/WebOxyContext.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -3,17 +3,18 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* Web-Only Oxy Context
|
|
5
5
|
* Clean implementation with ZERO React Native dependencies
|
|
6
|
+
* Uses CrossDomainAuth for proper SSO flow
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
|
9
|
-
import { OxyServices } from "../core/index.js";
|
|
10
|
+
import { OxyServices, createCrossDomainAuth } from "../core/index.js";
|
|
10
11
|
import { QueryClientProvider } from '@tanstack/react-query';
|
|
11
12
|
import { createQueryClient } from "../ui/hooks/queryClient.js";
|
|
12
13
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
14
|
const WebOxyContext = /*#__PURE__*/createContext(null);
|
|
14
15
|
/**
|
|
15
16
|
* Web-only Oxy Provider
|
|
16
|
-
*
|
|
17
|
+
* Uses CrossDomainAuth for automatic SSO with FedCM/Popup/Redirect fallback
|
|
17
18
|
*/
|
|
18
19
|
export function WebOxyProvider({
|
|
19
20
|
children,
|
|
@@ -25,66 +26,26 @@ export function WebOxyProvider({
|
|
|
25
26
|
baseURL,
|
|
26
27
|
authWebUrl
|
|
27
28
|
}));
|
|
29
|
+
const [crossDomainAuth] = useState(() => createCrossDomainAuth(oxyServices));
|
|
28
30
|
const [user, setUser] = useState(null);
|
|
29
31
|
const [isLoading, setIsLoading] = useState(true);
|
|
30
32
|
const [error, setError] = useState(null);
|
|
31
33
|
const [queryClient] = useState(() => createQueryClient());
|
|
32
34
|
const isAuthenticated = !!user;
|
|
33
35
|
|
|
34
|
-
// Initialize -
|
|
36
|
+
// Initialize - handle callbacks, restore session, try silent sign-in
|
|
35
37
|
useEffect(() => {
|
|
36
38
|
let mounted = true;
|
|
37
39
|
const initAuth = async () => {
|
|
38
40
|
try {
|
|
39
|
-
//
|
|
40
|
-
const
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// Try to get user info from the active session's userId
|
|
45
|
-
if (activeSession && activeSession.userId) {
|
|
46
|
-
try {
|
|
47
|
-
const userProfile = await oxyServices.getProfile(activeSession.userId);
|
|
48
|
-
if (mounted && userProfile) {
|
|
49
|
-
setUser(userProfile);
|
|
50
|
-
setIsLoading(false);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
} catch (err) {
|
|
54
|
-
console.log('[WebOxy] Could not fetch user profile:', err);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// No active session - check for cross-domain SSO via FedCM
|
|
60
|
-
if (typeof window !== 'undefined' && 'IdentityCredential' in window) {
|
|
61
|
-
try {
|
|
62
|
-
const credential = await navigator.credentials.get({
|
|
63
|
-
// @ts-expect-error - FedCM identity property is not in standard types
|
|
64
|
-
identity: {
|
|
65
|
-
providers: [{
|
|
66
|
-
configURL: `${authWebUrl || 'https://auth.oxy.so'}/fedcm.json`,
|
|
67
|
-
clientId: window.location.origin
|
|
68
|
-
}]
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
if (credential && 'token' in credential) {
|
|
72
|
-
// Use the token to authenticate
|
|
73
|
-
const session = await oxyServices.authenticateWithToken(credential.token);
|
|
74
|
-
if (mounted && session.user) {
|
|
75
|
-
setUser(session.user);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
} catch (fedcmError) {
|
|
79
|
-
// FedCM not available or user cancelled - this is fine
|
|
80
|
-
console.log('[WebOxy] FedCM SSO not available:', fedcmError);
|
|
81
|
-
}
|
|
41
|
+
// Complete initialization: handles callbacks, restores session, tries silent sign-in
|
|
42
|
+
const session = await crossDomainAuth.initialize();
|
|
43
|
+
if (mounted && session?.user) {
|
|
44
|
+
setUser(session.user);
|
|
82
45
|
}
|
|
83
46
|
} catch (err) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
setError(err instanceof Error ? err.message : 'Failed to initialize auth');
|
|
87
|
-
}
|
|
47
|
+
// No active session - this is fine
|
|
48
|
+
console.log('[WebOxy] No active session');
|
|
88
49
|
} finally {
|
|
89
50
|
if (mounted) {
|
|
90
51
|
setIsLoading(false);
|
|
@@ -95,7 +56,7 @@ export function WebOxyProvider({
|
|
|
95
56
|
return () => {
|
|
96
57
|
mounted = false;
|
|
97
58
|
};
|
|
98
|
-
}, [
|
|
59
|
+
}, [crossDomainAuth]);
|
|
99
60
|
|
|
100
61
|
// Notify parent of auth state changes
|
|
101
62
|
useEffect(() => {
|
|
@@ -105,71 +66,38 @@ export function WebOxyProvider({
|
|
|
105
66
|
setError(null);
|
|
106
67
|
setIsLoading(true);
|
|
107
68
|
try {
|
|
108
|
-
//
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// Listen for message from popup
|
|
115
|
-
const handleMessage = async event => {
|
|
116
|
-
if (event.origin !== (authWebUrl || 'https://auth.oxy.so')) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
if (event.data.type === 'oxy-auth-success') {
|
|
120
|
-
const {
|
|
121
|
-
sessionId,
|
|
122
|
-
accessToken,
|
|
123
|
-
user: authUser
|
|
124
|
-
} = event.data;
|
|
125
|
-
|
|
126
|
-
// Store session (note: user property doesn't exist in ClientSession type)
|
|
127
|
-
const session = {
|
|
128
|
-
sessionId,
|
|
129
|
-
deviceId: event.data.deviceId || '',
|
|
130
|
-
expiresAt: event.data.expiresAt || '',
|
|
131
|
-
lastActive: new Date().toISOString(),
|
|
132
|
-
userId: authUser.id,
|
|
133
|
-
isCurrent: true
|
|
134
|
-
};
|
|
135
|
-
await oxyServices.storeSession(session);
|
|
136
|
-
setUser(authUser);
|
|
137
|
-
setIsLoading(false);
|
|
138
|
-
window.removeEventListener('message', handleMessage);
|
|
139
|
-
popup.close();
|
|
140
|
-
} else if (event.data.type === 'oxy-auth-error') {
|
|
141
|
-
setError(event.data.error || 'Authentication failed');
|
|
142
|
-
setIsLoading(false);
|
|
143
|
-
window.removeEventListener('message', handleMessage);
|
|
144
|
-
popup.close();
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
window.addEventListener('message', handleMessage);
|
|
148
|
-
|
|
149
|
-
// Check if popup was closed
|
|
150
|
-
const checkClosed = setInterval(() => {
|
|
151
|
-
if (popup.closed) {
|
|
152
|
-
clearInterval(checkClosed);
|
|
153
|
-
window.removeEventListener('message', handleMessage);
|
|
154
|
-
setIsLoading(false);
|
|
69
|
+
// Sign in with automatic method selection (FedCM → Popup → Redirect)
|
|
70
|
+
const session = await crossDomainAuth.signIn({
|
|
71
|
+
method: 'auto',
|
|
72
|
+
// Automatic fallback
|
|
73
|
+
onMethodSelected: method => {
|
|
74
|
+
console.log('[WebOxy] Using auth method:', method);
|
|
155
75
|
}
|
|
156
|
-
}
|
|
76
|
+
});
|
|
77
|
+
if (session?.user) {
|
|
78
|
+
setUser(session.user);
|
|
79
|
+
}
|
|
157
80
|
} catch (err) {
|
|
158
81
|
console.error('[WebOxy] Sign in error:', err);
|
|
159
82
|
setError(err instanceof Error ? err.message : 'Sign in failed');
|
|
83
|
+
} finally {
|
|
160
84
|
setIsLoading(false);
|
|
161
85
|
}
|
|
162
|
-
}, [
|
|
86
|
+
}, [crossDomainAuth]);
|
|
163
87
|
const signOut = useCallback(async () => {
|
|
164
88
|
setError(null);
|
|
165
89
|
try {
|
|
166
|
-
|
|
90
|
+
// Clear stored session
|
|
91
|
+
if (typeof window !== 'undefined') {
|
|
92
|
+
localStorage.removeItem('oxy-session');
|
|
93
|
+
localStorage.removeItem('oxy-access-token');
|
|
94
|
+
}
|
|
167
95
|
setUser(null);
|
|
168
96
|
} catch (err) {
|
|
169
97
|
console.error('[WebOxy] Sign out error:', err);
|
|
170
98
|
setError(err instanceof Error ? err.message : 'Sign out failed');
|
|
171
99
|
}
|
|
172
|
-
}, [
|
|
100
|
+
}, []);
|
|
173
101
|
const contextValue = {
|
|
174
102
|
user,
|
|
175
103
|
isAuthenticated,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["createContext","useCallback","useContext","useEffect","useState","OxyServices","QueryClientProvider","createQueryClient","jsx","_jsx","WebOxyContext","WebOxyProvider","children","baseURL","authWebUrl","onAuthStateChange","oxyServices","user","setUser","isLoading","setIsLoading","error","setError","queryClient","isAuthenticated","mounted","initAuth","
|
|
1
|
+
{"version":3,"names":["createContext","useCallback","useContext","useEffect","useState","OxyServices","createCrossDomainAuth","QueryClientProvider","createQueryClient","jsx","_jsx","WebOxyContext","WebOxyProvider","children","baseURL","authWebUrl","onAuthStateChange","oxyServices","crossDomainAuth","user","setUser","isLoading","setIsLoading","error","setError","queryClient","isAuthenticated","mounted","initAuth","session","initialize","err","console","log","signIn","method","onMethodSelected","Error","message","signOut","window","localStorage","removeItem","contextValue","client","Provider","value","useWebOxy","context","useAuth","isReady"],"sourceRoot":"../../../src","sources":["web/WebOxyContext.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Web-Only Oxy Context
|
|
3
3
|
* Clean implementation with ZERO React Native dependencies
|
|
4
|
+
* Uses CrossDomainAuth for proper SSO flow
|
|
4
5
|
*/
|
|
5
6
|
import { type ReactNode } from 'react';
|
|
6
7
|
import { OxyServices } from '../core';
|
|
7
|
-
import type {
|
|
8
|
+
import type { MinimalUserData } from '../models/session';
|
|
8
9
|
export interface WebAuthState {
|
|
9
|
-
user:
|
|
10
|
+
user: MinimalUserData | null;
|
|
10
11
|
isAuthenticated: boolean;
|
|
11
12
|
isLoading: boolean;
|
|
12
13
|
error: string | null;
|
|
@@ -22,16 +23,16 @@ export interface WebOxyProviderProps {
|
|
|
22
23
|
children: ReactNode;
|
|
23
24
|
baseURL: string;
|
|
24
25
|
authWebUrl?: string;
|
|
25
|
-
onAuthStateChange?: (user:
|
|
26
|
+
onAuthStateChange?: (user: MinimalUserData | null) => void;
|
|
26
27
|
}
|
|
27
28
|
/**
|
|
28
29
|
* Web-only Oxy Provider
|
|
29
|
-
*
|
|
30
|
+
* Uses CrossDomainAuth for automatic SSO with FedCM/Popup/Redirect fallback
|
|
30
31
|
*/
|
|
31
32
|
export declare function WebOxyProvider({ children, baseURL, authWebUrl, onAuthStateChange, }: WebOxyProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
32
33
|
export declare function useWebOxy(): WebOxyContextValue;
|
|
33
34
|
export declare function useAuth(): {
|
|
34
|
-
user:
|
|
35
|
+
user: MinimalUserData | null;
|
|
35
36
|
isAuthenticated: boolean;
|
|
36
37
|
isLoading: boolean;
|
|
37
38
|
isReady: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebOxyContext.d.ts","sourceRoot":"","sources":["../../../../src/web/WebOxyContext.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"WebOxyContext.d.ts","sourceRoot":"","sources":["../../../../src/web/WebOxyContext.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,WAAW,EAAyB,MAAM,SAAS,CAAC;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIzD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAmB,SAAQ,YAAY,EAAE,cAAc;IACtE,WAAW,EAAE,WAAW,CAAC;CAC1B;AAID,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;CAC5D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,OAAO,EACP,UAAU,EACV,iBAAiB,GAClB,EAAE,mBAAmB,2CAsGrB;AAED,wBAAgB,SAAS,uBAMxB;AAED,wBAAgB,OAAO;;;;;;kBA1IP,OAAO,CAAC,IAAI,CAAC;mBACZ,OAAO,CAAC,IAAI,CAAC;;EAsJ7B"}
|
|
@@ -34,7 +34,7 @@ export type { CrossDomainAuthOptions, DeviceFingerprint, StoredDeviceInfo, } fro
|
|
|
34
34
|
export { WebOxyProvider, useWebOxy, useAuth } from './WebOxyContext';
|
|
35
35
|
export type { WebOxyProviderProps, WebAuthState, WebAuthActions, WebOxyContextValue } from './WebOxyContext';
|
|
36
36
|
export type { User, ApiError, Notification, FileMetadata, AssetUploadProgress, PaymentMethod, KarmaLeaderboardEntry, KarmaRule, Transaction, DeviceSession, } from '../models/interfaces';
|
|
37
|
-
export type { ClientSession } from '../models/session';
|
|
37
|
+
export type { ClientSession, MinimalUserData } from '../models/session';
|
|
38
38
|
export { SUPPORTED_LANGUAGES, getLanguageMetadata, getLanguageName, getNativeLanguageName, normalizeLanguageCode, } from '../utils/languageUtils';
|
|
39
39
|
export type { LanguageMetadata } from '../utils/languageUtils';
|
|
40
40
|
import { WebOxyProvider } from './WebOxyContext';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/web/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,6BAA6B,EAC7B,aAAa,EACb,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,aAAa,GACd,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACrE,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAI7G,YAAY,EACV,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,SAAS,EACT,WAAW,EACX,aAAa,GACd,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/web/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,6BAA6B,EAC7B,aAAa,EACb,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,aAAa,GACd,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACrE,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAI7G,YAAY,EACV,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,SAAS,EACT,WAAW,EACX,aAAa,GACd,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGxE,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,eAAe,cAAc,CAAC"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Web-Only Oxy Context
|
|
3
3
|
* Clean implementation with ZERO React Native dependencies
|
|
4
|
+
* Uses CrossDomainAuth for proper SSO flow
|
|
4
5
|
*/
|
|
5
6
|
import { type ReactNode } from 'react';
|
|
6
7
|
import { OxyServices } from '../core';
|
|
7
|
-
import type {
|
|
8
|
+
import type { MinimalUserData } from '../models/session';
|
|
8
9
|
export interface WebAuthState {
|
|
9
|
-
user:
|
|
10
|
+
user: MinimalUserData | null;
|
|
10
11
|
isAuthenticated: boolean;
|
|
11
12
|
isLoading: boolean;
|
|
12
13
|
error: string | null;
|
|
@@ -22,16 +23,16 @@ export interface WebOxyProviderProps {
|
|
|
22
23
|
children: ReactNode;
|
|
23
24
|
baseURL: string;
|
|
24
25
|
authWebUrl?: string;
|
|
25
|
-
onAuthStateChange?: (user:
|
|
26
|
+
onAuthStateChange?: (user: MinimalUserData | null) => void;
|
|
26
27
|
}
|
|
27
28
|
/**
|
|
28
29
|
* Web-only Oxy Provider
|
|
29
|
-
*
|
|
30
|
+
* Uses CrossDomainAuth for automatic SSO with FedCM/Popup/Redirect fallback
|
|
30
31
|
*/
|
|
31
32
|
export declare function WebOxyProvider({ children, baseURL, authWebUrl, onAuthStateChange, }: WebOxyProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
32
33
|
export declare function useWebOxy(): WebOxyContextValue;
|
|
33
34
|
export declare function useAuth(): {
|
|
34
|
-
user:
|
|
35
|
+
user: MinimalUserData | null;
|
|
35
36
|
isAuthenticated: boolean;
|
|
36
37
|
isLoading: boolean;
|
|
37
38
|
isReady: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebOxyContext.d.ts","sourceRoot":"","sources":["../../../../src/web/WebOxyContext.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"WebOxyContext.d.ts","sourceRoot":"","sources":["../../../../src/web/WebOxyContext.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,WAAW,EAAyB,MAAM,SAAS,CAAC;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIzD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAmB,SAAQ,YAAY,EAAE,cAAc;IACtE,WAAW,EAAE,WAAW,CAAC;CAC1B;AAID,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;CAC5D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,OAAO,EACP,UAAU,EACV,iBAAiB,GAClB,EAAE,mBAAmB,2CAsGrB;AAED,wBAAgB,SAAS,uBAMxB;AAED,wBAAgB,OAAO;;;;;;kBA1IP,OAAO,CAAC,IAAI,CAAC;mBACZ,OAAO,CAAC,IAAI,CAAC;;EAsJ7B"}
|
|
@@ -34,7 +34,7 @@ export type { CrossDomainAuthOptions, DeviceFingerprint, StoredDeviceInfo, } fro
|
|
|
34
34
|
export { WebOxyProvider, useWebOxy, useAuth } from './WebOxyContext';
|
|
35
35
|
export type { WebOxyProviderProps, WebAuthState, WebAuthActions, WebOxyContextValue } from './WebOxyContext';
|
|
36
36
|
export type { User, ApiError, Notification, FileMetadata, AssetUploadProgress, PaymentMethod, KarmaLeaderboardEntry, KarmaRule, Transaction, DeviceSession, } from '../models/interfaces';
|
|
37
|
-
export type { ClientSession } from '../models/session';
|
|
37
|
+
export type { ClientSession, MinimalUserData } from '../models/session';
|
|
38
38
|
export { SUPPORTED_LANGUAGES, getLanguageMetadata, getLanguageName, getNativeLanguageName, normalizeLanguageCode, } from '../utils/languageUtils';
|
|
39
39
|
export type { LanguageMetadata } from '../utils/languageUtils';
|
|
40
40
|
import { WebOxyProvider } from './WebOxyContext';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/web/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,6BAA6B,EAC7B,aAAa,EACb,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,aAAa,GACd,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACrE,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAI7G,YAAY,EACV,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,SAAS,EACT,WAAW,EACX,aAAa,GACd,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/web/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,6BAA6B,EAC7B,aAAa,EACb,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,aAAa,GACd,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACrE,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAI7G,YAAY,EACV,IAAI,EACJ,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,qBAAqB,EACrB,SAAS,EACT,WAAW,EACX,aAAa,GACd,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGxE,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,eAAe,cAAc,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxyhq/services",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.25.0",
|
|
4
4
|
"description": "Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Web-Only Oxy Context
|
|
3
3
|
* Clean implementation with ZERO React Native dependencies
|
|
4
|
+
* Uses CrossDomainAuth for proper SSO flow
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
import {
|
|
@@ -11,14 +12,14 @@ import {
|
|
|
11
12
|
useState,
|
|
12
13
|
type ReactNode,
|
|
13
14
|
} from 'react';
|
|
14
|
-
import { OxyServices } from '../core';
|
|
15
|
+
import { OxyServices, createCrossDomainAuth } from '../core';
|
|
15
16
|
import type { User } from '../models/interfaces';
|
|
16
|
-
import type {
|
|
17
|
+
import type { MinimalUserData } from '../models/session';
|
|
17
18
|
import { QueryClientProvider } from '@tanstack/react-query';
|
|
18
19
|
import { createQueryClient } from '../ui/hooks/queryClient';
|
|
19
20
|
|
|
20
21
|
export interface WebAuthState {
|
|
21
|
-
user:
|
|
22
|
+
user: MinimalUserData | null;
|
|
22
23
|
isAuthenticated: boolean;
|
|
23
24
|
isLoading: boolean;
|
|
24
25
|
error: string | null;
|
|
@@ -39,12 +40,12 @@ export interface WebOxyProviderProps {
|
|
|
39
40
|
children: ReactNode;
|
|
40
41
|
baseURL: string;
|
|
41
42
|
authWebUrl?: string;
|
|
42
|
-
onAuthStateChange?: (user:
|
|
43
|
+
onAuthStateChange?: (user: MinimalUserData | null) => void;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
47
|
* Web-only Oxy Provider
|
|
47
|
-
*
|
|
48
|
+
* Uses CrossDomainAuth for automatic SSO with FedCM/Popup/Redirect fallback
|
|
48
49
|
*/
|
|
49
50
|
export function WebOxyProvider({
|
|
50
51
|
children,
|
|
@@ -53,70 +54,29 @@ export function WebOxyProvider({
|
|
|
53
54
|
onAuthStateChange,
|
|
54
55
|
}: WebOxyProviderProps) {
|
|
55
56
|
const [oxyServices] = useState(() => new OxyServices({ baseURL, authWebUrl }));
|
|
56
|
-
const [
|
|
57
|
+
const [crossDomainAuth] = useState(() => createCrossDomainAuth(oxyServices));
|
|
58
|
+
const [user, setUser] = useState<MinimalUserData | null>(null);
|
|
57
59
|
const [isLoading, setIsLoading] = useState(true);
|
|
58
60
|
const [error, setError] = useState<string | null>(null);
|
|
59
61
|
const [queryClient] = useState(() => createQueryClient());
|
|
60
62
|
|
|
61
63
|
const isAuthenticated = !!user;
|
|
62
64
|
|
|
63
|
-
// Initialize -
|
|
65
|
+
// Initialize - handle callbacks, restore session, try silent sign-in
|
|
64
66
|
useEffect(() => {
|
|
65
67
|
let mounted = true;
|
|
66
68
|
|
|
67
69
|
const initAuth = async () => {
|
|
68
70
|
try {
|
|
69
|
-
//
|
|
70
|
-
const
|
|
71
|
+
// Complete initialization: handles callbacks, restores session, tries silent sign-in
|
|
72
|
+
const session = await crossDomainAuth.initialize();
|
|
71
73
|
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// Try to get user info from the active session's userId
|
|
76
|
-
if (activeSession && activeSession.userId) {
|
|
77
|
-
try {
|
|
78
|
-
const userProfile = await oxyServices.getProfile(activeSession.userId);
|
|
79
|
-
if (mounted && userProfile) {
|
|
80
|
-
setUser(userProfile as User);
|
|
81
|
-
setIsLoading(false);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
} catch (err) {
|
|
85
|
-
console.log('[WebOxy] Could not fetch user profile:', err);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// No active session - check for cross-domain SSO via FedCM
|
|
91
|
-
if (typeof window !== 'undefined' && 'IdentityCredential' in window) {
|
|
92
|
-
try {
|
|
93
|
-
const credential = await navigator.credentials.get({
|
|
94
|
-
// @ts-expect-error - FedCM identity property is not in standard types
|
|
95
|
-
identity: {
|
|
96
|
-
providers: [{
|
|
97
|
-
configURL: `${authWebUrl || 'https://auth.oxy.so'}/fedcm.json`,
|
|
98
|
-
clientId: window.location.origin,
|
|
99
|
-
}]
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
if (credential && 'token' in credential) {
|
|
104
|
-
// Use the token to authenticate
|
|
105
|
-
const session = await oxyServices.authenticateWithToken(credential.token);
|
|
106
|
-
if (mounted && session.user) {
|
|
107
|
-
setUser(session.user);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
} catch (fedcmError) {
|
|
111
|
-
// FedCM not available or user cancelled - this is fine
|
|
112
|
-
console.log('[WebOxy] FedCM SSO not available:', fedcmError);
|
|
113
|
-
}
|
|
74
|
+
if (mounted && session?.user) {
|
|
75
|
+
setUser(session.user);
|
|
114
76
|
}
|
|
115
77
|
} catch (err) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
setError(err instanceof Error ? err.message : 'Failed to initialize auth');
|
|
119
|
-
}
|
|
78
|
+
// No active session - this is fine
|
|
79
|
+
console.log('[WebOxy] No active session');
|
|
120
80
|
} finally {
|
|
121
81
|
if (mounted) {
|
|
122
82
|
setIsLoading(false);
|
|
@@ -129,7 +89,7 @@ export function WebOxyProvider({
|
|
|
129
89
|
return () => {
|
|
130
90
|
mounted = false;
|
|
131
91
|
};
|
|
132
|
-
}, [
|
|
92
|
+
}, [crossDomainAuth]);
|
|
133
93
|
|
|
134
94
|
// Notify parent of auth state changes
|
|
135
95
|
useEffect(() => {
|
|
@@ -141,78 +101,41 @@ export function WebOxyProvider({
|
|
|
141
101
|
setIsLoading(true);
|
|
142
102
|
|
|
143
103
|
try {
|
|
144
|
-
//
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
104
|
+
// Sign in with automatic method selection (FedCM → Popup → Redirect)
|
|
105
|
+
const session = await crossDomainAuth.signIn({
|
|
106
|
+
method: 'auto', // Automatic fallback
|
|
107
|
+
onMethodSelected: (method) => {
|
|
108
|
+
console.log('[WebOxy] Using auth method:', method);
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (session?.user) {
|
|
113
|
+
setUser(session.user);
|
|
153
114
|
}
|
|
154
|
-
|
|
155
|
-
// Listen for message from popup
|
|
156
|
-
const handleMessage = async (event: MessageEvent) => {
|
|
157
|
-
if (event.origin !== (authWebUrl || 'https://auth.oxy.so')) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (event.data.type === 'oxy-auth-success') {
|
|
162
|
-
const { sessionId, accessToken, user: authUser } = event.data;
|
|
163
|
-
|
|
164
|
-
// Store session (note: user property doesn't exist in ClientSession type)
|
|
165
|
-
const session: ClientSession = {
|
|
166
|
-
sessionId,
|
|
167
|
-
deviceId: event.data.deviceId || '',
|
|
168
|
-
expiresAt: event.data.expiresAt || '',
|
|
169
|
-
lastActive: new Date().toISOString(),
|
|
170
|
-
userId: authUser.id,
|
|
171
|
-
isCurrent: true,
|
|
172
|
-
};
|
|
173
|
-
await oxyServices.storeSession(session);
|
|
174
|
-
|
|
175
|
-
setUser(authUser);
|
|
176
|
-
setIsLoading(false);
|
|
177
|
-
|
|
178
|
-
window.removeEventListener('message', handleMessage);
|
|
179
|
-
popup.close();
|
|
180
|
-
} else if (event.data.type === 'oxy-auth-error') {
|
|
181
|
-
setError(event.data.error || 'Authentication failed');
|
|
182
|
-
setIsLoading(false);
|
|
183
|
-
window.removeEventListener('message', handleMessage);
|
|
184
|
-
popup.close();
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
window.addEventListener('message', handleMessage);
|
|
189
|
-
|
|
190
|
-
// Check if popup was closed
|
|
191
|
-
const checkClosed = setInterval(() => {
|
|
192
|
-
if (popup.closed) {
|
|
193
|
-
clearInterval(checkClosed);
|
|
194
|
-
window.removeEventListener('message', handleMessage);
|
|
195
|
-
setIsLoading(false);
|
|
196
|
-
}
|
|
197
|
-
}, 500);
|
|
198
115
|
} catch (err) {
|
|
199
116
|
console.error('[WebOxy] Sign in error:', err);
|
|
200
117
|
setError(err instanceof Error ? err.message : 'Sign in failed');
|
|
118
|
+
} finally {
|
|
201
119
|
setIsLoading(false);
|
|
202
120
|
}
|
|
203
|
-
}, [
|
|
121
|
+
}, [crossDomainAuth]);
|
|
204
122
|
|
|
205
123
|
const signOut = useCallback(async () => {
|
|
206
124
|
setError(null);
|
|
207
125
|
|
|
208
126
|
try {
|
|
209
|
-
|
|
127
|
+
// Clear stored session
|
|
128
|
+
if (typeof window !== 'undefined') {
|
|
129
|
+
localStorage.removeItem('oxy-session');
|
|
130
|
+
localStorage.removeItem('oxy-access-token');
|
|
131
|
+
}
|
|
132
|
+
|
|
210
133
|
setUser(null);
|
|
211
134
|
} catch (err) {
|
|
212
135
|
console.error('[WebOxy] Sign out error:', err);
|
|
213
136
|
setError(err instanceof Error ? err.message : 'Sign out failed');
|
|
214
137
|
}
|
|
215
|
-
}, [
|
|
138
|
+
}, []);
|
|
216
139
|
|
|
217
140
|
const contextValue: WebOxyContextValue = {
|
|
218
141
|
user,
|
package/src/web/index.ts
CHANGED
|
@@ -69,7 +69,7 @@ export type {
|
|
|
69
69
|
} from '../models/interfaces';
|
|
70
70
|
|
|
71
71
|
// Re-export session types
|
|
72
|
-
export type { ClientSession } from '../models/session';
|
|
72
|
+
export type { ClientSession, MinimalUserData } from '../models/session';
|
|
73
73
|
|
|
74
74
|
// ==================== Utilities ====================
|
|
75
75
|
export {
|