feat(frontend): implement center auth session flow with route guard

This commit is contained in:
root
2026-05-12 15:09:06 +00:00
parent 6219fbbcfe
commit d718128f89
12 changed files with 269 additions and 4 deletions

52
src/auth/AuthContext.tsx Normal file
View File

@@ -0,0 +1,52 @@
import { useMemo, useState } from 'react'
import type { PropsWithChildren } from 'react'
import { clearAuthSession, getAuthSession, isAccessTokenStale, setAuthSession } from '../lib/auth-storage'
import type { AuthSession } from '../lib/auth-storage'
import { loginCenter, logoutCenter, refreshCenter } from '../lib/center-auth-client'
import { AuthContext } from './auth-context'
import type { AuthContextValue } from './auth-context'
export function AuthProvider({ children }: PropsWithChildren) {
const [session, setSession] = useState<AuthSession | null>(getAuthSession())
const value = useMemo<AuthContextValue>(
() => ({
session,
isAuthed: !!session,
login: async (email: string, password: string) => {
const next = await loginCenter({ email, password })
setAuthSession(next)
setSession(next)
},
logout: async () => {
if (session?.refreshToken) {
try {
await logoutCenter(session.refreshToken)
} catch {
// noop
}
}
clearAuthSession()
setSession(null)
},
ensureFreshToken: async () => {
if (!session) return null
if (!isAccessTokenStale(session.accessToken)) return session.accessToken
const refreshed = await refreshCenter(session.refreshToken)
const next: AuthSession = {
...session,
accessToken: refreshed.accessToken,
refreshToken: refreshed.refreshToken,
tokenType: refreshed.tokenType,
}
setAuthSession(next)
setSession(next)
return next.accessToken
},
}),
[session],
)
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
}