feat(frontend): require center API key on login/auth calls
This commit is contained in:
@@ -13,15 +13,15 @@ export function AuthProvider({ children }: PropsWithChildren) {
|
||||
() => ({
|
||||
session,
|
||||
isAuthed: !!session,
|
||||
login: async (centerApiBase: string, email: string, password: string) => {
|
||||
const next = await loginCenter(centerApiBase, { email, password })
|
||||
login: async (centerApiBase: string, centerApiKey: string, email: string, password: string) => {
|
||||
const next = await loginCenter(centerApiBase, centerApiKey, { email, password })
|
||||
setAuthSession(next)
|
||||
setSession(next)
|
||||
},
|
||||
logout: async () => {
|
||||
if (session?.refreshToken) {
|
||||
try {
|
||||
await logoutCenter(session.centerApiBase, session.refreshToken)
|
||||
await logoutCenter(session.centerApiBase, session.centerApiKey, session.refreshToken)
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
@@ -33,7 +33,7 @@ export function AuthProvider({ children }: PropsWithChildren) {
|
||||
if (!session) return null
|
||||
if (!isAccessTokenStale(session.accessToken)) return session.accessToken
|
||||
|
||||
const refreshed = await refreshCenter(session.centerApiBase, session.refreshToken)
|
||||
const refreshed = await refreshCenter(session.centerApiBase, session.centerApiKey, session.refreshToken)
|
||||
const next: AuthSession = {
|
||||
...session,
|
||||
accessToken: refreshed.accessToken,
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { AuthSession } from '../lib/auth-storage'
|
||||
export type AuthContextValue = {
|
||||
session: AuthSession | null
|
||||
isAuthed: boolean
|
||||
login: (centerApiBase: string, email: string, password: string) => Promise<void>
|
||||
login: (centerApiBase: string, centerApiKey: string, email: string, password: string) => Promise<void>
|
||||
logout: () => Promise<void>
|
||||
ensureFreshToken: () => Promise<string | null>
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export type AuthSession = {
|
||||
centerApiBase: string
|
||||
centerApiKey: string
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
tokenType: string
|
||||
|
||||
@@ -19,7 +19,7 @@ type RefreshResponse = {
|
||||
tokenType: string
|
||||
}
|
||||
|
||||
function centerClient(centerApiBase: string) {
|
||||
function centerClient(centerApiBase: string, centerApiKey: string) {
|
||||
const client = axios.create({
|
||||
baseURL: centerApiBase,
|
||||
timeout: 10000,
|
||||
@@ -27,6 +27,7 @@ function centerClient(centerApiBase: string) {
|
||||
|
||||
client.interceptors.request.use((request) => {
|
||||
const requestId = crypto.randomUUID()
|
||||
request.headers['x-api-key'] = centerApiKey
|
||||
request.headers['x-request-id'] = requestId
|
||||
request.headers['x-client-name'] = 'fabric-frontend'
|
||||
return request
|
||||
@@ -35,16 +36,16 @@ function centerClient(centerApiBase: string) {
|
||||
return client
|
||||
}
|
||||
|
||||
export async function loginCenter(centerApiBase: string, payload: LoginPayload): Promise<AuthSession> {
|
||||
const res = await centerClient(centerApiBase).post<LoginResponse>('/auth/login', payload)
|
||||
return { ...res.data, centerApiBase }
|
||||
export async function loginCenter(centerApiBase: string, centerApiKey: string, payload: LoginPayload): Promise<AuthSession> {
|
||||
const res = await centerClient(centerApiBase, centerApiKey).post<LoginResponse>('/auth/login', payload)
|
||||
return { ...res.data, centerApiBase, centerApiKey }
|
||||
}
|
||||
|
||||
export async function refreshCenter(centerApiBase: string, refreshToken: string): Promise<RefreshResponse> {
|
||||
const res = await centerClient(centerApiBase).post<RefreshResponse>('/auth/refresh', { refreshToken })
|
||||
export async function refreshCenter(centerApiBase: string, centerApiKey: string, refreshToken: string): Promise<RefreshResponse> {
|
||||
const res = await centerClient(centerApiBase, centerApiKey).post<RefreshResponse>('/auth/refresh', { refreshToken })
|
||||
return res.data
|
||||
}
|
||||
|
||||
export async function logoutCenter(centerApiBase: string, refreshToken: string): Promise<void> {
|
||||
await centerClient(centerApiBase).post('/auth/logout', { refreshToken })
|
||||
export async function logoutCenter(centerApiBase: string, centerApiKey: string, refreshToken: string): Promise<void> {
|
||||
await centerClient(centerApiBase, centerApiKey).post('/auth/logout', { refreshToken })
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export default function LoginPage() {
|
||||
const navigate = useNavigate()
|
||||
const { login, isAuthed, session } = useAuth()
|
||||
const [centerApiBase, setCenterApiBase] = useState('http://localhost:7001/api')
|
||||
const [centerApiKey, setCenterApiKey] = useState('')
|
||||
const [email, setEmail] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const [error, setError] = useState('')
|
||||
@@ -15,7 +16,7 @@ export default function LoginPage() {
|
||||
e.preventDefault()
|
||||
setError('')
|
||||
try {
|
||||
await login(centerApiBase.trim(), email, password)
|
||||
await login(centerApiBase.trim(), centerApiKey.trim(), email, password)
|
||||
navigate('/workspace')
|
||||
} catch {
|
||||
setError('登录失败,请检查账号密码')
|
||||
@@ -32,6 +33,11 @@ export default function LoginPage() {
|
||||
onChange={(e) => setCenterApiBase(e.target.value)}
|
||||
placeholder="Center API Base (e.g. http://localhost:7001/api)"
|
||||
/>
|
||||
<input
|
||||
value={centerApiKey}
|
||||
onChange={(e) => setCenterApiKey(e.target.value)}
|
||||
placeholder="Center API Key"
|
||||
/>
|
||||
<input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" type="email" />
|
||||
<input
|
||||
value={password}
|
||||
|
||||
Reference in New Issue
Block a user