@spidy092/auth-client 2.0.0 → 2.0.2
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 +76 -0
- package/package.json +1 -1
- package/token.js +42 -60
package/core.js
CHANGED
|
@@ -40,6 +40,16 @@ export function login(clientKeyArg, redirectUriArg) {
|
|
|
40
40
|
sessionStorage.setItem('originalApp', clientKey);
|
|
41
41
|
sessionStorage.setItem('returnUrl', redirectUri);
|
|
42
42
|
|
|
43
|
+
try {
|
|
44
|
+
const hasValidSession = await checkExistingTokens();
|
|
45
|
+
if (hasValidSession) {
|
|
46
|
+
console.log('✅ Valid session found, skipping login redirect');
|
|
47
|
+
return getToken();
|
|
48
|
+
}
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.log('⚠️ No valid session, proceeding with login flow');
|
|
51
|
+
}
|
|
52
|
+
|
|
43
53
|
// ✅ Smart Router Logic
|
|
44
54
|
if (isRouterMode()) {
|
|
45
55
|
// Router mode: Direct backend authentication
|
|
@@ -64,6 +74,72 @@ function routerLogin(clientKey, redirectUri) {
|
|
|
64
74
|
window.location.href = backendLoginUrl;
|
|
65
75
|
}
|
|
66
76
|
|
|
77
|
+
|
|
78
|
+
async function checkExistingTokens() {
|
|
79
|
+
const token = getToken();
|
|
80
|
+
const refreshTokenValue = getRefreshToken();
|
|
81
|
+
|
|
82
|
+
console.log('🔍 Checking existing tokens:', {
|
|
83
|
+
hasAccessToken: !!token,
|
|
84
|
+
hasRefreshToken: !!refreshTokenValue
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// No tokens at all
|
|
88
|
+
if (!token && !refreshTokenValue) {
|
|
89
|
+
console.log('❌ No tokens found');
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Have valid access token
|
|
94
|
+
if (token && !isTokenExpiredLocal(token)) {
|
|
95
|
+
console.log('✅ Valid access token exists');
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Have refresh token, try to get new access token
|
|
100
|
+
if (refreshTokenValue) {
|
|
101
|
+
try {
|
|
102
|
+
console.log('🔄 Access token expired, attempting refresh...');
|
|
103
|
+
const newToken = await refreshToken();
|
|
104
|
+
console.log('✅ Token refreshed successfully');
|
|
105
|
+
return !!newToken;
|
|
106
|
+
} catch (err) {
|
|
107
|
+
console.warn('❌ Token refresh failed:', err);
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ✅ NEW HELPER: Check if token is expired
|
|
116
|
+
function isTokenExpiredLocal(token, bufferSeconds = 60) {
|
|
117
|
+
if (!token) return true;
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const parts = token.split('.');
|
|
121
|
+
if (parts.length !== 3) return true;
|
|
122
|
+
|
|
123
|
+
const payload = JSON.parse(atob(parts[1]));
|
|
124
|
+
|
|
125
|
+
if (!payload.exp) return true;
|
|
126
|
+
|
|
127
|
+
const now = Date.now() / 1000;
|
|
128
|
+
const isExpired = payload.exp < (now + bufferSeconds);
|
|
129
|
+
|
|
130
|
+
console.log('🕐 Token expiry check:', {
|
|
131
|
+
expiresAt: new Date(payload.exp * 1000).toLocaleString(),
|
|
132
|
+
now: new Date(now * 1000).toLocaleString(),
|
|
133
|
+
isExpired
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return isExpired;
|
|
137
|
+
} catch (err) {
|
|
138
|
+
console.error('❌ Failed to decode token:', err);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
67
143
|
// ✅ Client mode: Centralized login
|
|
68
144
|
function clientLogin(clientKey, redirectUri) {
|
|
69
145
|
const { accountUiUrl } = getConfig();
|
package/package.json
CHANGED
package/token.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
// auth-client/token.js
|
|
1
|
+
// auth-client/token.js - CORRECTED VERSION
|
|
3
2
|
|
|
4
3
|
import { jwtDecode } from 'jwt-decode';
|
|
5
4
|
|
|
@@ -7,7 +6,6 @@ let accessToken = null;
|
|
|
7
6
|
const listeners = new Set();
|
|
8
7
|
|
|
9
8
|
const REFRESH_COOKIE = 'account_refresh_token';
|
|
10
|
-
const REFRESH_STORAGE_KEY = 'refresh_token'; // localStorage key
|
|
11
9
|
const COOKIE_MAX_AGE = 7 * 24 * 60 * 60; // 7 days in seconds
|
|
12
10
|
|
|
13
11
|
function secureAttribute() {
|
|
@@ -20,7 +18,7 @@ function secureAttribute() {
|
|
|
20
18
|
}
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
// ========== ACCESS TOKEN (localStorage
|
|
21
|
+
// ========== ACCESS TOKEN (localStorage - keeps working) ==========
|
|
24
22
|
function writeAccessToken(token) {
|
|
25
23
|
if (!token) {
|
|
26
24
|
try {
|
|
@@ -47,12 +45,8 @@ function readAccessToken() {
|
|
|
47
45
|
}
|
|
48
46
|
}
|
|
49
47
|
|
|
50
|
-
// ========== REFRESH TOKEN (
|
|
48
|
+
// ========== REFRESH TOKEN (Cookie + sessionStorage - REVERTED) ==========
|
|
51
49
|
|
|
52
|
-
/**
|
|
53
|
-
* Store refresh token in BOTH localStorage AND cookie
|
|
54
|
-
* Whichever survives (cross-domain, privacy settings) will work
|
|
55
|
-
*/
|
|
56
50
|
export function setRefreshToken(token) {
|
|
57
51
|
if (!token) {
|
|
58
52
|
clearRefreshToken();
|
|
@@ -60,30 +54,26 @@ export function setRefreshToken(token) {
|
|
|
60
54
|
}
|
|
61
55
|
|
|
62
56
|
const expires = new Date(Date.now() + COOKIE_MAX_AGE * 1000);
|
|
63
|
-
|
|
64
|
-
//
|
|
57
|
+
|
|
58
|
+
// ✅ REVERT: Use SameSite=Lax (NOT Strict) for SSO to work
|
|
65
59
|
try {
|
|
66
60
|
document.cookie = `${REFRESH_COOKIE}=${encodeURIComponent(token)}; Path=/; SameSite=Lax${secureAttribute()}; Expires=${expires.toUTCString()}`;
|
|
67
|
-
console.log('✅ Refresh token
|
|
61
|
+
console.log('✅ Refresh token cookie set (SameSite=Lax for SSO)');
|
|
68
62
|
} catch (err) {
|
|
69
|
-
console.warn('
|
|
63
|
+
console.warn('Could not persist refresh token cookie:', err);
|
|
70
64
|
}
|
|
71
65
|
|
|
72
|
-
//
|
|
66
|
+
// ✅ REVERT: Keep sessionStorage (NOT localStorage) as fallback
|
|
73
67
|
try {
|
|
74
|
-
|
|
75
|
-
console.log('✅ Refresh token
|
|
68
|
+
sessionStorage.setItem(REFRESH_COOKIE, token);
|
|
69
|
+
console.log('✅ Refresh token sessionStorage backup set');
|
|
76
70
|
} catch (err) {
|
|
77
|
-
console.warn('
|
|
71
|
+
console.warn('Could not persist refresh token to sessionStorage:', err);
|
|
78
72
|
}
|
|
79
73
|
}
|
|
80
74
|
|
|
81
|
-
/**
|
|
82
|
-
* Get refresh token from cookie OR localStorage (whichever works)
|
|
83
|
-
* Priority: Cookie > localStorage
|
|
84
|
-
*/
|
|
85
75
|
export function getRefreshToken() {
|
|
86
|
-
//
|
|
76
|
+
// Prefer cookie to align with server expectations
|
|
87
77
|
let cookieMatch = null;
|
|
88
78
|
try {
|
|
89
79
|
cookieMatch = document.cookie
|
|
@@ -94,48 +84,57 @@ export function getRefreshToken() {
|
|
|
94
84
|
}
|
|
95
85
|
|
|
96
86
|
if (cookieMatch) {
|
|
97
|
-
const token = decodeURIComponent(cookieMatch.split('=')[1]);
|
|
98
87
|
console.log('✅ Retrieved refresh token from cookie');
|
|
99
|
-
return
|
|
88
|
+
return decodeURIComponent(cookieMatch.split('=')[1]);
|
|
100
89
|
}
|
|
101
90
|
|
|
102
|
-
//
|
|
91
|
+
// ✅ REVERT: Fallback to sessionStorage (NOT localStorage)
|
|
103
92
|
try {
|
|
104
|
-
const token =
|
|
93
|
+
const token = sessionStorage.getItem(REFRESH_COOKIE);
|
|
105
94
|
if (token) {
|
|
106
|
-
console.log('✅ Retrieved refresh token from
|
|
107
|
-
return token;
|
|
95
|
+
console.log('✅ Retrieved refresh token from sessionStorage (fallback)');
|
|
108
96
|
}
|
|
97
|
+
return token;
|
|
109
98
|
} catch (err) {
|
|
110
|
-
console.warn('
|
|
99
|
+
console.warn('Could not read refresh token from sessionStorage:', err);
|
|
100
|
+
return null;
|
|
111
101
|
}
|
|
112
|
-
|
|
113
|
-
console.warn('⚠️ No refresh token found in cookie or localStorage');
|
|
114
|
-
return null;
|
|
115
102
|
}
|
|
116
103
|
|
|
117
|
-
/**
|
|
118
|
-
* Clear refresh token from BOTH cookie AND localStorage
|
|
119
|
-
*/
|
|
120
104
|
export function clearRefreshToken() {
|
|
121
|
-
// Clear
|
|
105
|
+
// ✅ REVERT: Clear with SameSite=Lax
|
|
122
106
|
try {
|
|
123
107
|
document.cookie = `${REFRESH_COOKIE}=; Path=/; SameSite=Lax${secureAttribute()}; Expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
124
|
-
console.log('✅ Cleared refresh token cookie');
|
|
125
108
|
} catch (err) {
|
|
126
|
-
console.warn('
|
|
109
|
+
console.warn('Could not clear refresh token cookie:', err);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ✅ REVERT: Clear sessionStorage (NOT localStorage)
|
|
113
|
+
try {
|
|
114
|
+
sessionStorage.removeItem(REFRESH_COOKIE);
|
|
115
|
+
} catch (err) {
|
|
116
|
+
console.warn('Could not clear refresh token from sessionStorage:', err);
|
|
127
117
|
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ========== ACCESS TOKEN FUNCTIONS (unchanged) ==========
|
|
128
121
|
|
|
129
|
-
|
|
122
|
+
function decode(token) {
|
|
130
123
|
try {
|
|
131
|
-
|
|
132
|
-
console.log('✅ Cleared refresh token from localStorage');
|
|
124
|
+
return jwtDecode(token);
|
|
133
125
|
} catch (err) {
|
|
134
|
-
|
|
126
|
+
return null;
|
|
135
127
|
}
|
|
136
128
|
}
|
|
137
129
|
|
|
138
|
-
|
|
130
|
+
function isExpired(token, bufferSeconds = 60) {
|
|
131
|
+
if (!token) return true;
|
|
132
|
+
const decoded = decode(token);
|
|
133
|
+
if (!decoded?.exp) return true;
|
|
134
|
+
const now = Date.now() / 1000;
|
|
135
|
+
return decoded.exp < now + bufferSeconds;
|
|
136
|
+
}
|
|
137
|
+
|
|
139
138
|
export function setToken(token) {
|
|
140
139
|
const previousToken = accessToken;
|
|
141
140
|
accessToken = token || null;
|
|
@@ -179,23 +178,6 @@ export function clearToken() {
|
|
|
179
178
|
});
|
|
180
179
|
}
|
|
181
180
|
|
|
182
|
-
// ========== HELPER FUNCTIONS ==========
|
|
183
|
-
function decode(token) {
|
|
184
|
-
try {
|
|
185
|
-
return jwtDecode(token);
|
|
186
|
-
} catch (err) {
|
|
187
|
-
return null;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function isExpired(token, bufferSeconds = 60) {
|
|
192
|
-
if (!token) return true;
|
|
193
|
-
const decoded = decode(token);
|
|
194
|
-
if (!decoded?.exp) return true;
|
|
195
|
-
const now = Date.now() / 1000;
|
|
196
|
-
return decoded.exp < now + bufferSeconds;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
181
|
export function addTokenListener(listener) {
|
|
200
182
|
if (typeof listener !== 'function') {
|
|
201
183
|
throw new Error('Token listener must be a function');
|