antaeus.keycloak.react 2.3.0 → 2.4.0

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,5 +1,5 @@
1
- import { createContext, useState, useRef, useCallback, useEffect, useMemo, useContext } from 'react';
2
- import { useAuth as useAuth$1, AuthProvider } from 'react-oidc-context';
1
+ import { createContext, useContext, useState, useRef, useCallback, useEffect, useMemo } from 'react';
2
+ import { useAuth as useAuth$1, AuthContext, AuthProvider } from 'react-oidc-context';
3
3
  import { WebStorageStateStore, User } from 'oidc-client-ts';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import { useLocation } from 'react-router-dom';
@@ -656,6 +656,71 @@ var SessionMonitor = ({
656
656
  ] });
657
657
  };
658
658
 
659
+ // src/utils/tokenBridge.ts
660
+ var TokenBridge = class {
661
+ constructor() {
662
+ this.currentToken = null;
663
+ this.listeners = /* @__PURE__ */ new Set();
664
+ }
665
+ /**
666
+ * Update the tracked token and notify subscribers when it changes.
667
+ */
668
+ setToken(token) {
669
+ if (this.currentToken === token) {
670
+ return;
671
+ }
672
+ this.currentToken = token;
673
+ for (const listener of this.listeners) {
674
+ try {
675
+ listener(token);
676
+ } catch (error) {
677
+ console.error("[TokenBridge] Listener threw error:", error);
678
+ }
679
+ }
680
+ }
681
+ /**
682
+ * Read the most recent token value.
683
+ */
684
+ getToken() {
685
+ return this.currentToken;
686
+ }
687
+ /**
688
+ * Convenience helper for async callers.
689
+ */
690
+ async getTokenAsync() {
691
+ return this.currentToken;
692
+ }
693
+ /**
694
+ * Subscribe to token changes. Returns an unsubscribe callback.
695
+ */
696
+ subscribe(listener) {
697
+ this.listeners.add(listener);
698
+ listener(this.currentToken);
699
+ return () => {
700
+ this.listeners.delete(listener);
701
+ };
702
+ }
703
+ };
704
+ var createTokenBridge = () => new TokenBridge();
705
+ var defaultTokenBridge = createTokenBridge();
706
+
707
+ // src/components/TokenBridge.tsx
708
+ var TokenBridgeSync = ({
709
+ bridge = defaultTokenBridge
710
+ }) => {
711
+ const auth = useAuth();
712
+ useEffect(() => {
713
+ const token = auth.user?.access_token ?? null;
714
+ bridge.setToken(token);
715
+ }, [auth.user, bridge]);
716
+ useEffect(() => {
717
+ if (!auth.isAuthenticated) {
718
+ bridge.setToken(null);
719
+ }
720
+ }, [auth.isAuthenticated, bridge]);
721
+ return null;
722
+ };
723
+
659
724
  // src/config/presets.ts
660
725
  var CONFIG_PRESETS = {
661
726
  /**
@@ -874,11 +939,97 @@ var StorageConfigProvider = ({ storageType, children }) => {
874
939
  return /* @__PURE__ */ jsx(StorageConfigContext.Provider, { value: { storageType, storage }, children });
875
940
  };
876
941
  var useStorageConfig = () => useContext(StorageConfigContext);
942
+ var defaultStatus = {
943
+ isEnabled: true,
944
+ isConfigured: true
945
+ };
946
+ var KeycloakStatusContext = createContext(defaultStatus);
947
+ var KeycloakStatusProvider = KeycloakStatusContext.Provider;
948
+ var useKeycloakStatus = () => useContext(KeycloakStatusContext);
949
+ var createDisabledEvents = () => {
950
+ const noop = () => void 0;
951
+ const noopSubscription = () => () => void 0;
952
+ const noopAsync = async () => void 0;
953
+ const events = {
954
+ addAccessTokenExpiring: noopSubscription,
955
+ removeAccessTokenExpiring: noop,
956
+ addAccessTokenExpired: noopSubscription,
957
+ removeAccessTokenExpired: noop,
958
+ addSilentRenewError: noopSubscription,
959
+ removeSilentRenewError: noop,
960
+ addUserLoaded: noopSubscription,
961
+ removeUserLoaded: noop,
962
+ addUserUnloaded: noopSubscription,
963
+ removeUserUnloaded: noop,
964
+ addUserSignedIn: noopSubscription,
965
+ removeUserSignedIn: noop,
966
+ addUserSignedOut: noopSubscription,
967
+ removeUserSignedOut: noop,
968
+ addUserSessionChanged: noopSubscription,
969
+ removeUserSessionChanged: noop,
970
+ load: noopAsync,
971
+ unload: noopAsync
972
+ };
973
+ return events;
974
+ };
975
+ var disabledEvents = createDisabledEvents();
976
+ var disabledSettings = {
977
+ authority: "",
978
+ client_id: "",
979
+ redirect_uri: "http://localhost/disabled",
980
+ response_type: "code",
981
+ scope: ""
982
+ };
983
+ var disabledError = () => new Error("Keycloak integration is disabled for this environment.");
984
+ var disabledAsync = async () => {
985
+ throw disabledError();
986
+ };
987
+ var disabledAuthContext = {
988
+ settings: disabledSettings,
989
+ events: disabledEvents,
990
+ clearStaleState: async () => void 0,
991
+ removeUser: async () => void 0,
992
+ signinPopup: (_args) => disabledAsync(),
993
+ signinSilent: async (_args) => null,
994
+ signinRedirect: (_args) => disabledAsync(),
995
+ signinResourceOwnerCredentials: (_args) => disabledAsync(),
996
+ signoutRedirect: async (_args) => void 0,
997
+ signoutPopup: async (_args) => void 0,
998
+ signoutSilent: async (_args) => void 0,
999
+ querySessionStatus: async (_args) => null,
1000
+ revokeTokens: async (_types) => void 0,
1001
+ startSilentRenew: () => void 0,
1002
+ stopSilentRenew: () => void 0,
1003
+ user: null,
1004
+ isLoading: false,
1005
+ isAuthenticated: false,
1006
+ activeNavigator: void 0,
1007
+ error: void 0
1008
+ };
877
1009
  function isZeroConfig(props) {
878
1010
  return "authority" in props && "clientId" in props;
879
1011
  }
880
1012
  var KeycloakProvider = (props) => {
881
1013
  const { children, debug = false } = props;
1014
+ const status = useMemo(() => {
1015
+ const enabledFlag = props.enabled ?? true;
1016
+ const hasAuthority = isZeroConfig(props) ? Boolean(props.authority) : Boolean(props.config.authority);
1017
+ const hasClientId = isZeroConfig(props) ? Boolean(props.clientId) : Boolean(props.config.clientId);
1018
+ return {
1019
+ isEnabled: enabledFlag,
1020
+ isConfigured: hasAuthority && hasClientId,
1021
+ reason: !enabledFlag ? "disabled" : !hasAuthority || !hasClientId ? "missing-config" : void 0
1022
+ };
1023
+ }, [props]);
1024
+ const effectiveEnabled = status.isEnabled && status.isConfigured;
1025
+ useEffect(() => {
1026
+ if (!effectiveEnabled && props.tokenBridge) {
1027
+ props.tokenBridge.setToken(null);
1028
+ }
1029
+ }, [effectiveEnabled, props.tokenBridge]);
1030
+ if (!effectiveEnabled) {
1031
+ return /* @__PURE__ */ jsx(KeycloakStatusProvider, { value: status, children: /* @__PURE__ */ jsx(AuthContext.Provider, { value: disabledAuthContext, children: /* @__PURE__ */ jsx(StorageConfigProvider, { storageType: "session", children }) }) });
1032
+ }
882
1033
  const config = isZeroConfig(props) ? buildZeroConfig(props) : props.config;
883
1034
  const oidcConfig = KeycloakConfigBuilder.build(config);
884
1035
  const log = useCallback(
@@ -920,7 +1071,7 @@ var KeycloakProvider = (props) => {
920
1071
  }, [log]);
921
1072
  const showSessionMonitor = config.features?.sessionMonitor !== false;
922
1073
  const storageType = config.advanced?.storageType || "session";
923
- return /* @__PURE__ */ jsx(
1074
+ return /* @__PURE__ */ jsx(KeycloakStatusProvider, { value: status, children: /* @__PURE__ */ jsx(
924
1075
  AuthProvider,
925
1076
  {
926
1077
  ...oidcConfig,
@@ -928,11 +1079,12 @@ var KeycloakProvider = (props) => {
928
1079
  onSignoutCallback,
929
1080
  onRemoveUser,
930
1081
  children: /* @__PURE__ */ jsx(StorageConfigProvider, { storageType, children: /* @__PURE__ */ jsxs(TokenLifecycleManager, { config, debug, children: [
1082
+ props.tokenBridge && /* @__PURE__ */ jsx(TokenBridgeSync, { bridge: props.tokenBridge }),
931
1083
  showSessionMonitor && /* @__PURE__ */ jsx(SessionMonitor, {}),
932
1084
  children
933
1085
  ] }) })
934
1086
  }
935
- );
1087
+ ) });
936
1088
  };
937
1089
  function buildZeroConfig(props) {
938
1090
  const { authority, clientId, preset = "default", config: overrides = {} } = props;
@@ -1636,6 +1788,6 @@ function useProtectedFetch(options = {}) {
1636
1788
  };
1637
1789
  }
1638
1790
 
1639
- export { CONFIG_PRESETS, DeviceLogin, KeycloakConfigBuilder, KeycloakProvider, LoginButton, LogoutButton, ProtectedRoute, SessionMonitor, TokenLifecycleManager, UserProfile, defaultConfig, fetchUserInfo, getConfigFromEnv, getConfigPreset, mergeWithPreset, pollForToken, requestDeviceCode, useAuth, useProtectedFetch, useRoles, useScopes, useTokenLifecycle };
1791
+ export { CONFIG_PRESETS, DeviceLogin, KeycloakConfigBuilder, KeycloakProvider, KeycloakStatusProvider, LoginButton, LogoutButton, ProtectedRoute, SessionMonitor, TokenBridge, TokenBridgeSync, TokenLifecycleManager, UserProfile, createTokenBridge, defaultConfig, defaultTokenBridge, fetchUserInfo, getConfigFromEnv, getConfigPreset, mergeWithPreset, pollForToken, requestDeviceCode, useAuth, useKeycloakStatus, useProtectedFetch, useRoles, useScopes, useTokenLifecycle };
1640
1792
  //# sourceMappingURL=index.mjs.map
1641
1793
  //# sourceMappingURL=index.mjs.map