fix: evitar error CORS al expirar sesión de Authentik
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 28s
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 28s
Cuando la sesión de Authentik expira, los fetch() a /api/music recibían un redirect (302) a la página de login. Por defecto, fetch intenta seguir el redirect pero falla por CORS porque Authentik no tiene el header Access-Control-Allow-Origin. La solución es usar redirect: 'error' en todos los fetch() a endpoints protegidos, lo que convierte los redirects en errores que podemos capturar y manejar apropiadamente. Esto coincide con la estrategia que ya usa useAuth.ts. Cambios: - stores/music.ts: Agregar redirect: 'error' a fetchTracks() y cacheByName() - pages/index.vue: Agregar redirect: 'error' a playTrack() - Mejorar detección de errores de autenticación para incluir 'Failed to fetch' y errores de tipo TypeError relacionados con redirects
This commit is contained in:
@@ -197,7 +197,10 @@ const playTrack = async (track, index) => {
|
|||||||
|
|
||||||
// Fetch and preload entire song into memory
|
// Fetch and preload entire song into memory
|
||||||
const encodedName = encodeURIComponent(track.name)
|
const encodedName = encodeURIComponent(track.name)
|
||||||
const response = await fetch(`/api/music/${encodedName}`)
|
const response = await fetch(`/api/music/${encodedName}`, {
|
||||||
|
credentials: 'include',
|
||||||
|
redirect: 'error' // No seguir redirects de Authentik - convertir en error
|
||||||
|
})
|
||||||
|
|
||||||
// Check for authentication errors
|
// Check for authentication errors
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
@@ -235,8 +238,13 @@ const playTrack = async (track, index) => {
|
|||||||
loadingTrack.value = null
|
loadingTrack.value = null
|
||||||
|
|
||||||
// Don't try fallback streaming if it's an auth error (it will fail too)
|
// Don't try fallback streaming if it's an auth error (it will fail too)
|
||||||
if (error.message && (error.message.includes('401') || error.message.includes('403'))) {
|
// Esto incluye errores de redirect de Authentik
|
||||||
console.warn('[PlayTrack] Skipping fallback due to auth error')
|
if (error.message && (error.message.includes('401') ||
|
||||||
|
error.message.includes('403') ||
|
||||||
|
error.message.includes('Failed to fetch') ||
|
||||||
|
(error.name === 'TypeError' && error.message.includes('redirect')))) {
|
||||||
|
console.warn('[PlayTrack] Skipping fallback due to auth error:', error.message)
|
||||||
|
musicStore.error = error.message || 'Authentication error'
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,17 +44,22 @@ export const useMusicStore = defineStore('music', {
|
|||||||
this.loading = true
|
this.loading = true
|
||||||
this.error = null
|
this.error = null
|
||||||
try {
|
try {
|
||||||
const response = await $fetch<{ tracks: Track[] }>('/api/music')
|
const response = await $fetch<{ tracks: Track[] }>('/api/music', {
|
||||||
|
credentials: 'include',
|
||||||
|
redirect: 'error' // No seguir redirects de Authentik - convertir en error
|
||||||
|
})
|
||||||
this.tracks = response.tracks || []
|
this.tracks = response.tracks || []
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
const errorMsg = e?.message || 'Failed to load tracks'
|
const errorMsg = e?.message || 'Failed to load tracks'
|
||||||
this.error = errorMsg
|
this.error = errorMsg
|
||||||
|
|
||||||
// Check if it's an auth error
|
// Check if it's an auth error (including redirect attempts from Authentik)
|
||||||
if (e?.statusCode === 401 || e?.statusCode === 403 ||
|
if (e?.statusCode === 401 || e?.statusCode === 403 ||
|
||||||
errorMsg.includes('401') || errorMsg.includes('403') ||
|
errorMsg.includes('401') || errorMsg.includes('403') ||
|
||||||
errorMsg.includes('Unauthorized')) {
|
errorMsg.includes('Unauthorized') ||
|
||||||
console.warn('[Music Store] Authentication error detected')
|
errorMsg.includes('Failed to fetch') ||
|
||||||
|
(e?.cause?.name === 'TypeError' && e?.cause?.message?.includes('redirect'))) {
|
||||||
|
console.warn('[Music Store] Authentication error detected:', errorMsg)
|
||||||
// The useAuth composable will be notified via watch in components
|
// The useAuth composable will be notified via watch in components
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -128,7 +133,10 @@ export const useMusicStore = defineStore('music', {
|
|||||||
async cacheByName(name: string, duration?: number): Promise<boolean> {
|
async cacheByName(name: string, duration?: number): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const encodedName = encodeURIComponent(name)
|
const encodedName = encodeURIComponent(name)
|
||||||
const response = await fetch(`/api/music/${encodedName}`)
|
const response = await fetch(`/api/music/${encodedName}`, {
|
||||||
|
credentials: 'include',
|
||||||
|
redirect: 'error' // No seguir redirects de Authentik - convertir en error
|
||||||
|
})
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorMsg = `HTTP ${response.status}`
|
const errorMsg = `HTTP ${response.status}`
|
||||||
@@ -147,9 +155,13 @@ export const useMusicStore = defineStore('music', {
|
|||||||
return true
|
return true
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error('[Music Store] Cache failed:', e)
|
console.error('[Music Store] Cache failed:', e)
|
||||||
// Propagate auth errors
|
|
||||||
if (e?.message?.includes('401') || e?.message?.includes('403')) {
|
// Propagate auth errors (including redirect attempts from Authentik)
|
||||||
this.error = e.message
|
if (e?.message?.includes('401') ||
|
||||||
|
e?.message?.includes('403') ||
|
||||||
|
e?.message?.includes('Failed to fetch') ||
|
||||||
|
(e?.name === 'TypeError' && e?.message?.includes('redirect'))) {
|
||||||
|
this.error = e.message || 'Authentication error'
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user