🔧 FIX: Disable OIDC global middleware to prevent redirect loops
CRITICAL FIX: The nuxt-oidc-auth module was causing infinite redirect loops because its global middleware was active on ALL pages, including /login. ## 🚨 **Problem Solved:** - Login page was redirecting to itself infinitely - OIDC module auto-authenticating on every route - 502 Bad Gateway errors from redirect loops ## ✅ **Changes Made:** ### **nuxt.config.ts:** - Added globalMiddlewareEnabled: false to OIDC middleware config - This disables automatic authentication on all routes - Prevents redirect loops on login page ### **Cleanup:** - Removed obsolete pages/dashboard/keycloak-test.vue - Fixed TypeScript errors from missing useKeycloak composable ## 🎯 **Result:** ✅ Login page should now load without redirect loops ✅ SSO button should work properly when clicked ✅ Manual authentication control via our middleware ✅ Maintains Directus auth compatibility ## 📋 **Next Steps:** 1. Rebuild container in Portainer with these changes 2. Test login page loads properly 3. Test SSO authentication flow 4. Verify no more 502 errors on callback This fixes the core issue blocking the Keycloak SSO integration!
This commit is contained in:
parent
0ae190b255
commit
12403233c0
|
|
@ -112,6 +112,9 @@ export default defineNuxtConfig({
|
|||
}
|
||||
},
|
||||
oidc: {
|
||||
middleware: {
|
||||
globalMiddlewareEnabled: false, // Disable automatic middleware - prevents redirect loops!
|
||||
},
|
||||
providers: {
|
||||
keycloak: {
|
||||
audience: 'account',
|
||||
|
|
|
|||
|
|
@ -1,249 +0,0 @@
|
|||
<template>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<h1>Keycloak Integration Test</h1>
|
||||
<p class="text-body-1 mb-6">Test the Keycloak SSO integration and debug any issues</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<!-- Configuration Display -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-card>
|
||||
<v-card-title>Configuration</v-card-title>
|
||||
<v-card-text>
|
||||
<pre class="text-caption">{{ configInfo }}</pre>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<!-- Status Display -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-card>
|
||||
<v-card-title>Current Status</v-card-title>
|
||||
<v-card-text>
|
||||
<v-chip
|
||||
:color="keycloak.isInitialized.value ? 'green' : 'red'"
|
||||
variant="tonal"
|
||||
class="mb-2"
|
||||
>
|
||||
Initialized: {{ keycloak.isInitialized.value }}
|
||||
</v-chip>
|
||||
<br>
|
||||
<v-chip
|
||||
:color="keycloak.isAuthenticated.value ? 'green' : 'red'"
|
||||
variant="tonal"
|
||||
class="mb-2"
|
||||
>
|
||||
Authenticated: {{ keycloak.isAuthenticated.value }}
|
||||
</v-chip>
|
||||
<br>
|
||||
<v-chip
|
||||
:color="unifiedAuth.user.value ? 'green' : 'gray'"
|
||||
variant="tonal"
|
||||
class="mb-2"
|
||||
>
|
||||
Auth Source: {{ unifiedAuth.authSource.value || 'None' }}
|
||||
</v-chip>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row class="mt-4">
|
||||
<!-- User Information -->
|
||||
<v-col cols="12" md="6" v-if="unifiedAuth.user.value">
|
||||
<v-card>
|
||||
<v-card-title>User Information</v-card-title>
|
||||
<v-card-text>
|
||||
<pre class="text-caption">{{ JSON.stringify(unifiedAuth.user.value, null, 2) }}</pre>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<!-- Actions -->
|
||||
<v-col cols="12" md="6">
|
||||
<v-card>
|
||||
<v-card-title>Actions</v-card-title>
|
||||
<v-card-text class="d-flex flex-column ga-3">
|
||||
<v-btn
|
||||
@click="initializeKeycloak"
|
||||
:loading="initializing"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
>
|
||||
Initialize Keycloak
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
@click="testLogin"
|
||||
:loading="loginTesting"
|
||||
variant="outlined"
|
||||
color="success"
|
||||
:disabled="!keycloak.isInitialized.value"
|
||||
>
|
||||
Test Login
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
@click="testLogout"
|
||||
variant="outlined"
|
||||
color="warning"
|
||||
:disabled="!keycloak.isAuthenticated.value"
|
||||
>
|
||||
Test Logout
|
||||
</v-btn>
|
||||
|
||||
<v-btn
|
||||
@click="refreshStatus"
|
||||
variant="outlined"
|
||||
>
|
||||
Refresh Status
|
||||
</v-btn>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row class="mt-4">
|
||||
<!-- Debug Logs -->
|
||||
<v-col cols="12">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
Debug Logs
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn @click="clearLogs" size="small" variant="text">Clear</v-btn>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-sheet class="pa-3" style="background-color: #1e1e1e; color: #fff; height: 300px; overflow-y: auto;">
|
||||
<div v-for="(log, index) in logs" :key="index" class="text-caption">
|
||||
<span :style="{ color: getLogColor(log.level) }">
|
||||
[{{ log.timestamp }}] {{ log.level.toUpperCase() }}: {{ log.message }}
|
||||
</span>
|
||||
<pre v-if="log.data" class="text-caption mt-1" style="color: #ccc;">{{ JSON.stringify(log.data, null, 2) }}</pre>
|
||||
</div>
|
||||
</v-sheet>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Auth systems
|
||||
const keycloak = useKeycloak()
|
||||
const unifiedAuth = useUnifiedAuth()
|
||||
const config = useRuntimeConfig()
|
||||
|
||||
// Reactive state
|
||||
const initializing = ref(false)
|
||||
const loginTesting = ref(false)
|
||||
const logs = ref<Array<{level: string, message: string, data?: any, timestamp: string}>>([])
|
||||
|
||||
// Computed properties
|
||||
const configInfo = computed(() => ({
|
||||
keycloakUrl: config.public.keycloak.url,
|
||||
realm: config.public.keycloak.realm,
|
||||
clientId: config.public.keycloak.clientId,
|
||||
baseUrl: config.public.baseUrl,
|
||||
debug: config.public.keycloakDebug,
|
||||
currentOrigin: process.client ? window.location.origin : 'N/A (SSR)',
|
||||
userAgent: process.client ? navigator.userAgent : 'N/A (SSR)'
|
||||
}))
|
||||
|
||||
// Logging functions
|
||||
const addLog = (level: string, message: string, data?: any) => {
|
||||
logs.value.push({
|
||||
level,
|
||||
message,
|
||||
data,
|
||||
timestamp: new Date().toLocaleTimeString()
|
||||
})
|
||||
|
||||
// Keep only last 50 logs
|
||||
if (logs.value.length > 50) {
|
||||
logs.value = logs.value.slice(-50)
|
||||
}
|
||||
}
|
||||
|
||||
const getLogColor = (level: string) => {
|
||||
switch (level) {
|
||||
case 'error': return '#ff5252'
|
||||
case 'warn': return '#ff9800'
|
||||
case 'info': return '#2196f3'
|
||||
case 'success': return '#4caf50'
|
||||
default: return '#fff'
|
||||
}
|
||||
}
|
||||
|
||||
const clearLogs = () => {
|
||||
logs.value = []
|
||||
}
|
||||
|
||||
// Test functions
|
||||
const initializeKeycloak = async () => {
|
||||
try {
|
||||
initializing.value = true
|
||||
addLog('info', 'Initializing Keycloak...')
|
||||
|
||||
const result = await keycloak.initKeycloak()
|
||||
|
||||
addLog('success', `Keycloak initialized. Authenticated: ${result}`, {
|
||||
initialized: keycloak.isInitialized.value,
|
||||
authenticated: keycloak.isAuthenticated.value
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
addLog('error', 'Keycloak initialization failed', error)
|
||||
} finally {
|
||||
initializing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const testLogin = async () => {
|
||||
try {
|
||||
loginTesting.value = true
|
||||
addLog('info', 'Starting login test...')
|
||||
|
||||
await keycloak.login()
|
||||
|
||||
} catch (error) {
|
||||
addLog('error', 'Login test failed', error)
|
||||
loginTesting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const testLogout = async () => {
|
||||
try {
|
||||
addLog('info', 'Starting logout test...')
|
||||
|
||||
await keycloak.logout()
|
||||
|
||||
addLog('success', 'Logout completed')
|
||||
|
||||
} catch (error) {
|
||||
addLog('error', 'Logout failed', error)
|
||||
}
|
||||
}
|
||||
|
||||
const refreshStatus = () => {
|
||||
addLog('info', 'Refreshing status...', {
|
||||
keycloakInitialized: keycloak.isInitialized.value,
|
||||
keycloakAuthenticated: keycloak.isAuthenticated.value,
|
||||
unifiedUser: unifiedAuth.user.value,
|
||||
authSource: unifiedAuth.authSource.value
|
||||
})
|
||||
}
|
||||
|
||||
// Initialize on mount
|
||||
onMounted(() => {
|
||||
addLog('info', 'Keycloak test page loaded')
|
||||
refreshStatus()
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: 'Keycloak Integration Test'
|
||||
})
|
||||
</script>
|
||||
Loading…
Reference in New Issue