antaeus.keycloak.react 2.6.1 → 2.6.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/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createContext, useContext, useState, useRef, useCallback, useEffect, useMemo } from 'react';
2
2
  import { useAuth as useAuth$1, AuthContext, AuthProvider } from 'react-oidc-context';
3
- import { WebStorageStateStore, User } from 'oidc-client-ts';
3
+ import { WebStorageStateStore, User, ErrorResponse } from 'oidc-client-ts';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import { useLocation } from 'react-router-dom';
6
6
  import { QRCodeSVG } from 'qrcode.react';
@@ -162,6 +162,20 @@ var isTransientNetworkError = (error) => {
162
162
  }
163
163
  return message.includes("network") || message.includes("failed to fetch") || message.includes("fetch") || message.includes("timeout") || message.includes("temporarily unavailable") || message.includes("dns") || message.includes("offline");
164
164
  };
165
+ var isInvalidRefreshTokenError = (error) => {
166
+ if (error instanceof ErrorResponse) {
167
+ const code = error.error?.toLowerCase?.();
168
+ if (code === "invalid_grant" || code === "invalid_token") {
169
+ return true;
170
+ }
171
+ const description = error.error_description?.toLowerCase?.();
172
+ if (description?.includes("refresh token")) {
173
+ return true;
174
+ }
175
+ }
176
+ const message = error.message?.toLowerCase?.() ?? "";
177
+ return message.includes("invalid_grant") || message.includes("refresh token") || message.includes("invalid token");
178
+ };
165
179
  function useTokenLifecycle(options) {
166
180
  const {
167
181
  config,
@@ -252,6 +266,20 @@ function useTokenLifecycle(options) {
252
266
  onRefreshSuccess?.();
253
267
  } catch (error) {
254
268
  const err = error instanceof Error ? error : new Error(String(error));
269
+ if (isInvalidRefreshTokenError(err)) {
270
+ log("Refresh token rejected by the identity provider, clearing stored session");
271
+ setIsRefreshTokenExpired(true);
272
+ onRefreshTokenExpired?.();
273
+ const key = getStorageKey();
274
+ localStorage.removeItem(key);
275
+ try {
276
+ await auth.removeUser();
277
+ } catch (removeError) {
278
+ log("Error removing user after invalid refresh token:", removeError);
279
+ }
280
+ onRefreshError?.(err);
281
+ throw err;
282
+ }
255
283
  if (isTransientNetworkError(err)) {
256
284
  const reason = isNavigatorOffline() ? "offline" : "network";
257
285
  deferredRefreshReasonRef.current = reason;
@@ -282,6 +310,7 @@ function useTokenLifecycle(options) {
282
310
  onRefreshError,
283
311
  onRefreshTokenExpired,
284
312
  enqueueRetry,
313
+ getStorageKey,
285
314
  log
286
315
  ]);
287
316
  const checkAndRefreshTokens = useCallback(async () => {
@@ -445,6 +474,11 @@ function useTokenLifecycle(options) {
445
474
  storeFirstLoginTime();
446
475
  }
447
476
  }, [auth.user, auth.isLoading, storeFirstLoginTime]);
477
+ useEffect(() => {
478
+ if (auth.isAuthenticated && isRefreshTokenExpired) {
479
+ setIsRefreshTokenExpired(false);
480
+ }
481
+ }, [auth.isAuthenticated, isRefreshTokenExpired]);
448
482
  useEffect(() => {
449
483
  if (!auth.isAuthenticated || auth.isLoading) {
450
484
  return;