refactor(auth): streamline logout route and update route tree for logout integration
This commit is contained in:
1 parent
2a6adf7af8
commit
a4ece3d344
5 files changed
+69
-19
No files matched your search
+12
-16
@@ -91,22 +91,18 @@ export async function authRoutes(app: FastifyInstance): Promise<void> {
|
||||
},
|
||||
})
|
||||
|
||||
app.post(
|
||||
'/api/v1/auth/logout',
|
||||
{ onRequest: requireAuth },
|
||||
async (request, reply) => {
|
||||
const cookie = request.headers.cookie ?? ''
|
||||
const match = cookie.match(new RegExp(`${REFRESH_COOKIE}=([^;]+)`))
|
||||
if (match?.[1]) {
|
||||
revokeRefreshSession(app.db, match[1])
|
||||
}
|
||||
reply.header(
|
||||
'Set-Cookie',
|
||||
`${REFRESH_COOKIE}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`,
|
||||
)
|
||||
return { ok: true }
|
||||
},
|
||||
)
|
||||
app.post('/api/v1/auth/logout', async (request, reply) => {
|
||||
const cookie = request.headers.cookie ?? ''
|
||||
const match = cookie.match(new RegExp(`${REFRESH_COOKIE}=([^;]+)`))
|
||||
if (match?.[1]) {
|
||||
revokeRefreshSession(app.db, match[1])
|
||||
}
|
||||
reply.header(
|
||||
'Set-Cookie',
|
||||
`${REFRESH_COOKIE}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`,
|
||||
)
|
||||
return { ok: true }
|
||||
})
|
||||
|
||||
app.get(
|
||||
'/api/v1/auth/me',
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
import { Route as rootRouteImport } from './routes/__root'
|
||||
import { Route as IndexRouteImport } from './routes/index'
|
||||
import { Route as AuthRouteImport } from './routes/_auth'
|
||||
import { Route as LogoutRouteImport } from './routes/logout'
|
||||
import { Route as AuthAdminRouteImport } from './routes/_auth.admin'
|
||||
import { Route as AuthAppsRouteImport } from './routes/_auth.apps'
|
||||
import { Route as AuthAdminIndexRouteImport } from './routes/_auth.admin.index'
|
||||
@@ -25,6 +26,11 @@ const AuthRoute = AuthRouteImport.update({
|
||||
id: '/_auth',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const LogoutRoute = LogoutRouteImport.update({
|
||||
id: '/logout',
|
||||
path: '/logout',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const AuthAdminRoute = AuthAdminRouteImport.update({
|
||||
id: '/admin',
|
||||
path: '/admin',
|
||||
@@ -48,6 +54,7 @@ const AuthAdminUsersUserIdRoute = AuthAdminUsersUserIdRouteImport.update({
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexRoute
|
||||
'/logout': typeof LogoutRoute
|
||||
'/admin': typeof AuthAdminRouteWithChildren
|
||||
'/apps': typeof AuthAppsRoute
|
||||
'/admin/': typeof AuthAdminIndexRoute
|
||||
@@ -55,6 +62,7 @@ export interface FileRoutesByFullPath {
|
||||
}
|
||||
export interface FileRoutesByTo {
|
||||
'/': typeof IndexRoute
|
||||
'/logout': typeof LogoutRoute
|
||||
'/apps': typeof AuthAppsRoute
|
||||
'/admin': typeof AuthAdminIndexRoute
|
||||
'/admin/users/$userId': typeof AuthAdminUsersUserIdRoute
|
||||
@@ -63,6 +71,7 @@ export interface FileRoutesById {
|
||||
__root__: typeof rootRouteImport
|
||||
'/': typeof IndexRoute
|
||||
'/_auth': typeof AuthRouteWithChildren
|
||||
'/logout': typeof LogoutRoute
|
||||
'/_auth/admin': typeof AuthAdminRouteWithChildren
|
||||
'/_auth/apps': typeof AuthAppsRoute
|
||||
'/_auth/admin/': typeof AuthAdminIndexRoute
|
||||
@@ -70,13 +79,15 @@ export interface FileRoutesById {
|
||||
}
|
||||
export interface FileRouteTypes {
|
||||
fileRoutesByFullPath: FileRoutesByFullPath
|
||||
fullPaths: '/' | '/admin' | '/apps' | '/admin/' | '/admin/users/$userId'
|
||||
fullPaths:
|
||||
'/' | '/logout' | '/admin' | '/apps' | '/admin/' | '/admin/users/$userId'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to: '/' | '/apps' | '/admin' | '/admin/users/$userId'
|
||||
to: '/' | '/logout' | '/apps' | '/admin' | '/admin/users/$userId'
|
||||
id:
|
||||
| '__root__'
|
||||
| '/'
|
||||
| '/_auth'
|
||||
| '/logout'
|
||||
| '/_auth/admin'
|
||||
| '/_auth/apps'
|
||||
| '/_auth/admin/'
|
||||
@@ -86,6 +97,7 @@ export interface FileRouteTypes {
|
||||
export interface RootRouteChildren {
|
||||
IndexRoute: typeof IndexRoute
|
||||
AuthRoute: typeof AuthRouteWithChildren
|
||||
LogoutRoute: typeof LogoutRoute
|
||||
}
|
||||
|
||||
declare module '@tanstack/react-router' {
|
||||
@@ -104,6 +116,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof AuthRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/logout': {
|
||||
id: '/logout'
|
||||
path: '/logout'
|
||||
fullPath: '/logout'
|
||||
preLoaderRoute: typeof LogoutRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/_auth/admin': {
|
||||
id: '/_auth/admin'
|
||||
path: '/admin'
|
||||
@@ -164,6 +183,7 @@ const AuthRouteWithChildren = AuthRoute._addFileChildren(AuthRouteChildren)
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
IndexRoute: IndexRoute,
|
||||
AuthRoute: AuthRouteWithChildren,
|
||||
LogoutRoute: LogoutRoute,
|
||||
}
|
||||
export const routeTree = rootRouteImport
|
||||
._addFileChildren(rootRouteChildren)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router'
|
||||
import { clearToken } from '@/lib/auth'
|
||||
import { logout } from '@/queries/auth'
|
||||
|
||||
/**
|
||||
* Cross-app SSO logout landing.
|
||||
* Apps (vps-tracker, CFDM, …) redirect here after clearing their local JWT
|
||||
* so the portal session (localStorage + refresh cookie) is revoked —
|
||||
* otherwise `/?return_to=…` would immediately hand a new token back.
|
||||
*/
|
||||
export const Route = createFileRoute('/logout')({
|
||||
beforeLoad: async () => {
|
||||
try {
|
||||
await logout()
|
||||
} catch {
|
||||
/* cookie/token already gone */
|
||||
}
|
||||
clearToken()
|
||||
throw redirect({ to: '/' })
|
||||
},
|
||||
component: () => null,
|
||||
})
|
||||
Reference in new issue
Block a user