UNPKG

@rkosafo/cai.components

Version:

This package is under development and not ready for public use.

146 lines (145 loc) 5.2 kB
import Keycloak from 'keycloak-js'; export function createAuthStore() { return { isLoading: true, isAuthenticated: false, accessToken: '', idToken: '', userInfo: null, authError: '', userIsFound: false }; } export class KeycloakService { keycloak = null; initialized = false; store; fetchUserInfo; onAuthenticated; onLogout; onError; constructor(store, fetchUserInfo, callbacks) { this.store = store; this.fetchUserInfo = fetchUserInfo; this.onAuthenticated = callbacks?.onAuthenticated; this.onLogout = callbacks?.onLogout; this.onError = callbacks?.onError; } async init(config, initOptions = { onLoad: 'login-required', checkLoginIframe: false }) { try { this.keycloak = new Keycloak(config); const authenticated = await this.keycloak.init(initOptions); if (authenticated) { await this.setTokenDetails(this.keycloak.idTokenParsed); } else { this.setTokenDetails(null); } this.initialized = true; this.store.isLoading = false; } catch (error) { this.initialized = false; const errorMessage = error instanceof Error ? error.message : 'Initialization failed'; this.store.authError = errorMessage; this.onError?.(errorMessage); this.store.isLoading = false; } } async setTokenDetails(details) { if (!details) { this.store.isAuthenticated = false; this.store.accessToken = ''; this.store.idToken = ''; this.store.userInfo = null; return; } try { this.store.isAuthenticated = true; this.store.accessToken = this.keycloak.token; this.store.idToken = this.keycloak.idToken; this.store.authError = ''; // Fetch user info using provided function const meRet = await this.fetchUserInfo(this.keycloak.token); let extras = {}; if (meRet.success) { extras = meRet.data; this.store.userIsFound = true; } else { this.store.authError = meRet.message || 'Failed to fetch user info'; this.store.userIsFound = meRet.code === 402; } const userInfo = { id: extras.id, email: extras?.email || details.email, firstName: extras?.firstName || details.given_name, lastName: extras?.lastName || details.family_name, otherNames: '', name: extras?.name || extras?.fullName || details.name, username: extras?.name || extras?.fullName || details.preferred_username, initials: extras?.name || extras?.fullName || details.name ?.split(' ') .filter((x) => x.length > 1) .map((x) => x[0]) .join('') || '', department: extras?.department || '', departmentId: extras?.departmentId, role: extras?.role, roleId: extras?.roleId, tags: extras?.tags ?? [], permissions: extras?.permissions ?? [], type: extras?.type, activeDashboardId: extras?.activeDashboardId, district: extras?.district, phoneNumber: extras?.phoneNumber || '', profileImage: extras?.profileImage || '', status: extras?.status || '' }; this.store.userInfo = userInfo; this.onAuthenticated?.({ keycloakUser: userInfo, queryUser: meRet.data }); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Failed to set token details'; this.store.authError = errorMessage; this.onError?.(errorMessage); } } login() { if (this.initialized && this.keycloak) { this.keycloak.login(); } } async refreshToken() { if (!this.initialized || !this.keycloak) return; try { const refreshed = await this.keycloak.updateToken(30); if (refreshed) { await this.setTokenDetails(this.keycloak.idTokenParsed); } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Token refresh failed'; this.store.authError = errorMessage; this.onError?.(errorMessage); } } logout() { if (!this.initialized || !this.keycloak) return; this.keycloak.logout(); this.store.userInfo = null; this.store.isAuthenticated = false; this.onLogout?.(); } getKeycloakInstance() { return this.keycloak; } isInitialized() { return this.initialized; } }