Refactor app instance to Keycloak SSO
This commit is contained in:
@ -58,6 +58,7 @@ const WS_URL = process.env.NEXT_PUBLIC_WS_URL?.trim();
|
||||
const DEFAULT_API_URL = 'http://127.0.0.1:18080';
|
||||
const ACCESS_TOKEN_KEY = 'beaver_access_token';
|
||||
const REFRESH_TOKEN_KEY = 'beaver_refresh_token';
|
||||
const ID_TOKEN_KEY = 'beaver_id_token';
|
||||
const REQUEST_TIMEOUT_MS = 8000;
|
||||
const OUTLOOK_REQUEST_TIMEOUT_MS = 45000;
|
||||
const SKILL_LEARNING_REQUEST_TIMEOUT_MS = 120000;
|
||||
@ -75,31 +76,6 @@ function isBrowser(): boolean {
|
||||
return typeof window !== 'undefined';
|
||||
}
|
||||
|
||||
function normalizeBaseUrl(value?: string | null): string | null {
|
||||
const trimmed = value?.trim();
|
||||
if (!trimmed) return null;
|
||||
return trimmed.replace(/\/+$/, '');
|
||||
}
|
||||
|
||||
export function buildAuthHandoffUrl(response: TokenResponse, nextPath: string): string | null {
|
||||
const targetBaseUrl = normalizeBaseUrl(
|
||||
response.backend_connection?.frontend_base_url ||
|
||||
response.backend_connection?.public_base_url ||
|
||||
response.backend_connection?.api_base_url ||
|
||||
response.local_backend?.public_base_url
|
||||
);
|
||||
if (!targetBaseUrl) return null;
|
||||
const handoffCode = response.handoff_code?.trim();
|
||||
if (!handoffCode) return null;
|
||||
|
||||
const target = new URL('/handoff', targetBaseUrl);
|
||||
target.searchParams.set('code', handoffCode);
|
||||
if (nextPath) {
|
||||
target.searchParams.set('next', nextPath);
|
||||
}
|
||||
return target.toString();
|
||||
}
|
||||
|
||||
function getApiBaseUrl(): string {
|
||||
if (API_URL) return API_URL;
|
||||
if (isBrowser()) return window.location.origin;
|
||||
@ -153,16 +129,31 @@ export function getRefreshToken(): string | null {
|
||||
return localStorage.getItem(REFRESH_TOKEN_KEY);
|
||||
}
|
||||
|
||||
export function setTokens(access: string, refresh: string): void {
|
||||
export function getIdToken(): string | null {
|
||||
if (!isBrowser()) return null;
|
||||
return localStorage.getItem(ID_TOKEN_KEY);
|
||||
}
|
||||
|
||||
export function setTokens(access: string, refresh: string, idToken: string = ''): void {
|
||||
if (!isBrowser()) return;
|
||||
localStorage.setItem(ACCESS_TOKEN_KEY, access);
|
||||
localStorage.setItem(REFRESH_TOKEN_KEY, refresh);
|
||||
if (refresh) {
|
||||
localStorage.setItem(REFRESH_TOKEN_KEY, refresh);
|
||||
} else {
|
||||
localStorage.removeItem(REFRESH_TOKEN_KEY);
|
||||
}
|
||||
if (idToken) {
|
||||
localStorage.setItem(ID_TOKEN_KEY, idToken);
|
||||
} else {
|
||||
localStorage.removeItem(ID_TOKEN_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
export function clearTokens(): void {
|
||||
if (!isBrowser()) return;
|
||||
localStorage.removeItem(ACCESS_TOKEN_KEY);
|
||||
localStorage.removeItem(REFRESH_TOKEN_KEY);
|
||||
localStorage.removeItem(ID_TOKEN_KEY);
|
||||
}
|
||||
|
||||
export function isLoggedIn(): boolean {
|
||||
@ -233,27 +224,6 @@ async function fetchJSON<T>(path: string, options?: FetchJsonOptions): Promise<T
|
||||
// Auth API
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export async function register(username: string, email: string, password: string): Promise<TokenResponse> {
|
||||
return fetchJSON('/api/auth/register', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ username, email, password }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function login(username: string, password: string): Promise<TokenResponse> {
|
||||
return fetchJSON('/api/auth/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ username, password }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function consumeHandoffCode(code: string): Promise<TokenResponse> {
|
||||
return fetchJSON('/api/auth/handoff/consume', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ code }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function logout(): Promise<void> {
|
||||
try {
|
||||
await fetchJSON('/api/auth/logout', { method: 'POST' });
|
||||
|
||||
Reference in New Issue
Block a user