@tidecloak/react
Version:
TideCloak client-side React SDK
146 lines (145 loc) • 5.75 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import React from "react";
import { IAMService } from '@tidecloak/js';
const TideCloakContext = React.createContext(undefined);
export function TideCloakContextProvider({ config, children }) {
const [isInitializing, setIsInitializing] = React.useState(true);
const [initError, setInitError] = React.useState(null);
const [authenticated, setAuthenticated] = React.useState(false);
const [sessionExpired, setSessionExpired] = React.useState(false);
const [isRefreshing, setIsRefreshing] = React.useState(false);
const [token, setToken] = React.useState(null);
const [idToken, setIdToken] = React.useState(null);
const [tokenExp, setTokenExp] = React.useState(null);
const [baseURL, setBaseURL] = React.useState("");
const [reloadKey, setReloadKey] = React.useState(0);
React.useEffect(() => {
let mounted = true;
const updateAuthState = async (eventName) => {
console.debug(`[TideCloak Provider] Updating auth state. Triggered by the ${eventName} event`);
if (!mounted)
return;
const logged = IAMService.isLoggedIn();
setAuthenticated(logged);
if (logged) {
setSessionExpired(false);
try {
const t = await IAMService.getToken();
const idt = IAMService.getIDToken();
setToken(t);
setIdToken(idt);
setTokenExp(IAMService.getTokenExp());
}
catch (e) {
console.error("[TideCloak Provider] Failed to update auth state", e);
}
}
else {
setSessionExpired(true);
setToken(null);
setIdToken(null);
}
};
const onInitError = (err) => {
if (mounted) {
setInitError(err);
setIsInitializing(false);
}
};
const onTokenExpired = async () => {
if (!mounted)
return;
console.debug("[TideCloak Provider] Token expired, attempting refresh...");
setSessionExpired(true);
try {
await IAMService.updateIAMToken();
}
catch (refreshError) {
console.error("[TideCloak Provider] Failed to refresh token:", refreshError);
}
};
IAMService
.on('authSuccess', updateAuthState)
.on('authError', updateAuthState)
.on('authRefreshSuccess', updateAuthState)
.on('authRefreshError', updateAuthState)
.on('logout', updateAuthState)
.on('tokenExpired', onTokenExpired)
.on('initError', onInitError);
setIsInitializing(true);
(async () => {
try {
const loaded = await IAMService.loadConfig(config);
;
if (!loaded)
throw new Error("Invalid config");
setBaseURL(loaded['auth-server-url'].replace(/\/+$/, ''));
await IAMService.initIAM(config, updateAuthState);
if (!mounted)
return;
setIsInitializing(false);
}
catch (err) {
onInitError(err);
}
})();
return () => {
mounted = false;
IAMService.off('ready', updateAuthState)
.off('authSuccess', updateAuthState)
.off('authError', updateAuthState)
.off('authRefreshSuccess', updateAuthState)
.off('authRefreshError', updateAuthState)
.off('logout', updateAuthState)
.off('tokenExpired', onTokenExpired)
.off('initError', onInitError);
};
}, [config, reloadKey]);
if (isInitializing)
return null;
return (_jsx(TideCloakContext.Provider, { value: {
isInitializing,
initError,
authenticated,
sessionExpired,
isRefreshing,
token,
idToken,
tokenExp,
baseURL,
getConfig: () => IAMService.getConfig(),
reload: () => setReloadKey(k => k + 1),
login: () => IAMService.doLogin(),
logout: () => IAMService.doLogout(),
refreshToken: async () => {
setIsRefreshing(true);
try {
return await IAMService.updateIAMToken();
}
finally {
setIsRefreshing(false);
}
},
forceRefreshToken: async () => {
setIsRefreshing(true);
try {
return await IAMService.forceUpdateToken();
}
finally {
setIsRefreshing(false);
}
},
hasRealmRole: (role) => IAMService.hasRealmRole(role),
hasClientRole: (role, resource) => IAMService.hasClientRole(role, resource),
getValueFromToken: (key) => IAMService.getValueFromToken(key),
getValueFromIdToken: (key) => IAMService.getValueFromIDToken(key),
doEncrypt: async (data) => await IAMService.doEncrypt(data),
doDecrypt: async (data) => await IAMService.doDecrypt(data)
}, children: children }));
}
export function useTideCloakContext() {
const ctx = React.useContext(TideCloakContext);
if (!ctx)
throw new Error("useTideCloakContext must be used within <TideCloakContextProvider>");
return ctx;
}