refactor: replace hand-rolled OIDC with @logto/react SDK
All checks were successful
CI / build (push) Successful in 38s
CI / docker (push) Successful in 48s

The hand-rolled OIDC flow (manual PKCE, token exchange, URL
construction) was fragile and accumulated multiple bugs. Replaced
with the official @logto/react SDK which handles PKCE, token
exchange, storage, and refresh automatically.

- Add @logto/react SDK dependency
- Add LogtoProvider with runtime config in main.tsx
- Add TokenSync component bridging SDK tokens to API client
- Add useAuth hook replacing Zustand auth store
- Simplify LoginPage to signIn(), CallbackPage to useHandleSignInCallback()
- Delete pkce.ts and auth-store.ts (replaced by SDK)
- Fix react-router-dom → react-router imports in page files
- All 17 React Query hooks unchanged (token provider pattern)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-05 01:17:47 +02:00
parent 84667170f1
commit 0843a33383
19 changed files with 320 additions and 224 deletions

View File

@@ -1,9 +1,19 @@
import { useAuthStore } from '../auth/auth-store';
const API_BASE = '/api';
let tokenProvider: (() => Promise<string | undefined>) | null = null;
export function setTokenProvider(provider: (() => Promise<string | undefined>) | null) {
tokenProvider = provider;
}
let logoutHandler: (() => void) | null = null;
export function setLogoutHandler(handler: (() => void) | null) {
logoutHandler = handler;
}
async function apiFetch<T>(path: string, options: RequestInit = {}): Promise<T> {
const token = useAuthStore.getState().accessToken;
const token = tokenProvider ? await tokenProvider() : null;
const headers: Record<string, string> = {
...(options.headers as Record<string, string> || {}),
};
@@ -17,7 +27,7 @@ async function apiFetch<T>(path: string, options: RequestInit = {}): Promise<T>
const response = await fetch(`${API_BASE}${path}`, { ...options, headers });
if (response.status === 401) {
useAuthStore.getState().logout();
if (logoutHandler) logoutHandler();
window.location.href = '/login';
throw new Error('Unauthorized');
}