a tool for shared writing and social publishing

use regular route to logout

+33 -39
-9
actions/logout.ts
··· 1 - "use server"; 2 - 3 - import { cookies } from "next/headers"; 4 - import { removeAuthToken } from "src/auth"; 5 - 6 - export async function logout() { 7 - await removeAuthToken(); 8 - (await cookies()).delete("identity"); 9 - }
+28
app/api/auth/logout/route.ts
··· 1 + import { NextRequest } from "next/server"; 2 + export const runtime = "edge"; 3 + export const preferredRegion = []; 4 + 5 + export async function GET(req: NextRequest) { 6 + const host = req.headers.get("host"); 7 + const response = new Response("Logged out successfully", { 8 + status: 200, 9 + headers: { 10 + "Content-Type": "text/plain", 11 + }, 12 + }); 13 + 14 + // Get the base domain from the host 15 + const domain = host?.includes(":") ? host.split(":")[0] : host; 16 + 17 + // Clear the auth_token cookie on both the base domain and the domain with a leading dot 18 + response.headers.append( 19 + "Set-Cookie", 20 + `auth_token=; Path=/; Domain=${domain}; Max-Age=0; HttpOnly; Secure; SameSite=Strict`, 21 + ); 22 + response.headers.append( 23 + "Set-Cookie", 24 + `auth_token=; Path=/; Domain=.${domain}; Max-Age=0; HttpOnly; Secure; SameSite=Strict`, 25 + ); 26 + 27 + return response; 28 + }
+2 -3
app/home/AccountSettings.tsx
··· 2 2 3 3 import { ActionButton } from "components/ActionBar/ActionButton"; 4 4 import { Menu, MenuItem } from "components/Layout"; 5 - import { logout } from "actions/logout"; 6 5 import { mutate } from "swr"; 7 6 import { AccountSmall } from "components/Icons/AccountSmall"; 8 7 import { LogoutSmall } from "components/Icons/LogoutSmall"; ··· 16 15 > 17 16 <MenuItem 18 17 onSelect={async () => { 19 - await logout(); 20 - mutate("identity"); 18 + await fetch("/api/auth/logout"); 19 + mutate("identity", null); 21 20 }} 22 21 > 23 22 <LogoutSmall />
+1 -3
app/home/page.tsx
··· 21 21 22 22 export default async function Home() { 23 23 let cookieStore = await cookies(); 24 - 25 - let auth_token = cookieStore.get("auth_token")?.value; 26 - let auth_res = auth_token ? await getIdentityData() : null; 24 + let auth_res = await getIdentityData(); 27 25 let identity: string | undefined; 28 26 if (auth_res) identity = auth_res.id; 29 27 else identity = cookieStore.get("identity")?.value;
-23
app/login/page.tsx
··· 1 - import { cookies } from "next/headers"; 2 - import LoginForm from "./LoginForm"; 3 - import { logout } from "actions/logout"; 4 - 5 - export default async function LoginPage() { 6 - let cookieStore = await cookies(); 7 - let identity = cookieStore.get("auth_token")?.value; 8 - if (!identity) 9 - return ( 10 - <div> 11 - this is a login page! 12 - <LoginForm /> 13 - </div> 14 - ); 15 - return ( 16 - <div> 17 - identity: {identity} 18 - <form action={logout}> 19 - <button>logout</button> 20 - </form> 21 - </div> 22 - ); 23 - }
+2 -1
src/auth.ts
··· 3 3 4 4 export async function setAuthToken(tokenID: string) { 5 5 let c = await cookies(); 6 + let host = (await headers()).get("host"); 6 7 c.set("auth_token", tokenID, { 7 8 maxAge: 60 * 60 * 24 * 365, 8 9 secure: process.env.NODE_ENV === "production", 9 - domain: isProductionDomain() ? "leaflet.pub" : undefined, 10 + domain: isProductionDomain() ? host! : undefined, 10 11 httpOnly: true, 11 12 sameSite: "lax", 12 13 });