Skip to content

Commit eb6eff7

Browse files
Clément VALENTINclaude
andcommitted
fix(auth): resolve login bootloop after httpOnly cookie migration
- client.ts: Skip 401 redirect for /accounts/me and /login page - auth.ts: Return success: false instead of throwing on 401 - Login.tsx: Redirect to dashboard if already authenticated 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 577860e commit eb6eff7

File tree

3 files changed

+25
-6
lines changed

3 files changed

+25
-6
lines changed

apps/web/src/api/auth.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ export const authApi = {
1111
},
1212

1313
getMe: async () => {
14-
return apiClient.get<User>('accounts/me')
14+
try {
15+
return await apiClient.get<User>('accounts/me')
16+
} catch {
17+
// 401 is expected when not logged in - return success: false instead of throwing
18+
return { success: false, data: null, error: { message: 'Not authenticated' } }
19+
}
1520
},
1621

1722
getCredentials: async () => {

apps/web/src/api/client.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,16 @@ class APIClient {
6363
(response) => response,
6464
async (error: AxiosError<APIResponse>) => {
6565
if (error.response?.status === 401) {
66-
// Cookie expired/invalid, redirect to login
67-
// The httpOnly cookie will be cleared by the server on next request
68-
window.location.href = '/login'
66+
// Don't redirect if:
67+
// 1. Already on login page (would cause loop)
68+
// 2. Checking auth status (normal to get 401 if not logged in)
69+
const isLoginPage = window.location.pathname === '/login'
70+
const isAuthCheck = error.config?.url?.includes('accounts/me')
71+
72+
if (!isLoginPage && !isAuthCheck) {
73+
// Session expired during normal use, redirect to login
74+
window.location.href = '/login'
75+
}
6976
}
7077
return Promise.reject(error)
7178
}

apps/web/src/pages/Login.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState } from 'react'
1+
import { useState, useEffect } from 'react'
22
import { Link, useNavigate, useLocation } from 'react-router-dom'
33
import { useAuth } from '@/hooks/useAuth'
44
import { LogIn, Eye, EyeOff } from 'lucide-react'
@@ -11,13 +11,20 @@ export default function Login() {
1111
const [email, setEmail] = useState('')
1212
const [password, setPassword] = useState('')
1313
const [showPassword, setShowPassword] = useState(false)
14-
const { login, loginLoading, loginError } = useAuth()
14+
const { login, loginLoading, loginError, isAuthenticated, isLoading } = useAuth()
1515
const navigate = useNavigate()
1616
const location = useLocation()
1717

1818
// Récupérer l'URL de redirection depuis le state ou utiliser /dashboard par défaut
1919
const from = (location.state as LocationState)?.from || '/dashboard'
2020

21+
// Redirect if already authenticated
22+
useEffect(() => {
23+
if (isAuthenticated && !isLoading) {
24+
navigate(from, { replace: true })
25+
}
26+
}, [isAuthenticated, isLoading, navigate, from])
27+
2128
const handleSubmit = async (e: React.FormEvent) => {
2229
e.preventDefault()
2330
login({ email, password }, {

0 commit comments

Comments
 (0)