@spidy092/auth-client 1.0.12 → 1.0.14

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.
Files changed (4) hide show
  1. package/core.js +87 -53
  2. package/index.js +5 -2
  3. package/package.json +1 -1
  4. 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 if callback was already processed
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 (from my previous response)
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 (same as before)
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,18 +125,68 @@ async function routerLogout(clientKey, authBaseUrl, accountUiUrl, token) {
170
125
  window.location.href = '/login';
171
126
  }
172
127
 
173
- // Client logout (same as before)
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
  }
179
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
+ }
180
182
 
181
183
  export async function refreshToken() {
182
184
  const { clientKey, authBaseUrl } = getConfig();
183
185
 
184
- console.log('🔄 Refreshing token:', { clientKey, mode: isRouterMode() ? 'ROUTER' : 'CLIENT' });
186
+ console.log('🔄 Refreshing token:', {
187
+ clientKey,
188
+ mode: isRouterMode() ? 'ROUTER' : 'CLIENT'
189
+ });
185
190
 
186
191
  try {
187
192
  const response = await fetch(`${authBaseUrl}/refresh/${clientKey}`, {
@@ -194,10 +199,39 @@ export async function refreshToken() {
194
199
  }
195
200
 
196
201
  const { access_token } = await response.json();
202
+ // ✅ This will trigger token listeners
197
203
  setToken(access_token);
204
+ console.log('✅ Token refresh successful, listeners notified');
198
205
  return access_token;
199
206
  } catch (err) {
207
+ // ✅ This will trigger token listeners
200
208
  clearToken();
201
209
  throw err;
202
210
  }
203
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, // ✅ Export reset function
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spidy092/auth-client",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "Scalable frontend auth SDK for centralized login using Keycloak + Auth Service.",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
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
  }