feat: SSO Rework — Test Login, emailClaim, discoveryUri, protocol selector#27336
feat: SSO Rework — Test Login, emailClaim, discoveryUri, protocol selector#27336
Conversation
…ocol selector (#27312) Backend: - Add discoveryUri and emailClaim fields to authenticationConfiguration schema - Add emailClaim priority chain in SecurityUtil (claimsMapping > emailClaim > fallback) - Add syncFieldsFromDiscoveryUri auto-sync on save (authority, clientId, callbackUrl) - Add TestLoginHandler with OIDC popup flow (initiate + callback) and LDAP inline test - Add Test Login endpoints in SystemResource (initiate, callback, LDAP) - Add SAML email attribute check before NameID fallback - Exclude test-login callback from JwtFilter Frontend: - Add protocol selector (OIDC / SAML / LDAP) replacing 8 provider cards - Add OIDC provider dropdown options with Discovery URI templates - Add TestLoginButton component (popup + postMessage listener) - Add ClaimSelector component (claims table + email claim selection) - Add AuthModeWidget replacing Public/Confidential jargon - Hide auto-derived fields (authority, publicKeyUrls, tokenValidationAlgorithm) - Wire Test Login into SSOConfigurationForm Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
| String json = JsonUtils.pojoToJson(message); | ||
|
|
||
| resp.setContentType("text/html; charset=UTF-8"); | ||
| resp.getWriter() | ||
| .write( | ||
| "<!DOCTYPE html><html><body>" | ||
| + "<p>" | ||
| + (success | ||
| ? "Authentication successful. This window will close." | ||
| : "Error: " + error) | ||
| + "</p>" | ||
| + "<script>" | ||
| + "if (window.opener) {" | ||
| + " window.opener.postMessage(" | ||
| + json |
There was a problem hiding this comment.
🚨 Security: XSS via IdP claims injected raw into HTML <script> tag
In sendPostMessage(), the JSON-serialized claims from the IdP are embedded directly into a <script> tag without HTML escaping (line 266). Jackson's writeValueAsString() does not escape HTML characters like </script>. If an IdP returns a claim value containing </script><script>alert(document.cookie)</script>, it will break out of the script context and execute arbitrary JavaScript.
Similarly, in sendError() (line 312-317), the message parameter is interpolated into both an HTML <p> tag (no escaping) and a JavaScript string (only single-quote escaping via replace("'", "\'")). Error messages from exceptions may contain attacker-influenced content.
Since the callback endpoint is excluded from JWT authentication (JwtFilter line 109), any user completing an IdP flow reaches this code path.
Suggested fix:
Escape the JSON before embedding in HTML by replacing `</` with `<\/` (standard script-safe encoding). For sendError, HTML-encode the message for the <p> tag and properly escape it for JS:
// In sendPostMessage:
String safeJson = json.replace("</", "<\/");
// use safeJson in the script tag
// In sendError, HTML-encode for the <p> tag:
String htmlSafe = message.replace("&","&").replace("<","<").replace(">",">");
// And for JS string, also escape backslashes, quotes, newlines:
String jsSafe = message.replace("\","\\").replace("'","\'").replace("
","\n");
Was this helpful? React with 👍 / 👎 | Reply gitar fix to apply this suggestion
| @GET | ||
| @Path("/config/auth/test-login/initiate") | ||
| @Produces("text/html") | ||
| @Consumes("*/*") | ||
| @Operation( | ||
| operationId = "testLoginInitiate", | ||
| summary = "Initiate Test Login", | ||
| description = | ||
| "Initiates a Test Login flow by redirecting to the IdP. " | ||
| + "Opens in a popup window. After authentication, redirects to the callback endpoint.") | ||
| public void testLoginInitiate( | ||
| @Context HttpServletRequest request, @Context HttpServletResponse response) { | ||
| TestLoginHandler.handleInitiate(request, response); | ||
| } |
There was a problem hiding this comment.
⚠️ Security: Test login initiate endpoint lacks admin authorization check
The testLoginInitiate endpoint (GET /config/auth/test-login/initiate) requires JWT authentication (not in EXCLUDED_ENDPOINTS), but performs no role-based authorization. Any authenticated user — not just admins — can initiate the test login flow. This is inconsistent with the LDAP test login endpoint which calls authorizer.authorizeAdmin(securityContext). The test login flow is an admin-only diagnostic feature and should be restricted accordingly.
Note: The callback endpoint must remain unauthenticated (it's an IdP redirect), but the initiate endpoint should require admin privileges.
Suggested fix:
Add SecurityContext and admin authorization to the initiate endpoint:
public void testLoginInitiate(
@Context SecurityContext securityContext,
@Context HttpServletRequest request,
@Context HttpServletResponse response) {
authorizer.authorizeAdmin(securityContext);
TestLoginHandler.handleInitiate(request, response);
}
Was this helpful? React with 👍 / 👎 | Reply gitar fix to apply this suggestion
Code Review 🚫 Blocked 2 resolved / 4 findingsSSO rework integrates emailClaim, discoveryUri, and protocol selection, but is blocked by a critical XSS vulnerability in claims injection and an authorization bypass in the test login endpoint. 🚨 Security: XSS via IdP claims injected raw into HTML <script> tag📄 openmetadata-service/src/main/java/org/openmetadata/service/security/auth/TestLoginHandler.java:252-266 📄 openmetadata-service/src/main/java/org/openmetadata/service/security/auth/TestLoginHandler.java:305-319 📄 openmetadata-service/src/main/java/org/openmetadata/service/security/auth/TestLoginHandler.java:136-141 In Similarly, in Since the callback endpoint is excluded from JWT authentication (JwtFilter line 109), any user completing an IdP flow reaches this code path. Suggested fix
|
| Compact |
|
Was this helpful? React with 👍 / 👎 | Gitar
…ields - Add test-login/initiate to JwtFilter EXCLUDED_ENDPOINTS (popup window doesn't carry JWT token — endpoint only redirects to IdP, no data exposure) - Hide authorizer fields: botPrincipals, principalDomain, enforcePrincipalDomain, enableSecureSocketConnection, useRolesFromProvider, allowedEmailRegistrationDomains, allowedDomains, defaultOAuthRole (these will be auto-filled by Test Login or moved to advanced settings) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…e-validation to Test Login - Hide emailClaim, discoveryUri from form (set via Test Login, not manual input) - Hide adminPrincipals, enableSelfSignup, enableAutoRedirect (auto-filled or advanced) - Test Login now validates configuration before opening popup — calls validateSecurityConfiguration first, shows error inline if validation fails, only opens popup if config is valid Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
The 404 was caused by Dropwizard/Jersey rejecting void return type for @get methods. Rewritten to return proper JAX-RS Response objects: - handleInitiate returns Response.temporaryRedirect(authUrl) instead of HttpServletResponse.sendRedirect - handleCallback returns Response.ok(html, "text/html") instead of writing to HttpServletResponse directly - Removed HttpServletResponse dependency from endpoints Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
Moved prompt to hidden in all provider-specific UI schemas (Google, Azure, Okta, Auth0/Cognito, Custom OIDC) — this is an advanced setting that rarely needs user configuration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
Root cause of 404: ConfigResource owns @path("/v1/system/config") and SystemResource is at @path("/v1/system"). When the test-login endpoints were in SystemResource at @path("/config/auth/test-login/..."), Jersey routed them to ConfigResource (which owns /config/*) instead. ConfigResource had no matching sub-path, so it returned 404. Fix: moved all test-login endpoints to ConfigResource where they belong under the /config/auth path prefix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…rm data TestLoginHandler no longer depends on AuthenticationCodeFlowHandler being initialized. Instead, it: 1. Reads discoveryUri, clientId, clientSecret, scope from query params (passed by frontend from the unsaved form data) 2. Fetches OIDC discovery document directly via OIDCProviderMetadata.resolve() 3. Builds authorization URL from the discovery metadata 4. On callback, builds token request directly using Nimbus SDK (ClientSecretBasic for confidential, ClientID-only for public) 5. Stores clientId/secret/discoveryUri in HTTP session for the callback This means Test Login works BEFORE saving — user fills fields, clicks Test Login to validate, then saves. No dependency on server state. Frontend: TestLoginButton now passes form data (discoveryUri, clientId, clientSecret, scope) as query params to the initiate endpoint. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…ery URI resolve() expects an Issuer (base URL) and appends .well-known/openid-configuration. We have the full discovery URI, so use parse() with direct HTTP fetch instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…_mismatch Root cause: Test Login used a separate callback URL (/api/v1/system/config/ auth/test-login/callback) that wasn't registered in the IdP's OAuth app. Google (and other IdPs) reject unregistered redirect URIs with 400. Fix: Reuse the same /callback URL that's already registered in the IdP. Differentiate Test Login callbacks using state prefix "test-login:". Changes: - TestLoginHandler.handleInitiate(): uses registered callbackUrl (from form data or defaults to /callback), prefixes state with "test-login:" - AuthCallbackServlet.doGet(): checks state prefix, routes test-login callbacks to TestLoginHandler.handleCallback() - Removed separate /auth/test-login/callback endpoint from ConfigResource - Removed callback from JwtFilter excluded endpoints (servlet handles it) - Frontend passes callbackUrl from form data to initiate endpoint Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…ailClaim set Bug 1: "Client ID is required" on first click — formData was missing from useCallback dependency array, causing stale closure. Added formData to deps. Bug 2: Save button now disabled for new OIDC setups until emailClaim is confirmed via Test Login → Claim Selector flow. Existing configs can still save freely. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
The JSON schema default was updated but 6 hardcoded fallbacks in frontend code still used "openid email profile" without offline_access. Updated: - SSOUtils.ts (2 occurrences) - AuthProvider.util.ts (3 occurrences) - TestLoginButton.component.tsx (1 occurrence) - conf/openmetadata.yaml (OIDC_SCOPE default) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…uthMethod to visible 1. Popup communication: replaced window.opener.postMessage with localStorage. window.opener is null after redirect chains (initiate → IdP → callback). localStorage works across same-origin windows regardless of redirects. Popup stores result, parent reads via storage event + close-check fallback. Popup always closes itself. 2. Restored scope, prompt to visible in all 5 provider UI schemas (they were hidden but should be in advanced config = visible). 3. Restored Okta clientAuthenticationMethod to visible. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…veryUri discoveryUri is a top-level field in authenticationConfiguration — the single source of truth for both public and confidential flows. The nested oidcConfiguration.discoveryUri is synced from it on save. - Made top-level discoveryUri visible with title and placeholder - Hidden nested oidcConfiguration.discoveryUri in all 6 provider schemas (OIDC, Google, Azure, Okta, Auth0/Cognito, Custom OIDC) - One discoveryUri field visible regardless of client type Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…estLoginButton handleOidcProviderChange was writing discoveryUri to the nested oidcConfiguration.discoveryUri (hidden), not the top-level discoveryUri (visible). TestLoginButton was also checking nested first. Fixed both to use the top-level field as primary. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
… default Test Login now mirrors the actual OIDC flow by passing: - prompt (consent/login/none) - maxAge - clientAuthenticationMethod (client_secret_basic/client_secret_post) Backend: TestLoginHandler reads these from query params, applies to auth URL, and uses correct client auth method for token exchange. Also reverted offline_access from default scope — back to "openid email profile" everywhere (schema, SSOUtils, AuthProvider.util, TestLoginButton, openmetadata.yaml). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…normalization - backend: add normalizeForPersistence and hydrateForResponse in SystemRepository. deterministic priority-based mirroring between root and nested OIDC fields, always-overwrite derivation of authority and publicKeyUrls from discoveryUri, Azure tenant extraction across commercial/gov/china cloud variants. - backend: SystemResource calls normalizeForPersistence on validate/PUT, hydrateForResponse on GET. Legacy configs without discoveryUri are preserved unchanged — zero regression for existing customers. - ui: mirror canonical and legacy OIDC fields in form onChange so RJSF's schema required check passes before hitting the API (workaround only; backend handles partial payloads on its own). - ui: validation state machine — Validate button posts to /validate?context=testLogin, enables Test Login on success. Save gated on Test Login + claim-selector confirm. Reset only when actual validation inputs change, not post-test fields. - ui: hide Azure tenant (backend-derived). Advanced Configuration accordion collapses non-essential OIDC fields via SSO_ADVANCED_OIDC_FIELDS. - tests: SystemRepositoryNormalizeTest covers mirror directions, Azure tenant extraction (all cloud variants), legacy preservation, null safety, no-network-call on hydrate. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
adminPrincipals is often configured by email (e.g. "alice@company.com")
while the derived userName is typically the email local part ("alice").
The previous check only looked up userName in adminPrincipals, so a user
configured by email never got promoted to admin on login.
- SecurityUtil: new isAdminPrincipal(adminPrincipals, userName, email)
helper that matches either form.
- AuthenticationCodeFlowHandler: use helper on existing and new OIDC
user paths.
- SamlAuthServletHandler: same for existing and new SAML user paths.
- SamlAssertionConsumerServlet: same for JWT token admin flag.
LDAP intentionally unchanged — LDAP principals are usernames, not emails.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
Two coupled changes enabling the full Test Login gated flow across both
OIDC and SAML:
## SAML Test Login
- New TestSamlHandler builds a temporary Saml2Settings from form-provided
IdP details, redirects popup to IdP with RelayState="saml-test-login:<uuid>",
and on callback verifies the SAMLResponse + flattens attributes into the
same {success, claims} payload that OIDC Test Login produces.
- New POST /v1/system/config/auth/test-login/saml-initiate endpoint using
@FormParam so Jersey reliably parses the form-urlencoded body.
- AuthCallbackServlet.doPost now routes SAML Test Login callbacks by
RelayState prefix (parallel to the existing doGet state-prefix routing
for OIDC Test Login).
- TestLoginResponses extracted from TestLoginHandler so both OIDC and SAML
use the same popup HTML / localStorage handoff.
- UI: TestLoginButton branches by provider; SAML uses a hidden-form POST
with target=_blank so the cert fits cleanly in the body.
- UI: SAML main form now shows only IdP Entity ID, SSO Login URL, X.509
Certificate, NameID Format. SP fields are surfaced in a banner and
derived server-side. SP certs, signing flags, and security options move
to an Advanced Configuration accordion via SSO_ADVANCED_SAML_FIELDS.
- ClaimSelector handles multi-valued SAML attributes (arrays joined for
display, single values stringified as before).
## OIDC validator refinement
- New SystemRepository.validateDiscoveryUriReachable runs at the top of
validateSecurityConfiguration for any OIDC provider with a discoveryUri.
Short-circuits with a single clear error ("Could not reach Discovery
URI") when the URI is unreachable, invalid JSON, missing issuer/jwks_uri,
or (for Azure) doesn't match the Azure AD URL shape.
- Removed duplicate discoveryUri fetches from Azure, Okta, Auth0, and
Cognito validators now that the upstream check handles reachability.
Each validator keeps only its provider-specific semantic checks (issuer
format, required endpoints, client credential validation).
- Improved error messages where fields are backend-derived:
Azure: "Tenant could not be determined from Discovery URI…"
Okta/Auth0/Cognito: "domain/URL could not be verified…"
Custom OIDC: "Discovery document is missing required endpoints…"
## Validation state machine (shared across OIDC and SAML)
- areMainFieldsFilled and didValidationInputsChange now branch on
provider so SAML uses IdP fields and OIDC uses discoveryUri + client
credentials. validationStatus resets only when fields that actually
affect validation change.
- Test Login and Validate button gates now accept either OIDC or SAML.
## Tests
8 new tests in SystemRepositoryNormalizeTest for the upstream discoveryUri
check (unreachable, invalid JSON, missing issuer, Azure shape mismatch,
LDAP scope skip, valid happy path, invalid URL format, legacy config
fall-through).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
| + "</script>" | ||
| + "</body></html>"; | ||
|
|
||
| return Response.ok(html, "text/html").build(); |
| + "</script>" | ||
| + "</body></html>"; | ||
|
|
||
| return Response.status(Response.Status.BAD_REQUEST).entity(html).type("text/html").build(); |
| + "</script>" | ||
| + "</body></html>"; | ||
|
|
||
| return Response.ok(html, "text/html").build(); |
| + "</script>" | ||
| + "</body></html>"; | ||
|
|
||
| return Response.status(Response.Status.BAD_REQUEST).entity(html).type("text/html").build(); |
- TestLoginHandler: PKCE code_challenge sent by default (unless disablePkce=true), code_verifier stored in session and included in token exchange. Nonce now conditional on useNonce param. customParams parsed from JSON and merged into auth URL. Session cleanup includes CODE_VERIFIER. clientAuthMethod extracted to constant. - TestSamlHandler: replaced HttpSession storage with ConcurrentHashMap keyed by RelayState UUID. Fixes "Session expired" error caused by SameSite=Lax blocking cookies on IdP's cross-origin POST callback. Entries auto-cleaned after 5 min TTL. - SystemRepository: normalizeForPersistence now populates serverUrl (derived from callbackUrl). discoveryUri mirror changed to one-way root→nested only (Option B) — legacy configs with only nested discoveryUri no longer trigger derivation on unrelated PATCHes. Removed dead autoPopulatePublicKeyUrlsIfNeeded method. - SystemResource: PATCH handler calls normalizeForPersistence after patch apply. PUT handler @Valid removed (fires before normalize, rejects partial payloads that normalize would fill). - TestLoginButton: passes disablePkce, useNonce, customParams to backend for OIDC Test Login. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
Switch OIDC Test Login initiate from GET+query-params to POST+form-body so clientSecret stays out of URLs, server logs, and browser history. - ConfigResource: endpoint changed to POST with @FormParam for each OIDC field (same pattern as SAML initiate). - TestLoginHandler: accepts params as method arguments instead of req.getParameter() (Jersey consumes form body before handler runs). - Redirect changed from 307 (temporaryRedirect) to 302 so the browser converts POST→GET when following the redirect to the IdP. 307 preserved the POST method, causing Azure to reject with "client_id missing in body". - TestLoginButton: OIDC now uses hidden-form POST with target=_blank (same pattern as SAML). Both protocols use identical transport. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
LDAP pre-save Test Login so admins can verify form-provided LDAP config without requiring a saved authenticator. UI collects user credentials via an inline modal (no popup — LDAP has no external IdP to redirect to). ClaimSelector is skipped since LDAP's email attribute is explicit; principalDomain and adminPrincipal are auto-filled from the test user's resolved email. ## Backend - TestLdapHandler: stateless handler that accepts form-provided LdapConfiguration + user credentials. Admin bind → search by mailAttributeName → user bind → read mail attribute. Uses UnboundID LDAPConnection directly; no singletons, no DB writes, no user creation. Try-with-resources for connection lifecycle. - ConfigResource: POST /v1/system/config/auth/test-login/ldap-initiate (JSON body with ldapConfiguration, email, password). Inline LdapTestLoginRequest DTO. - JwtFilter: whitelisted the new endpoint. - LdapAuthenticator: admin promotion now checks both userName and email via SecurityUtil.isAdminPrincipal — matches the fix already applied to OIDC/SAML. Fixes the case where adminPrincipals is saved as a full email but LDAP login was comparing against the local-part username. ## Frontend - TestLoginButton: LDAP branch opens an Ant Design Modal with email and password inputs. Submits JSON to /ldap-initiate, calls onSuccess with derivedPrincipalDomain + suggestedAdminPrincipal. No popup. - SSOConfigurationForm: handleTestLoginSuccess branches on provider — LDAP bypasses ClaimSelector entirely and directly applies principalDomain + adminPrincipals (emailClaim is left unset so the jwtPrincipalClaims fallback picks up "email" from the OM-issued JWT). areMainFieldsFilled and didValidationInputsChange handle LDAP fields. - TestLogin.interface: ldapConfiguration added to form data type. ## Tests (44 new, 67 total) - TestLoginHandlerTest (17) — OIDC validation branches, callback validation, buildClientAuthentication helper (basic/post/fallback), buildTestLoginResult (timestamp filtering, email detection, domain derivation, null handling). - TestSamlHandlerTest (14) — SAML validation branches, RelayState routing, buildSamlSettings (IdP fields, NameID format, security flags off), buildClaimsFromAuth (single/multi-value flattening, empty/null handling). - TestLdapHandlerTest (13) — uses UnboundID InMemoryDirectoryServer (real LDAP in-process). Covers input validation, happy path, wrong admin password, user not found, wrong user password, wrong userBaseDN, wrong mailAttributeName, server unreachable. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…login # Conflicts: # openmetadata-ui/src/main/resources/ui/src/locale/languages/ar-sa.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json # openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
Formatting-only changes: import reordering and long argument list splitting per Google Java Format. No logic changes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
Remove AuthModeWidget, TestLogin components/types, and net-new SSO util/API additions from PR #27336 so this branch carries only the backend Test Login support and inherits our existing SSO chrome work. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Wire SSO Test Login to PR #27336's backend: TestLoginButton (OIDC/SAML hidden-form-POST popup + LDAP credential modal) and a ClaimSelector modal that auto-populates adminPrincipal (email local-part) and principalDomain from the chosen email claim. Drop the old broken call to /security/config/test. - Make oidcConfiguration.secret optional with a recommended hint; auto-derive clientType from secret presence; hide the manual radio. - Drop adminPrincipals + principalDomain from authorizerConfiguration required[] so initial save isn't blocked. Hide them during the new-config flow; keep main tier so they surface once Test Login fills. - Strip oidcConfiguration from the schema for SAML/LDAP to stop RJSF materializing defaults inside a hidden subtree. - Hide root-level OIDC mirrors and tenant per the field-layout proposal; surface preferredJwsAlgorithm in advanced; remove in-form callbackUrl (the read-only display beside the form is the source). - Fix TestLoginButton formData prop shape so SAML/LDAP click paths route correctly; vertically center action-bar buttons. - Sync 19 new i18n keys across the 17 locales. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
SSO configuration rework — simplifies setup from 8 provider options to 3 protocols (OIDC/SAML/LDAP), adds Test Login for claim verification, and prevents user lockouts.
Closes #27312
Changes
Backend
discoveryUriandemailClaimtoauthenticationConfigurationjwtPrincipalClaimsMapping(highest) →emailClaim(new) →jwtPrincipalClaims(legacy fallback). Explicit config hard-fails if claim missing; legacy fallback is soft (zero regression)syncFieldsFromDiscoveryUri()— derives authority, publicKeyUrls, clientId from discovery documentTestLoginHandlerwith OIDC popup flow (initiate → IdP auth → callback → extract claims → postMessage) and LDAP inline testemailattribute before NameID fallback (backward compatible)Frontend
Backward Compatibility
emailattribute not presentjwtPrincipalClaimssoft fallback still works for unconfigured setupsTest plan
🤖 Generated with Claude Code
Summary by Gitar
SystemRepositoryby checkingsemanticSearchEnabledstatus.SSOConfigurationFormclick event listeners to use capture phase for better interaction handling.SSOConfigurationForm.tsx.This will update automatically on new commits.