mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 12:41:30 +00:00
feat(gui/oidc): Test Connection panel on create + edit forms (MED-5 GUI half)
Audit 2026-05-11 Fix 09 closure. MED-5's backend dry-run endpoint
(POST /api/v1/auth/oidc/test, gated auth.oidc.create) shipped on
dev/auth-bundle-2 (commit b4b9879) but the GUI never called it —
authOIDCTestProvider in web/src/api/client.ts was dead code.
Operator gap before this fix: complete the create form blind, save,
then click 'Refresh' to discover whether the issuer URL worked.
Discovery failures left a broken provider row in the DB that had
to be deleted before retrying. The MED-5 backend exists to short-
circuit this — surface the dry-run result before commit.
New shared component web/src/pages/auth/OIDCTestConnectionPanel.tsx
calls authOIDCTestProvider against the live form state (issuer URL
+ client ID + parsed scopes) and renders a four-row status panel
inline:
* ✓/✗ Discovery fetched (with issuer-echo from the well-known doc)
* ✓/✗ JWKS reachable (with the discovered jwks_uri)
* ✓/⚠ Supported algs (warning glyph when the IdP advertises none —
distinct from a discovery failure)
* ✓/· RFC 9207 iss-parameter advertised (informational · glyph
rather than ✗ because the spec is SHOULD, not MUST)
Backend per-leg errors[] flow into an inline bullet list. A
top-level rectangle catches network/fetch failures separately.
The Run button is disabled when the issuer URL is empty or
whitespace-only. The component does NOT persist anything — safe
to run repeatedly before the operator clicks Save.
The panel is mounted in two places:
* OIDCProvidersPage create modal (between the form fields and the
Create button) — short-circuits the blind-save footgun for new
provider configs.
* OIDCProviderDetailPage edit form (between the field grid and
the Save button) — load-bearing for verifying IdP rotations
(Keycloak realm rename, Okta tenant move, certctl side-by-side
hostname change) without committing first.
A testIDSuffix prop (default 'create' / 'edit') gives each mount
point a distinct data-testid namespace so both panels can coexist
on a hypothetical page that uses both without DOM-id collisions.
8 Vitest tests in OIDCTestConnectionPanel.test.tsx:
* RunButton — disabled until issuer URL is non-empty
* RunButton — also disabled when issuer URL is whitespace-only
* RunButton — enabled when issuer URL is non-empty
* HappyPath — all four primary checks render green with detail
rows for authorization_url / token_url / userinfo_endpoint
(asserts both the glyph contract AND the mocked POST body shape)
* FailurePath — discovery=false renders ✗ on discovery + ✗ on
JWKS + ⚠ on empty supported algs + error list with backend
per-leg messages
* IssParamFalse — load-bearing UX claim that the iss-parameter
row renders · (informational), not ✗; body must contain the
word 'informational' so operators understand it's not a failure
* FetchError — top-level error rectangle when the POST throws
* TestIDSuffix — same component mounted twice with different
suffixes renders both without DOM-id collision
Verify gate:
* tsc --noEmit — clean
* vitest OIDCTestConnectionPanel.test.tsx — 8/8 pass
* vitest OIDCProvidersPage.test.tsx + OIDCProviderDetailPage.test.tsx
— 38/38 pass (panel-mount in both pages does not regress
existing tests because they don't trigger the test button)
Operator runbook: the four glyph meanings are documented inline on
the panel's subtitle. Audit doc annotation at
cowork/auth-bundles-audit-2026-05-10.md flips MED-5 from
'BACKEND CLOSED' to 'CLOSED' with the GUI-half annotation.
Refs cowork/auth-bundles-fixes-2026-05-11/09-med-oidc-test-connection-button.md.
This commit is contained in:
@@ -4,6 +4,29 @@
|
||||
|
||||
### Security
|
||||
|
||||
- **OIDC provider "Test connection" panel (Audit 2026-05-11 Fix 09 — MED-5 GUI half).**
|
||||
MED-5's backend dry-run endpoint (`POST /api/v1/auth/oidc/test`, gated
|
||||
`auth.oidc.create`) shipped on `dev/auth-bundle-2` but had no GUI caller —
|
||||
the `authOIDCTestProvider` function in `web/src/api/client.ts` was dead
|
||||
code. Operators had to complete the create form blind, save, then click
|
||||
"Refresh" to discover whether the issuer URL worked; failures left a
|
||||
broken provider row in the database that had to be deleted before
|
||||
retrying. New shared component
|
||||
`web/src/pages/auth/OIDCTestConnectionPanel.tsx` calls the backend
|
||||
against the live form state and renders a four-row status panel inline:
|
||||
Discovery fetched, JWKS reachable, supported algs (warns when the IdP
|
||||
advertises none), and RFC 9207 iss-parameter advertisement (informational
|
||||
`·` glyph, not ✗, because the spec is SHOULD). Backend per-leg `errors[]`
|
||||
flow into an inline bullet list. The panel is mounted in the
|
||||
OIDCProvidersPage create modal AND the OIDCProviderDetailPage edit form —
|
||||
the edit-form half is load-bearing for verifying IdP rotations (Keycloak
|
||||
realm rename, Okta tenant move) without committing first. Run button is
|
||||
disabled until the issuer URL is non-empty (whitespace-trimmed); the
|
||||
component is read-only — safe to run repeatedly. 8 Vitest tests pin the
|
||||
glyph-vs-glyph contract (✓/✗/⚠/·), the button-disabled-without-issuer
|
||||
shape, and the test-id-suffix collision-prevention when the panel is
|
||||
mounted twice on the same page.
|
||||
|
||||
- **Scope-aware actor-role revoke (Audit 2026-05-11 A-4).**
|
||||
HIGH-10 made it possible to grant the same role to the same actor at
|
||||
multiple scopes (e.g. `r-operator` on `profile=p-acme` AND `profile=p-globex`)
|
||||
|
||||
Reference in New Issue
Block a user