@spidy092/auth-client 2.1.0 → 2.1.3
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 +29 -5
- package/index.js +4 -1
- package/package.json +1 -1
- package/token.js +6 -6
package/core.js
CHANGED
|
@@ -233,15 +233,31 @@ export async function refreshToken() {
|
|
|
233
233
|
refreshInProgress = true;
|
|
234
234
|
refreshPromise = (async () => {
|
|
235
235
|
try {
|
|
236
|
+
// Get stored refresh token (for HTTP development)
|
|
237
|
+
const storedRefreshToken = getRefreshToken();
|
|
238
|
+
|
|
236
239
|
console.log('🔄 Refreshing token:', {
|
|
237
240
|
clientKey,
|
|
238
|
-
mode: isRouterMode() ? 'ROUTER' : 'CLIENT'
|
|
241
|
+
mode: isRouterMode() ? 'ROUTER' : 'CLIENT',
|
|
242
|
+
hasStoredRefreshToken: !!storedRefreshToken
|
|
239
243
|
});
|
|
240
244
|
|
|
241
|
-
|
|
245
|
+
// Build request options - send refresh token in body and header for HTTP dev
|
|
246
|
+
const requestOptions = {
|
|
242
247
|
method: 'POST',
|
|
243
|
-
credentials: 'include', // ✅ Include httpOnly cookies
|
|
244
|
-
|
|
248
|
+
credentials: 'include', // ✅ Include httpOnly cookies (for HTTPS)
|
|
249
|
+
headers: {
|
|
250
|
+
'Content-Type': 'application/json'
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// For HTTP development, send refresh token in body and header
|
|
255
|
+
if (storedRefreshToken) {
|
|
256
|
+
requestOptions.headers['X-Refresh-Token'] = storedRefreshToken;
|
|
257
|
+
requestOptions.body = JSON.stringify({ refreshToken: storedRefreshToken });
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const response = await fetch(`${authBaseUrl}/refresh/${clientKey}`, requestOptions);
|
|
245
261
|
|
|
246
262
|
if (!response.ok) {
|
|
247
263
|
const errorText = await response.text();
|
|
@@ -249,7 +265,8 @@ export async function refreshToken() {
|
|
|
249
265
|
throw new Error(`Refresh failed: ${response.status}`);
|
|
250
266
|
}
|
|
251
267
|
|
|
252
|
-
const
|
|
268
|
+
const data = await response.json();
|
|
269
|
+
const { access_token, refresh_token: new_refresh_token } = data;
|
|
253
270
|
|
|
254
271
|
if (!access_token) {
|
|
255
272
|
throw new Error('No access token in refresh response');
|
|
@@ -257,6 +274,13 @@ export async function refreshToken() {
|
|
|
257
274
|
|
|
258
275
|
// ✅ This will trigger token listeners
|
|
259
276
|
setToken(access_token);
|
|
277
|
+
|
|
278
|
+
// ✅ Store new refresh token if provided (token rotation)
|
|
279
|
+
if (new_refresh_token) {
|
|
280
|
+
setRefreshToken(new_refresh_token);
|
|
281
|
+
console.log('🔄 New refresh token stored from rotation');
|
|
282
|
+
}
|
|
283
|
+
|
|
260
284
|
console.log('✅ Token refresh successful, listeners notified');
|
|
261
285
|
return access_token;
|
|
262
286
|
} catch (err) {
|
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, validateCurrentSession } from './core';
|
|
4
|
-
import { getToken, setToken, clearToken, addTokenListener, removeTokenListener, getListenerCount } from './token';
|
|
4
|
+
import { getToken, setToken, clearToken, setRefreshToken, getRefreshToken, clearRefreshToken, addTokenListener, removeTokenListener, getListenerCount } from './token';
|
|
5
5
|
import api from './api';
|
|
6
6
|
import { decodeToken, isTokenExpired, isAuthenticated } from './utils/jwt';
|
|
7
7
|
|
|
@@ -23,6 +23,9 @@ export const auth = {
|
|
|
23
23
|
getToken,
|
|
24
24
|
setToken,
|
|
25
25
|
clearToken,
|
|
26
|
+
setRefreshToken, // ✅ Refresh token for HTTP dev
|
|
27
|
+
getRefreshToken,
|
|
28
|
+
clearRefreshToken,
|
|
26
29
|
addTokenListener, // ✅ Export new functions
|
|
27
30
|
removeTokenListener,
|
|
28
31
|
getListenerCount, // ✅ Debug function
|
package/package.json
CHANGED
package/token.js
CHANGED
|
@@ -146,14 +146,14 @@ export function clearToken() {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
// ========== REFRESH TOKEN STORAGE FOR HTTP DEVELOPMENT ==========
|
|
149
|
-
// In production, refresh tokens should ONLY be in httpOnly cookies set by server
|
|
149
|
+
// In production (HTTPS), refresh tokens should ONLY be in httpOnly cookies set by server
|
|
150
150
|
// For HTTP development (cross-origin cookies don't work), we store in localStorage
|
|
151
151
|
const REFRESH_TOKEN_KEY = 'auth_refresh_token';
|
|
152
152
|
|
|
153
153
|
function isHttpDevelopment() {
|
|
154
154
|
try {
|
|
155
|
-
return typeof window !== 'undefined' &&
|
|
156
|
-
|
|
155
|
+
return typeof window !== 'undefined' &&
|
|
156
|
+
window.location?.protocol === 'http:';
|
|
157
157
|
} catch (err) {
|
|
158
158
|
return false;
|
|
159
159
|
}
|
|
@@ -190,7 +190,7 @@ export function getRefreshToken() {
|
|
|
190
190
|
return null;
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
|
-
|
|
193
|
+
|
|
194
194
|
// In production, refresh token is in httpOnly cookie (not accessible via JS)
|
|
195
195
|
// The refresh endpoint uses credentials: 'include' to send the cookie
|
|
196
196
|
return null;
|
|
@@ -203,14 +203,14 @@ export function clearRefreshToken() {
|
|
|
203
203
|
} catch (err) {
|
|
204
204
|
// Ignore
|
|
205
205
|
}
|
|
206
|
-
|
|
206
|
+
|
|
207
207
|
// Clear cookie (for production)
|
|
208
208
|
try {
|
|
209
209
|
document.cookie = `${REFRESH_COOKIE}=; Path=/; SameSite=Strict${secureAttribute()}; Expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
210
210
|
} catch (err) {
|
|
211
211
|
console.warn('Could not clear refresh token cookie:', err);
|
|
212
212
|
}
|
|
213
|
-
|
|
213
|
+
|
|
214
214
|
// Clear sessionStorage
|
|
215
215
|
try {
|
|
216
216
|
sessionStorage.removeItem(REFRESH_COOKIE);
|