@spidy092/auth-client 1.0.11 → 1.0.13
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/core.js +111 -52
- package/index.js +5 -2
- package/package.json +1 -1
- package/token.js +70 -0
package/core.js
CHANGED
|
@@ -2,56 +2,9 @@
|
|
|
2
2
|
import { setToken, clearToken, getToken } from './token';
|
|
3
3
|
import { getConfig, isRouterMode } from './config';
|
|
4
4
|
|
|
5
|
-
// ✅ Track
|
|
5
|
+
// ✅ Track callback state with listeners
|
|
6
6
|
let callbackProcessed = false;
|
|
7
7
|
|
|
8
|
-
export function handleCallback() {
|
|
9
|
-
const params = new URLSearchParams(window.location.search);
|
|
10
|
-
const accessToken = params.get('access_token');
|
|
11
|
-
const error = params.get('error');
|
|
12
|
-
|
|
13
|
-
console.log('🔄 Handling authentication callback:', {
|
|
14
|
-
mode: isRouterMode() ? 'ROUTER' : 'CLIENT',
|
|
15
|
-
hasAccessToken: !!accessToken,
|
|
16
|
-
error,
|
|
17
|
-
alreadyProcessed: callbackProcessed // ✅ Log if already processed
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// ✅ If already processed and we have a token, return it
|
|
21
|
-
if (callbackProcessed) {
|
|
22
|
-
const existingToken = getToken();
|
|
23
|
-
if (existingToken) {
|
|
24
|
-
console.log('🔄 Callback already processed, returning existing token');
|
|
25
|
-
return existingToken;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// ✅ Mark as processed first
|
|
30
|
-
callbackProcessed = true;
|
|
31
|
-
|
|
32
|
-
// Clean up session storage (only once)
|
|
33
|
-
sessionStorage.removeItem('originalApp');
|
|
34
|
-
sessionStorage.removeItem('returnUrl');
|
|
35
|
-
|
|
36
|
-
if (error) {
|
|
37
|
-
throw new Error(`Authentication failed: ${error}`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (accessToken) {
|
|
41
|
-
setToken(accessToken);
|
|
42
|
-
console.log('✅ Token set successfully');
|
|
43
|
-
return accessToken;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
throw new Error('No access token found in callback URL');
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// ✅ Reset callback state when needed
|
|
50
|
-
export function resetCallbackState() {
|
|
51
|
-
callbackProcessed = false;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Your other functions remain the same...
|
|
55
8
|
export function login(clientKeyArg, redirectUriArg) {
|
|
56
9
|
// ✅ Reset callback state when starting new login
|
|
57
10
|
resetCallbackState();
|
|
@@ -80,10 +33,12 @@ export function login(clientKeyArg, redirectUriArg) {
|
|
|
80
33
|
sessionStorage.setItem('originalApp', clientKey);
|
|
81
34
|
sessionStorage.setItem('returnUrl', redirectUri);
|
|
82
35
|
|
|
83
|
-
// Smart Router Logic
|
|
36
|
+
// ✅ Smart Router Logic
|
|
84
37
|
if (isRouterMode()) {
|
|
38
|
+
// Router mode: Direct backend authentication
|
|
85
39
|
return routerLogin(clientKey, redirectUri);
|
|
86
40
|
} else {
|
|
41
|
+
// Client mode: Redirect to centralized login
|
|
87
42
|
return clientLogin(clientKey, redirectUri);
|
|
88
43
|
}
|
|
89
44
|
}
|
|
@@ -129,7 +84,7 @@ export function logout() {
|
|
|
129
84
|
hasToken: !!token
|
|
130
85
|
});
|
|
131
86
|
|
|
132
|
-
// Clear local storage immediately
|
|
87
|
+
// Clear local storage immediately (this will trigger listeners)
|
|
133
88
|
clearToken();
|
|
134
89
|
sessionStorage.clear();
|
|
135
90
|
|
|
@@ -140,7 +95,7 @@ export function logout() {
|
|
|
140
95
|
}
|
|
141
96
|
}
|
|
142
97
|
|
|
143
|
-
// Router logout
|
|
98
|
+
// ✅ Router logout
|
|
144
99
|
async function routerLogout(clientKey, authBaseUrl, accountUiUrl, token) {
|
|
145
100
|
console.log('🏭 Router Logout: Backend logout for all sessions');
|
|
146
101
|
|
|
@@ -170,9 +125,113 @@ async function routerLogout(clientKey, authBaseUrl, accountUiUrl, token) {
|
|
|
170
125
|
window.location.href = '/login';
|
|
171
126
|
}
|
|
172
127
|
|
|
173
|
-
// Client logout
|
|
128
|
+
// ✅ Client logout
|
|
174
129
|
function clientLogout(clientKey, accountUiUrl) {
|
|
175
130
|
console.log('🔄 Client Logout: Redirecting to centralized login');
|
|
176
131
|
const logoutUrl = `${accountUiUrl}/login?client=${clientKey}&logout=true`;
|
|
177
132
|
window.location.href = logoutUrl;
|
|
178
133
|
}
|
|
134
|
+
|
|
135
|
+
export function handleCallback() {
|
|
136
|
+
const params = new URLSearchParams(window.location.search);
|
|
137
|
+
const accessToken = params.get('access_token');
|
|
138
|
+
const error = params.get('error');
|
|
139
|
+
|
|
140
|
+
console.log('🔄 Handling authentication callback:', {
|
|
141
|
+
mode: isRouterMode() ? 'ROUTER' : 'CLIENT',
|
|
142
|
+
hasAccessToken: !!accessToken,
|
|
143
|
+
error,
|
|
144
|
+
alreadyProcessed: callbackProcessed
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ✅ If already processed and we have a token, return it
|
|
148
|
+
if (callbackProcessed) {
|
|
149
|
+
const existingToken = getToken();
|
|
150
|
+
if (existingToken) {
|
|
151
|
+
console.log('🔄 Callback already processed, returning existing token');
|
|
152
|
+
return existingToken;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ✅ Mark as processed first
|
|
157
|
+
callbackProcessed = true;
|
|
158
|
+
|
|
159
|
+
// Clean up session storage (only once)
|
|
160
|
+
sessionStorage.removeItem('originalApp');
|
|
161
|
+
sessionStorage.removeItem('returnUrl');
|
|
162
|
+
|
|
163
|
+
if (error) {
|
|
164
|
+
throw new Error(`Authentication failed: ${error}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (accessToken) {
|
|
168
|
+
// ✅ This will trigger token listeners
|
|
169
|
+
setToken(accessToken);
|
|
170
|
+
console.log('✅ Token set successfully, listeners notified');
|
|
171
|
+
return accessToken;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
throw new Error('No access token found in callback URL');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ✅ Reset callback state
|
|
178
|
+
export function resetCallbackState() {
|
|
179
|
+
callbackProcessed = false;
|
|
180
|
+
console.log('🔄 Callback state reset');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export async function refreshToken() {
|
|
184
|
+
const { clientKey, authBaseUrl } = getConfig();
|
|
185
|
+
|
|
186
|
+
console.log('🔄 Refreshing token:', {
|
|
187
|
+
clientKey,
|
|
188
|
+
mode: isRouterMode() ? 'ROUTER' : 'CLIENT'
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
const response = await fetch(`${authBaseUrl}/refresh/${clientKey}`, {
|
|
193
|
+
method: 'POST',
|
|
194
|
+
credentials: 'include',
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
if (!response.ok) {
|
|
198
|
+
throw new Error('Refresh failed');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const { access_token } = await response.json();
|
|
202
|
+
// ✅ This will trigger token listeners
|
|
203
|
+
setToken(access_token);
|
|
204
|
+
console.log('✅ Token refresh successful, listeners notified');
|
|
205
|
+
return access_token;
|
|
206
|
+
} catch (err) {
|
|
207
|
+
// ✅ This will trigger token listeners
|
|
208
|
+
clearToken();
|
|
209
|
+
throw err;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
export async function refreshToken() {
|
|
216
|
+
const { clientKey, authBaseUrl } = getConfig();
|
|
217
|
+
|
|
218
|
+
console.log('🔄 Refreshing token:', { clientKey, mode: isRouterMode() ? 'ROUTER' : 'CLIENT' });
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
const response = await fetch(`${authBaseUrl}/refresh/${clientKey}`, {
|
|
222
|
+
method: 'POST',
|
|
223
|
+
credentials: 'include',
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
if (!response.ok) {
|
|
227
|
+
throw new Error('Refresh failed');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const { access_token } = await response.json();
|
|
231
|
+
setToken(access_token);
|
|
232
|
+
return access_token;
|
|
233
|
+
} catch (err) {
|
|
234
|
+
clearToken();
|
|
235
|
+
throw err;
|
|
236
|
+
}
|
|
237
|
+
}
|
package/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// auth-client/index.js
|
|
2
2
|
import { setConfig, getConfig, isRouterMode } from './config';
|
|
3
3
|
import { login, logout, handleCallback, refreshToken, resetCallbackState } from './core';
|
|
4
|
-
import { getToken, setToken, clearToken } from './token';
|
|
4
|
+
import { getToken, setToken, clearToken, addTokenListener, removeTokenListener, getListenerCount } from './token';
|
|
5
5
|
import api from './api';
|
|
6
6
|
import { decodeToken, isTokenExpired } from './utils/jwt';
|
|
7
7
|
|
|
@@ -16,12 +16,15 @@ export const auth = {
|
|
|
16
16
|
logout,
|
|
17
17
|
handleCallback,
|
|
18
18
|
refreshToken,
|
|
19
|
-
resetCallbackState,
|
|
19
|
+
resetCallbackState,
|
|
20
20
|
|
|
21
21
|
// 🔑 Token management
|
|
22
22
|
getToken,
|
|
23
23
|
setToken,
|
|
24
24
|
clearToken,
|
|
25
|
+
addTokenListener, // ✅ Export new functions
|
|
26
|
+
removeTokenListener,
|
|
27
|
+
getListenerCount, // ✅ Debug function
|
|
25
28
|
|
|
26
29
|
// 🌐 Authenticated API client
|
|
27
30
|
api,
|
package/package.json
CHANGED
package/token.js
CHANGED
|
@@ -1,12 +1,33 @@
|
|
|
1
|
+
// auth-client/token.js
|
|
1
2
|
let memoryToken = null;
|
|
3
|
+
const listeners = new Set(); // ✅ Add listeners
|
|
2
4
|
|
|
3
5
|
export function setToken(token) {
|
|
6
|
+
const previousToken = memoryToken;
|
|
4
7
|
memoryToken = token;
|
|
8
|
+
|
|
5
9
|
try {
|
|
6
10
|
localStorage.setItem('authToken', token);
|
|
7
11
|
} catch (err) {
|
|
8
12
|
console.warn('Could not write token to localStorage:', err);
|
|
9
13
|
}
|
|
14
|
+
|
|
15
|
+
// ✅ Notify listeners when token changes
|
|
16
|
+
if (previousToken !== token) {
|
|
17
|
+
console.log('🔔 Token changed, notifying listeners:', {
|
|
18
|
+
listenerCount: listeners.size,
|
|
19
|
+
hadToken: !!previousToken,
|
|
20
|
+
hasToken: !!token
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
listeners.forEach(listener => {
|
|
24
|
+
try {
|
|
25
|
+
listener(token, previousToken);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
console.warn('Token listener error:', err);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
10
31
|
}
|
|
11
32
|
|
|
12
33
|
export function getToken() {
|
|
@@ -22,10 +43,59 @@ export function getToken() {
|
|
|
22
43
|
}
|
|
23
44
|
|
|
24
45
|
export function clearToken() {
|
|
46
|
+
const previousToken = memoryToken;
|
|
25
47
|
memoryToken = null;
|
|
48
|
+
|
|
26
49
|
try {
|
|
27
50
|
localStorage.removeItem('authToken');
|
|
28
51
|
} catch (err) {
|
|
29
52
|
console.warn('Could not clear token from localStorage:', err);
|
|
30
53
|
}
|
|
54
|
+
|
|
55
|
+
// ✅ Notify listeners when token is cleared
|
|
56
|
+
if (previousToken) {
|
|
57
|
+
console.log('🔔 Token cleared, notifying listeners:', {
|
|
58
|
+
listenerCount: listeners.size
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
listeners.forEach(listener => {
|
|
62
|
+
try {
|
|
63
|
+
listener(null, previousToken);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
console.warn('Token listener error:', err);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ✅ Add listener management
|
|
72
|
+
export function addTokenListener(listener) {
|
|
73
|
+
if (typeof listener !== 'function') {
|
|
74
|
+
throw new Error('Token listener must be a function');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
listeners.add(listener);
|
|
78
|
+
console.log('📎 Token listener added, total listeners:', listeners.size);
|
|
79
|
+
|
|
80
|
+
// Return cleanup function
|
|
81
|
+
return () => {
|
|
82
|
+
const removed = listeners.delete(listener);
|
|
83
|
+
if (removed) {
|
|
84
|
+
console.log('📎 Token listener removed, remaining listeners:', listeners.size);
|
|
85
|
+
}
|
|
86
|
+
return removed;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function removeTokenListener(listener) {
|
|
91
|
+
const removed = listeners.delete(listener);
|
|
92
|
+
if (removed) {
|
|
93
|
+
console.log('📎 Token listener removed, remaining listeners:', listeners.size);
|
|
94
|
+
}
|
|
95
|
+
return removed;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ✅ Debug function to see current listeners
|
|
99
|
+
export function getListenerCount() {
|
|
100
|
+
return listeners.size;
|
|
31
101
|
}
|