@spidy092/auth-client 2.1.8 → 3.0.1

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/token.js DELETED
@@ -1,455 +0,0 @@
1
- // auth-client/token.js - MINIMAL WORKING VERSION
2
-
3
- import { jwtDecode } from 'jwt-decode';
4
-
5
- let accessToken = null;
6
- const listeners = new Set();
7
-
8
- const REFRESH_COOKIE = 'account_refresh_token';
9
- const COOKIE_MAX_AGE = 7 * 24 * 60 * 60;
10
-
11
- function secureAttribute() {
12
- try {
13
- return typeof window !== 'undefined' && window.location?.protocol === 'https:'
14
- ? '; Secure'
15
- : '';
16
- } catch (err) {
17
- return '';
18
- }
19
- }
20
-
21
- // ========== ACCESS TOKEN ==========
22
- function writeAccessToken(token) {
23
- if (!token) {
24
- try {
25
- localStorage.removeItem('authToken');
26
- } catch (err) {
27
- console.warn('Could not clear token from localStorage:', err);
28
- }
29
- return;
30
- }
31
-
32
- try {
33
- localStorage.setItem('authToken', token);
34
- } catch (err) {
35
- console.warn('Could not persist token to localStorage:', err);
36
- }
37
- }
38
-
39
- function readAccessToken() {
40
- try {
41
- return localStorage.getItem('authToken');
42
- } catch (err) {
43
- console.warn('Could not read token from localStorage:', err);
44
- return null;
45
- }
46
- }
47
-
48
- // ========== REFRESH TOKEN (KEEP SIMPLE) ==========
49
- // export function setRefreshToken(token) {
50
- // if (!token) {
51
- // clearRefreshToken();
52
- // return;
53
- // }
54
-
55
- // const expires = new Date(Date.now() + COOKIE_MAX_AGE * 1000);
56
-
57
- // try {
58
- // document.cookie = `${REFRESH_COOKIE}=${encodeURIComponent(token)}; Path=/; SameSite=Lax${secureAttribute()}; Expires=${expires.toUTCString()}`;
59
- // } catch (err) {
60
- // console.warn('Could not set refresh token:', err);
61
- // }
62
- // }
63
-
64
- // export function getRefreshToken() {
65
- // try {
66
- // const match = document.cookie
67
- // ?.split('; ')
68
- // ?.find((row) => row.startsWith(`${REFRESH_COOKIE}=`));
69
-
70
- // if (match) {
71
- // return decodeURIComponent(match.split('=')[1]);
72
- // }
73
- // } catch (err) {
74
- // console.warn('Could not read refresh token:', err);
75
- // }
76
-
77
- // return null;
78
- // }
79
-
80
- // export function clearRefreshToken() {
81
- // try {
82
- // document.cookie = `${REFRESH_COOKIE}=; Path=/; SameSite=Lax${secureAttribute()}; Expires=Thu, 01 Jan 1970 00:00:00 GMT`;
83
- // } catch (err) {
84
- // console.warn('Could not clear refresh token:', err);
85
- // }
86
- // }
87
-
88
- // ========== ACCESS TOKEN FUNCTIONS ==========
89
- function decode(token) {
90
- try {
91
- return jwtDecode(token);
92
- } catch (err) {
93
- return null;
94
- }
95
- }
96
-
97
- function isExpired(token, bufferSeconds = 60) {
98
- if (!token) return true;
99
- const decoded = decode(token);
100
- if (!decoded?.exp) return true;
101
- const now = Date.now() / 1000;
102
- return decoded.exp < now + bufferSeconds;
103
- }
104
-
105
- // ========== TOKEN EXPIRY UTILITIES ==========
106
- // Get the exact expiry time of a token as a Date object
107
- export function getTokenExpiryTime(token) {
108
- if (!token) return null;
109
- const decoded = decode(token);
110
- if (!decoded?.exp) return null;
111
- return new Date(decoded.exp * 1000);
112
- }
113
-
114
- // Get seconds until token expires (negative if already expired)
115
- export function getTimeUntilExpiry(token) {
116
- if (!token) return -1;
117
- const decoded = decode(token);
118
- if (!decoded?.exp) return -1;
119
- const now = Date.now() / 1000;
120
- return Math.floor(decoded.exp - now);
121
- }
122
-
123
- // Check if token will expire within the next N seconds
124
- export function willExpireSoon(token, withinSeconds = 60) {
125
- const timeLeft = getTimeUntilExpiry(token);
126
- return timeLeft >= 0 && timeLeft <= withinSeconds;
127
- }
128
-
129
- export function setToken(token) {
130
- const previousToken = accessToken;
131
- accessToken = token || null;
132
- writeAccessToken(accessToken);
133
-
134
- if (previousToken !== accessToken) {
135
- listeners.forEach((listener) => {
136
- try {
137
- listener(accessToken, previousToken);
138
- } catch (err) {
139
- console.warn('Token listener error:', err);
140
- }
141
- });
142
- }
143
- }
144
-
145
- export function getToken() {
146
- if (accessToken) return accessToken;
147
- accessToken = readAccessToken();
148
- return accessToken;
149
- }
150
-
151
- export function clearToken() {
152
- if (!accessToken) {
153
- writeAccessToken(null);
154
- clearRefreshToken();
155
- return;
156
- }
157
-
158
- const previousToken = accessToken;
159
- accessToken = null;
160
- writeAccessToken(null);
161
- clearRefreshToken();
162
-
163
- listeners.forEach((listener) => {
164
- try {
165
- listener(null, previousToken);
166
- } catch (err) {
167
- console.warn('Token listener error:', err);
168
- }
169
- });
170
- }
171
-
172
- // ========== REFRESH TOKEN STORAGE FOR HTTP DEVELOPMENT ==========
173
- // In production (HTTPS), refresh tokens should ONLY be in httpOnly cookies set by server
174
- // For HTTP development (cross-origin cookies don't work), we store in localStorage
175
- const REFRESH_TOKEN_KEY = 'auth_refresh_token';
176
-
177
- function isHttpDevelopment() {
178
- try {
179
- return typeof window !== 'undefined' &&
180
- window.location?.protocol === 'http:';
181
- } catch (err) {
182
- return false;
183
- }
184
- }
185
-
186
- export function setRefreshToken(token) {
187
- if (!token) {
188
- clearRefreshToken();
189
- return;
190
- }
191
-
192
- // For HTTP development, store in localStorage (since httpOnly cookies don't work cross-origin)
193
- if (isHttpDevelopment()) {
194
- try {
195
- localStorage.setItem(REFRESH_TOKEN_KEY, token);
196
- console.log('📦 Refresh token stored in localStorage (HTTP dev mode)');
197
- } catch (err) {
198
- console.warn('Could not store refresh token:', err);
199
- }
200
- } else {
201
- // In production (HTTPS), refresh token should be in httpOnly cookie only
202
- console.log('🔒 Refresh token managed by server httpOnly cookie (production mode)');
203
- }
204
- }
205
-
206
- export function getRefreshToken() {
207
- // For HTTP development, read from localStorage
208
- if (isHttpDevelopment()) {
209
- try {
210
- const token = localStorage.getItem(REFRESH_TOKEN_KEY);
211
- return token;
212
- } catch (err) {
213
- console.warn('Could not read refresh token:', err);
214
- return null;
215
- }
216
- }
217
-
218
- // In production, refresh token is in httpOnly cookie (not accessible via JS)
219
- // The refresh endpoint uses credentials: 'include' to send the cookie
220
- return null;
221
- }
222
-
223
- export function clearRefreshToken() {
224
- // Clear localStorage (for HTTP dev)
225
- try {
226
- localStorage.removeItem(REFRESH_TOKEN_KEY);
227
- } catch (err) {
228
- // Ignore
229
- }
230
-
231
- // Clear cookie (for production)
232
- try {
233
- document.cookie = `${REFRESH_COOKIE}=; Path=/; SameSite=Strict${secureAttribute()}; Expires=Thu, 01 Jan 1970 00:00:00 GMT`;
234
- } catch (err) {
235
- console.warn('Could not clear refresh token cookie:', err);
236
- }
237
-
238
- // Clear sessionStorage
239
- try {
240
- sessionStorage.removeItem(REFRESH_COOKIE);
241
- } catch (err) {
242
- // Ignore
243
- }
244
- }
245
-
246
- export function addTokenListener(listener) {
247
- if (typeof listener !== 'function') {
248
- throw new Error('Token listener must be a function');
249
- }
250
- listeners.add(listener);
251
- return () => {
252
- listeners.delete(listener);
253
- };
254
- }
255
-
256
- export function removeTokenListener(listener) {
257
- listeners.delete(listener);
258
- }
259
-
260
- export function getListenerCount() {
261
- return listeners.size;
262
- }
263
-
264
- export function isAuthenticated() {
265
- const token = getToken();
266
- return !!token && !isExpired(token, 15);
267
- }
268
-
269
-
270
-
271
-
272
- // // auth-client/token.js
273
- // import { jwtDecode } from 'jwt-decode';
274
-
275
- // let accessToken = null;
276
- // const listeners = new Set();
277
-
278
- // const REFRESH_COOKIE = 'account_refresh_token';
279
- // const COOKIE_MAX_AGE = 7 * 24 * 60 * 60; // 7 days in seconds
280
-
281
- // function secureAttribute() {
282
- // try {
283
- // return typeof window !== 'undefined' && window.location?.protocol === 'https:'
284
- // ? '; Secure'
285
- // : '';
286
- // } catch (err) {
287
- // return '';
288
- // }
289
- // }
290
-
291
- // function writeAccessToken(token) {
292
- // if (!token) {
293
- // try {
294
- // localStorage.removeItem('authToken');
295
- // } catch (err) {
296
- // console.warn('Could not clear token from localStorage:', err);
297
- // }
298
- // return;
299
- // }
300
-
301
- // try {
302
- // localStorage.setItem('authToken', token);
303
- // } catch (err) {
304
- // console.warn('Could not persist token to localStorage:', err);
305
- // }
306
- // }
307
-
308
- // function readAccessToken() {
309
- // try {
310
- // return localStorage.getItem('authToken');
311
- // } catch (err) {
312
- // console.warn('Could not read token from localStorage:', err);
313
- // return null;
314
- // }
315
- // }
316
-
317
- // function decode(token) {
318
- // try {
319
- // return jwtDecode(token);
320
- // } catch (err) {
321
- // return null;
322
- // }
323
- // }
324
-
325
- // function isExpired(token, bufferSeconds = 60) {
326
- // if (!token) return true;
327
- // const decoded = decode(token);
328
- // if (!decoded?.exp) return true;
329
- // const now = Date.now() / 1000;
330
- // return decoded.exp < now + bufferSeconds;
331
- // }
332
-
333
- // export function setToken(token) {
334
- // const previousToken = accessToken;
335
- // accessToken = token || null;
336
- // writeAccessToken(accessToken);
337
-
338
- // if (previousToken !== accessToken) {
339
- // listeners.forEach((listener) => {
340
- // try {
341
- // listener(accessToken, previousToken);
342
- // } catch (err) {
343
- // console.warn('Token listener error:', err);
344
- // }
345
- // });
346
- // }
347
- // }
348
-
349
- // export function getToken() {
350
- // if (accessToken) return accessToken;
351
- // accessToken = readAccessToken();
352
- // return accessToken;
353
- // }
354
-
355
- // export function clearToken() {
356
- // if (!accessToken) {
357
- // writeAccessToken(null);
358
- // clearRefreshToken();
359
- // return;
360
- // }
361
-
362
- // const previousToken = accessToken;
363
- // accessToken = null;
364
- // writeAccessToken(null);
365
- // clearRefreshToken();
366
-
367
- // listeners.forEach((listener) => {
368
- // try {
369
- // listener(null, previousToken);
370
- // } catch (err) {
371
- // console.warn('Token listener error:', err);
372
- // }
373
- // });
374
- // }
375
-
376
- // export function setRefreshToken(token) {
377
- // if (!token) {
378
- // clearRefreshToken();
379
- // return;
380
- // }
381
-
382
- // const expires = new Date(Date.now() + COOKIE_MAX_AGE * 1000);
383
- // try {
384
- // document.cookie = `${REFRESH_COOKIE}=${encodeURIComponent(token)}; Path=/; SameSite=Strict${secureAttribute()}; Expires=${expires.toUTCString()}`;
385
- // } catch (err) {
386
- // console.warn('Could not persist refresh token cookie:', err);
387
- // }
388
-
389
- // try {
390
- // sessionStorage.setItem(REFRESH_COOKIE, token);
391
- // } catch (err) {
392
- // console.warn('Could not persist refresh token to sessionStorage:', err);
393
- // }
394
- // }
395
-
396
- // export function getRefreshToken() {
397
- // // Prefer cookie to align with server expectations
398
- // let cookieMatch = null;
399
-
400
- // try {
401
- // cookieMatch = document.cookie
402
- // ?.split('; ')
403
- // ?.find((row) => row.startsWith(`${REFRESH_COOKIE}=`));
404
- // } catch (err) {
405
- // cookieMatch = null;
406
- // }
407
-
408
- // if (cookieMatch) {
409
- // return decodeURIComponent(cookieMatch.split('=')[1]);
410
- // }
411
-
412
- // try {
413
- // return sessionStorage.getItem(REFRESH_COOKIE);
414
- // } catch (err) {
415
- // console.warn('Could not read refresh token from sessionStorage:', err);
416
- // return null;
417
- // }
418
- // }
419
-
420
- // export function clearRefreshToken() {
421
- // try {
422
- // document.cookie = `${REFRESH_COOKIE}=; Path=/; SameSite=Strict${secureAttribute()}; Expires=Thu, 01 Jan 1970 00:00:00 GMT`;
423
- // } catch (err) {
424
- // console.warn('Could not clear refresh token cookie:', err);
425
- // }
426
- // try {
427
- // sessionStorage.removeItem(REFRESH_COOKIE);
428
- // } catch (err) {
429
- // console.warn('Could not clear refresh token from sessionStorage:', err);
430
- // }
431
- // }
432
-
433
- // export function addTokenListener(listener) {
434
- // if (typeof listener !== 'function') {
435
- // throw new Error('Token listener must be a function');
436
- // }
437
- // listeners.add(listener);
438
- // return () => {
439
- // listeners.delete(listener);
440
- // };
441
- // }
442
-
443
- // export function removeTokenListener(listener) {
444
- // listeners.delete(listener);
445
- // }
446
-
447
- // export function getListenerCount() {
448
- // return listeners.size;
449
- // }
450
-
451
- // export function isAuthenticated() {
452
- // const token = getToken();
453
- // return !!token && !isExpired(token, 15);
454
- // }
455
-
package/utils/jwt.js DELETED
@@ -1,27 +0,0 @@
1
- // auth-client/utils/jwt.js
2
- import { jwtDecode } from 'jwt-decode';
3
- import { getToken } from '../token';
4
-
5
- export function decodeToken(token) {
6
- try {
7
- return jwtDecode(token);
8
- } catch (err) {
9
- console.warn('Failed to decode JWT:', err);
10
- return null;
11
- }
12
- }
13
-
14
- export function isTokenExpired(token, bufferSeconds = 60) {
15
- const decoded = decodeToken(token);
16
- if (!decoded || !decoded.exp) return true;
17
- const currentTime = Date.now() / 1000;
18
- return decoded.exp < currentTime + bufferSeconds;
19
- }
20
-
21
-
22
- // ✅ Check if user is authenticated
23
- export function isAuthenticated() {
24
- const token = getToken();
25
- return !!token && !isTokenExpired(token);
26
- }
27
-