diff --git a/apps/web/src/app/(app)/components/SidebarUserFooter.tsx b/apps/web/src/app/(app)/components/SidebarUserFooter.tsx index 916b223423..254691b45d 100644 --- a/apps/web/src/app/(app)/components/SidebarUserFooter.tsx +++ b/apps/web/src/app/(app)/components/SidebarUserFooter.tsx @@ -11,7 +11,6 @@ import { } from '@/components/ui/dropdown-menu'; import { Avatar, AvatarImage, AvatarFallback } from '@radix-ui/react-avatar'; import { BookOpen, ChevronsUpDown, Download, FileDown, LogOut, UserCog } from 'lucide-react'; -import { signOut } from 'next-auth/react'; import { useRouter } from 'next/navigation'; type User = { @@ -37,12 +36,8 @@ function getUserInitials(name: string) { export default function SidebarUserFooter({ user, isLoading }: SidebarUserFooterProps) { const router = useRouter(); - const handleLogout = async () => { - try { - await fetch('/api/auth/revoke-web-session', { method: 'POST' }); - } finally { - await signOut({ callbackUrl: '/' }); - } + const handleLogout = () => { + router.push('/users/sign_out?callbackUrl=%2F'); }; return ( diff --git a/apps/web/src/app/device-auth/DeviceAuthClient.tsx b/apps/web/src/app/device-auth/DeviceAuthClient.tsx index 86240dfcc9..39e310a0e3 100644 --- a/apps/web/src/app/device-auth/DeviceAuthClient.tsx +++ b/apps/web/src/app/device-auth/DeviceAuthClient.tsx @@ -1,7 +1,6 @@ 'use client'; import { useState } from 'react'; -import { signOut } from 'next-auth/react'; import { z } from 'zod'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; @@ -55,14 +54,10 @@ export function DeviceAuthClient({ code, viewerToken, isAppMode, user }: DeviceA const shellClassName = getDeviceAuthShellClassName(isAppMode); const outcomeHeaderClassName = getDeviceAuthOutcomeHeaderClassName(); - const handleSignOut = async () => { + const handleSignOut = () => { setIsSigningOut(true); - - try { - await fetch('/api/auth/revoke-web-session', { method: 'POST' }); - } finally { - await signOut({ callbackUrl: getDeviceAuthSignInUrl(code, { app: isAppMode }) }); - } + const callbackUrl = getDeviceAuthSignInUrl(code, { app: isAppMode }); + window.location.assign(`/users/sign_out?callbackUrl=${encodeURIComponent(callbackUrl)}`); }; const redirectToSignIn = () => { diff --git a/apps/web/src/app/users/sign_out/page.tsx b/apps/web/src/app/users/sign_out/page.tsx new file mode 100644 index 0000000000..a036b887f6 --- /dev/null +++ b/apps/web/src/app/users/sign_out/page.tsx @@ -0,0 +1,66 @@ +'use client'; + +import { useRouter, useSearchParams } from 'next/navigation'; +import { signOut } from 'next-auth/react'; +import { useState } from 'react'; + +import { AuthPageLayout } from '@/components/auth/AuthPageLayout'; +import { Button } from '@/components/ui/button'; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from '@/components/ui/card'; + +function safeCallbackUrl(raw: string | null): string { + if (!raw) return '/profile'; + if (!raw.startsWith('/') || raw.startsWith('//')) return '/profile'; + return raw; +} + +export default function SignOutPage() { + const router = useRouter(); + const params = useSearchParams(); + const callbackUrl = safeCallbackUrl(params.get('callbackUrl')); + const [submitting, setSubmitting] = useState(false); + + const handleSignOut = async () => { + if (submitting) return; + setSubmitting(true); + try { + await fetch('/api/auth/revoke-web-session', { method: 'POST' }); + } finally { + await signOut({ callbackUrl }); + } + }; + + return ( + + + + Sign out of Kilo? + + You'll need to sign in again to access your account. + + + + + + + + + + ); +} \ No newline at end of file diff --git a/apps/web/src/components/dev/actions.ts b/apps/web/src/components/dev/actions.ts index 24fab1e94a..be68f5276d 100644 --- a/apps/web/src/components/dev/actions.ts +++ b/apps/web/src/components/dev/actions.ts @@ -33,5 +33,5 @@ export async function nuke() { throw new Error('Failed to nuke account. Please try again later.'); } - redirect('/api/auth/signout?callbackUrl=/profile'); + redirect('/users/sign_out?callbackUrl=/profile'); } diff --git a/apps/web/src/lib/user/server.ts b/apps/web/src/lib/user/server.ts index b0d5374211..b645685206 100644 --- a/apps/web/src/lib/user/server.ts +++ b/apps/web/src/lib/user/server.ts @@ -1058,6 +1058,7 @@ export const authOptions: NextAuthOptions = { pages: { signIn: '/users/sign_in', error: '/users/sign_in', + signOut: '/users/sign_out', }, debug: !!getEnvVariable('DEBUG_AUTH'), };