@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.
Files changed (4) hide show
  1. package/core.js +29 -5
  2. package/index.js +4 -1
  3. package/package.json +1 -1
  4. 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
- const response = await fetch(`${authBaseUrl}/refresh/${clientKey}`, {
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 { access_token } = await response.json();
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spidy092/auth-client",
3
- "version": "2.1.0",
3
+ "version": "2.1.3",
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
@@ -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
- window.location?.protocol === 'http:';
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);