feat(admin): add SAML Settings admin UI (PR9) - #42
Merged
Conversation
Adds an organization-scoped SAML admin UI on top of PR8's CRUD API
(auth#49), mirroring SSOSettingsPage.tsx (PR11.3) and
OrganizationMFAPolicyPage.tsx (PR11.5.6) as closely as the two
protocols allow: same permission (manage_sso, reused rather than a new
manage_saml), same org-picker "list -> detail" nav shape under
Security, same loading/denied/not-configured/error state machine.
Backend: routes_org_saml_proxy.py relays the /orgs/{org_id}/saml CRUD
surface to omnibioai-auth (same thin-relay pattern as every other
*_proxy.py here, no authorization decision made locally) plus GET
/auth/saml/{org_slug}/metadata -- deliberately not built on the shared
JSON-wrapping _proxy() helper, since that endpoint returns raw XML.
Frontend: saml.ts (typed API client, mirroring sso.ts/security.ts),
SAMLSettingsPage.tsx (view/create/update/delete, a PEM certificate
textarea, a key/value attribute-mapping editor, and a "Download SP
Metadata" action), wired into navigation.ts/AdminApp.tsx as its own
Security section item alongside IAM/SSO and MFA Policy.
`enabled` is shown informationally only, never as an actionable
"disable login" control -- confirmed via PR8 that only `status` is
read by the SAML login/ACS path. The Status card is labeled and gated
accordingly; no break-glass override card exists, since
OrganizationSAMLConfig has no enforcement flag for one to suspend.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
omnibioai-auth#49), reusing the exact org-picker "list → detail" navigation shape and permission modelSSOSettingsPage.tsx(PR11.3) andOrganizationMFAPolicyPage.tsx(PR11.5.6) already established under the Security section — no new permission (manage_ssoreused, not a newmanage_saml).routes_org_saml_proxy.pyrelaysGET/POST/PATCH/DELETE /orgs/{org_id}/samltoomnibioai-auth, the same thin-relay pattern every other*_proxy.pyin this repo uses — no authorization decision is made locally, that's entirelyomnibioai-auth's job (require_org_permission_or_platform_admin(MANAGE_SSO), pre-existing, unmodified). Also proxiesGET /auth/saml/{org_slug}/metadata— deliberately not built on the shared JSON-wrapping_proxy()helper, since that endpoint returns raw XML (application/samlmetadata+xml), not JSON.saml.ts(typed API client),SAMLSettingsPage.tsx— view/create/update/delete, a PEM certificate textarea (pre-filled on edit since it's a public cert, unlike a secret), a key/value attribute-mapping editor, a Status control, and a "Download SP Metadata" action (blob download of the existing endpoint, same mechanismcompliance.ts's HIPAA report downloads already use — no client-side XML construction, no IdP metadata import, no arbitrary URL fetch).navigation.ts/AdminApp.tsxas its own Security-section nav item (/security/saml/{orgId}deep-link), gated by the samehasOrganizationsAccessUX signaliam/mfa-policyalready use (backend remains authoritative either way).Key design decisions (see PR9 report for full reasoning)
enabledis shown informationally only, never as an actionable "disable login" control. Confirmed via PR8's own report that onlystatusis read by the SAML login/ACS path — the UI is honest about this rather than building a toggle that would silently do nothing.enabledfield), since flippingstatusbetweenactive/disabledis what actually gatesGET /auth/saml/{org_slug}/login.OrganizationSSOConfig.enforced/OrganizationMFAPolicy.required,OrganizationSAMLConfighas no enforcement flag with a lockout guard for an override to suspend, so there's nothing analogous to build.entity_id_for/acs_url_for); surfacing a second, different URL here would be confusing rather than helpful.Test plan
origin/mainbaseline — backend:1259 passed; frontend:495 passed(40 files); build: clean1281 passed(exact +22, matching the new proxy test file); frontend:535 passed(exact +40, matching the new component/data-layer/nav-placement tests, 42 files); build: clean;tsc -btypecheck: 0 errorsruff checkon all changed/new backend files: 0 genuinely new findings (confirmed by diffingmain.py's pre-existing findings against cleanmain; the one new finding in the test file mirrors an identical, already-unfixed pattern intest_routes_org_sso_proxy.py, the file it was modeled on)dangerouslySetInnerHTML, nolocalStorage/sessionStoragepersistence, no client-constructed hrefs from IdP-supplied values, org id always server/routing-resolved (never client state/payload-supplied)Scope confirmation
omnibioai-control-centertouched (no changes toomnibioai-auth, TES, workflow-bundles, RAG, billing, or the root repo)🤖 Generated with Claude Code