import { useEffect, useState } from 'react'; import { get } from '../lib/api'; import { RefreshCw } from '../components/Icons'; interface IdentityServerSettings { issuer: string; discoveryUrl: string; tokenEndpoint: string; userInfoEndpoint: string; client: { clientId: string; clientName: string; allowedGrantTypes: string[]; allowedScopes: string[]; allowOfflineAccess: boolean; accessTokenLifetime: number; absoluteRefreshTokenLifetime: number; slidingRefreshTokenLifetime: number; refreshTokenUsage: string; refreshTokenExpiration: string; }; signing: { certificateSource: string; loadedFromBase64: boolean; certificatePath: string; certificateExists: boolean; thumbprint: string; notBeforeUtc: string; notAfterUtc: string; algorithm: string; }; license: { configured: boolean; }; persistedGrants: { store: string; warning: string; }; legacyCompatibility: { injectsClientId: boolean; injectsDefaultScopes: boolean; addsLegacyTokenAliases: boolean; acceptsLegacyJwtSigningKey: boolean; }; } export function IdentityServer() { const [settings, setSettings] = useState(null); const [err, setErr] = useState(null); const [busy, setBusy] = useState(false); const load = async () => { setBusy(true); try { const data = await get('/identityserver'); setSettings(data); setErr(null); } catch (e) { setErr((e as Error).message); } finally { setBusy(false); } }; useEffect(() => { void load(); }, []); return (
{err && (
{err}
)} {!settings && !err && (
Loading...
)} {settings && (

IdentityServer

{settings.issuer}

Client

{settings.client.clientId}

Offline access {settings.client.allowOfflineAccess ? 'on' : 'off'}

Legacy compatibility

Signing certificate

{!settings.signing.loadedFromBase64 && ( )}

Operational store

Persisted grants {settings.persistedGrants.store}

{settings.persistedGrants.warning}

)}
); } function Endpoint({ label, value }: { label: string; value: string }) { return (
{label}
{value}
); } function ChipList({ title, values }: { title: string; values: string[] }) { return (

{title}

{values.map((value) => ( {value} ))}
); } function Metric({ label, value }: { label: string; value: string }) { return (
{label}
{value}
); } function Compatibility({ label, ok }: { label: string; ok: boolean }) { return (
{label}
); } function Detail({ label, value, mono }: { label: string; value: string; mono?: boolean }) { return (
{label}
{value}
); } function StatusBadge({ ok, on, off }: { ok: boolean; on: string; off: string }) { return {ok ? on : off}; } function formatDate(value: string): string { const date = new Date(value); return Number.isNaN(date.getTime()) ? value : date.toLocaleString(); } function duration(seconds: number): string { if (!Number.isFinite(seconds) || seconds <= 0) return '0s'; const days = Math.floor(seconds / 86400); const hours = Math.floor((seconds % 86400) / 3600); const minutes = Math.floor((seconds % 3600) / 60); if (days > 0) return `${days}d ${hours}h`; if (hours > 0) return `${hours}h ${minutes}m`; if (minutes > 0) return `${minutes}m`; return `${seconds}s`; }