import type Keycloak from 'keycloak-js' export const useKeycloak = () => { const config = useRuntimeConfig() const keycloak = ref(null) const isAuthenticated = ref(false) const user = ref(null) const token = ref(null) const isInitialized = ref(false) const initKeycloak = async () => { if (process.server) return try { // Dynamically import keycloak-js const KeycloakModule = await import('keycloak-js') const KeycloakConstructor = KeycloakModule.default keycloak.value = new KeycloakConstructor({ url: config.public.keycloak.url, realm: config.public.keycloak.realm, clientId: config.public.keycloak.clientId, }) const authenticated = await keycloak.value.init({ onLoad: 'check-sso', silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html', checkLoginIframe: false, // Disable iframe checks for better compatibility }) isAuthenticated.value = authenticated isInitialized.value = true if (authenticated && keycloak.value.token) { token.value = keycloak.value.token || null user.value = { id: keycloak.value.subject, username: keycloak.value.tokenParsed?.preferred_username, email: keycloak.value.tokenParsed?.email, firstName: keycloak.value.tokenParsed?.given_name, lastName: keycloak.value.tokenParsed?.family_name, fullName: keycloak.value.tokenParsed?.name, roles: keycloak.value.tokenParsed?.realm_access?.roles || [], } // Set up token refresh keycloak.value.onTokenExpired = () => { keycloak.value?.updateToken(30).then((refreshed) => { if (refreshed) { token.value = keycloak.value?.token || null console.log('Token refreshed') } else { console.log('Token still valid') } }).catch(() => { console.log('Failed to refresh token') logout() }) } } return authenticated } catch (error) { console.error('Failed to initialize Keycloak:', error) isInitialized.value = true return false } } const login = async () => { if (!keycloak.value) { await initKeycloak() } if (keycloak.value) { try { await keycloak.value.login({ redirectUri: window.location.origin + '/dashboard' }) } catch (error) { console.error('Login failed:', error) throw error } } } const logout = async () => { if (keycloak.value) { try { await keycloak.value.logout({ redirectUri: window.location.origin }) } catch (error) { console.error('Logout failed:', error) } } // Clear local state isAuthenticated.value = false user.value = null token.value = null } const getToken = () => { return token.value } const hasRole = (role: string) => { return user.value?.roles?.includes(role) || false } const hasAnyRole = (roles: string[]) => { return roles.some(role => hasRole(role)) } return { keycloak: readonly(keycloak), isAuthenticated: readonly(isAuthenticated), user: readonly(user), token: readonly(token), isInitialized: readonly(isInitialized), initKeycloak, login, logout, getToken, hasRole, hasAnyRole, } }