port-nimara-client-portal/composables/useKeycloak.ts

172 lines
4.7 KiB
TypeScript
Raw Normal View History

import type Keycloak from 'keycloak-js'
export const useKeycloak = () => {
const config = useRuntimeConfig()
const keycloak = ref<Keycloak | null>(null)
const isAuthenticated = ref(false)
const user = ref<any>(null)
const token = ref<string | null>(null)
const isInitialized = ref(false)
Implement Official Keycloak JS Adapter with Proxy-Aware Configuration MAJOR ENHANCEMENT: Complete Keycloak integration with proper HTTPS/proxy handling ## Core Improvements: ### 1. Enhanced Configuration (nuxt.config.ts) - Added proxy trust configuration for nginx environments - Configured baseUrl for production HTTPS enforcement - Added debug mode configuration for development ### 2. Proxy-Aware Keycloak Composable (composables/useKeycloak.ts) - Intelligent base URL detection (production vs development) - Force HTTPS redirect URIs in production environments - Enhanced debugging and logging capabilities - Proper PKCE implementation for security - Automatic token refresh mechanism ### 3. Dual Authentication System - Updated middleware to support both Directus and Keycloak - Enhanced useUnifiedAuth for seamless auth source switching - Maintains backward compatibility with existing Directus users ### 4. OAuth Flow Implementation - Created proper callback handler (pages/auth/callback.vue) - Comprehensive error handling and user feedback - Automatic redirect to dashboard on success ### 5. Enhanced Login Experience (pages/login.vue) - Restored SSO login button with proper error handling - Maintained existing Directus login form - Clear separation between auth methods with visual divider ### 6. Comprehensive Testing Suite (pages/dashboard/keycloak-test.vue) - Real-time configuration display - Authentication status monitoring - Interactive testing tools - Detailed debug logging system ## Technical Solutions: **Proxy Detection**: Automatically detects nginx proxy and uses correct HTTPS URLs **HTTPS Enforcement**: Forces secure redirect URIs in production **Error Handling**: Comprehensive error catching with user-friendly messages **Debug Capabilities**: Enhanced logging for troubleshooting **Security**: Implements PKCE and secure token handling ## Infrastructure Compatibility: - Works with nginx reverse proxy setups - Compatible with Docker container networking - Handles SSL termination at proxy level - Supports both development and production environments This implementation specifically addresses the HTTP/HTTPS redirect URI mismatch that was causing 'unauthorized_client' errors in the proxy environment.
2025-06-14 15:26:26 +02:00
// Get the correct base URL considering proxy setup
const getBaseUrl = () => {
if (process.server) {
// In production, always use the configured HTTPS base URL
return config.public.baseUrl
}
// Client-side: detect if we're behind a proxy
const currentOrigin = window.location.origin
const isProduction = !currentOrigin.includes('localhost') && !currentOrigin.includes('127.0.0.1')
if (isProduction) {
// Force HTTPS in production environments
return config.public.baseUrl
}
// Development: use current origin
return currentOrigin
}
const logDebug = (message: string, data?: any) => {
if (config.public.keycloakDebug) {
console.log(`[KEYCLOAK] ${message}`, data)
}
}
const initKeycloak = async () => {
if (process.server) return false
try {
Implement Official Keycloak JS Adapter with Proxy-Aware Configuration MAJOR ENHANCEMENT: Complete Keycloak integration with proper HTTPS/proxy handling ## Core Improvements: ### 1. Enhanced Configuration (nuxt.config.ts) - Added proxy trust configuration for nginx environments - Configured baseUrl for production HTTPS enforcement - Added debug mode configuration for development ### 2. Proxy-Aware Keycloak Composable (composables/useKeycloak.ts) - Intelligent base URL detection (production vs development) - Force HTTPS redirect URIs in production environments - Enhanced debugging and logging capabilities - Proper PKCE implementation for security - Automatic token refresh mechanism ### 3. Dual Authentication System - Updated middleware to support both Directus and Keycloak - Enhanced useUnifiedAuth for seamless auth source switching - Maintains backward compatibility with existing Directus users ### 4. OAuth Flow Implementation - Created proper callback handler (pages/auth/callback.vue) - Comprehensive error handling and user feedback - Automatic redirect to dashboard on success ### 5. Enhanced Login Experience (pages/login.vue) - Restored SSO login button with proper error handling - Maintained existing Directus login form - Clear separation between auth methods with visual divider ### 6. Comprehensive Testing Suite (pages/dashboard/keycloak-test.vue) - Real-time configuration display - Authentication status monitoring - Interactive testing tools - Detailed debug logging system ## Technical Solutions: **Proxy Detection**: Automatically detects nginx proxy and uses correct HTTPS URLs **HTTPS Enforcement**: Forces secure redirect URIs in production **Error Handling**: Comprehensive error catching with user-friendly messages **Debug Capabilities**: Enhanced logging for troubleshooting **Security**: Implements PKCE and secure token handling ## Infrastructure Compatibility: - Works with nginx reverse proxy setups - Compatible with Docker container networking - Handles SSL termination at proxy level - Supports both development and production environments This implementation specifically addresses the HTTP/HTTPS redirect URI mismatch that was causing 'unauthorized_client' errors in the proxy environment.
2025-06-14 15:26:26 +02:00
const baseUrl = getBaseUrl()
logDebug('Initializing Keycloak', {
baseUrl,
keycloakUrl: config.public.keycloak.url,
realm: config.public.keycloak.realm,
clientId: config.public.keycloak.clientId
})
// 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',
Implement Official Keycloak JS Adapter with Proxy-Aware Configuration MAJOR ENHANCEMENT: Complete Keycloak integration with proper HTTPS/proxy handling ## Core Improvements: ### 1. Enhanced Configuration (nuxt.config.ts) - Added proxy trust configuration for nginx environments - Configured baseUrl for production HTTPS enforcement - Added debug mode configuration for development ### 2. Proxy-Aware Keycloak Composable (composables/useKeycloak.ts) - Intelligent base URL detection (production vs development) - Force HTTPS redirect URIs in production environments - Enhanced debugging and logging capabilities - Proper PKCE implementation for security - Automatic token refresh mechanism ### 3. Dual Authentication System - Updated middleware to support both Directus and Keycloak - Enhanced useUnifiedAuth for seamless auth source switching - Maintains backward compatibility with existing Directus users ### 4. OAuth Flow Implementation - Created proper callback handler (pages/auth/callback.vue) - Comprehensive error handling and user feedback - Automatic redirect to dashboard on success ### 5. Enhanced Login Experience (pages/login.vue) - Restored SSO login button with proper error handling - Maintained existing Directus login form - Clear separation between auth methods with visual divider ### 6. Comprehensive Testing Suite (pages/dashboard/keycloak-test.vue) - Real-time configuration display - Authentication status monitoring - Interactive testing tools - Detailed debug logging system ## Technical Solutions: **Proxy Detection**: Automatically detects nginx proxy and uses correct HTTPS URLs **HTTPS Enforcement**: Forces secure redirect URIs in production **Error Handling**: Comprehensive error catching with user-friendly messages **Debug Capabilities**: Enhanced logging for troubleshooting **Security**: Implements PKCE and secure token handling ## Infrastructure Compatibility: - Works with nginx reverse proxy setups - Compatible with Docker container networking - Handles SSL termination at proxy level - Supports both development and production environments This implementation specifically addresses the HTTP/HTTPS redirect URI mismatch that was causing 'unauthorized_client' errors in the proxy environment.
2025-06-14 15:26:26 +02:00
// Use proper HTTPS redirect URI
redirectUri: `${baseUrl}/auth/callback`,
silentCheckSsoRedirectUri: `${baseUrl}/silent-check-sso.html`,
checkLoginIframe: false, // Disable iframe checks for better compatibility
Implement Official Keycloak JS Adapter with Proxy-Aware Configuration MAJOR ENHANCEMENT: Complete Keycloak integration with proper HTTPS/proxy handling ## Core Improvements: ### 1. Enhanced Configuration (nuxt.config.ts) - Added proxy trust configuration for nginx environments - Configured baseUrl for production HTTPS enforcement - Added debug mode configuration for development ### 2. Proxy-Aware Keycloak Composable (composables/useKeycloak.ts) - Intelligent base URL detection (production vs development) - Force HTTPS redirect URIs in production environments - Enhanced debugging and logging capabilities - Proper PKCE implementation for security - Automatic token refresh mechanism ### 3. Dual Authentication System - Updated middleware to support both Directus and Keycloak - Enhanced useUnifiedAuth for seamless auth source switching - Maintains backward compatibility with existing Directus users ### 4. OAuth Flow Implementation - Created proper callback handler (pages/auth/callback.vue) - Comprehensive error handling and user feedback - Automatic redirect to dashboard on success ### 5. Enhanced Login Experience (pages/login.vue) - Restored SSO login button with proper error handling - Maintained existing Directus login form - Clear separation between auth methods with visual divider ### 6. Comprehensive Testing Suite (pages/dashboard/keycloak-test.vue) - Real-time configuration display - Authentication status monitoring - Interactive testing tools - Detailed debug logging system ## Technical Solutions: **Proxy Detection**: Automatically detects nginx proxy and uses correct HTTPS URLs **HTTPS Enforcement**: Forces secure redirect URIs in production **Error Handling**: Comprehensive error catching with user-friendly messages **Debug Capabilities**: Enhanced logging for troubleshooting **Security**: Implements PKCE and secure token handling ## Infrastructure Compatibility: - Works with nginx reverse proxy setups - Compatible with Docker container networking - Handles SSL termination at proxy level - Supports both development and production environments This implementation specifically addresses the HTTP/HTTPS redirect URI mismatch that was causing 'unauthorized_client' errors in the proxy environment.
2025-06-14 15:26:26 +02:00
pkceMethod: 'S256', // Use PKCE for better security
})
logDebug('Keycloak initialization result', {
authenticated,
redirectUri: `${baseUrl}/auth/callback`
})
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,
}
}