import { useEffect, useState } from 'react' import api from '@/services/api' import { useAuth } from '@/hooks/useAuth' interface Settings { enabled: boolean issuer: string | null client_id: string | null has_client_secret: boolean redirect_uri: string | null scopes: string | null post_login_redirect: string | null admin_role: string oidc_only: boolean effective_enabled: boolean source: string } export default function OidcSettingsPage() { const { user } = useAuth() const isAdmin = user?.is_admin === true const [loaded, setLoaded] = useState(null) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [message, setMessage] = useState('') const [form, setForm] = useState({ enabled: false, issuer: '', client_id: '', client_secret: '', redirect_uri: '', scopes: 'openid email profile', post_login_redirect: '', admin_role: 'admin', }) useEffect(() => { if (!isAdmin) { setLoading(false); return } api.get('/auth/oidc/settings') .then(({ data }) => { setLoaded(data) setForm({ enabled: data.enabled, issuer: data.issuer || '', client_id: data.client_id || '', client_secret: '', redirect_uri: data.redirect_uri || '', scopes: data.scopes || 'openid email profile', post_login_redirect: data.post_login_redirect || '', admin_role: data.admin_role || 'admin', }) }) .catch((e) => setMessage(e.response?.data?.detail || 'Failed to load OIDC settings')) .finally(() => setLoading(false)) }, [isAdmin]) const save = async () => { setSaving(true) setMessage('') try { const payload: Record = { enabled: form.enabled, issuer: form.issuer.trim(), client_id: form.client_id.trim(), redirect_uri: form.redirect_uri.trim(), scopes: form.scopes.trim(), post_login_redirect: form.post_login_redirect.trim(), admin_role: form.admin_role.trim() || 'admin', } if (form.client_secret) payload.client_secret = form.client_secret const { data } = await api.put('/auth/oidc/settings', payload) setLoaded(data) setForm((f) => ({ ...f, client_secret: '' })) setMessage('OIDC settings saved successfully') } catch (e: any) { setMessage(e.response?.data?.detail || 'Failed to save OIDC settings') } finally { setSaving(false) } } if (loading) return
Loading OIDC settings...
if (!isAdmin) { return (

🔐 OIDC Settings

Admin access required.

) } const callbackHint = form.redirect_uri.trim() || loaded?.redirect_uri || '(set the Redirect / Callback URL below)' return (

🔐 OIDC Settings

Configure the OpenID Connect provider. Saved values override environment defaults.
{message && (
{message}
)}
Status
{loaded?.effective_enabled ? 'OIDC active' : 'OIDC inactive'}
config source: {loaded?.source} · OIDC-only mode (deploy env): {loaded?.oidc_only ? 'on' : 'off'}
Register this Redirect / Callback URL at your identity provider:
{callbackHint}

OIDC-only bootstrap: before any admin is linked, an IdP user whose token carries this role auto-connects to the HarborForge admin account on first sign-in. Disables itself once an admin is bound.

) }