Repository navigation
Description
Detail Bug Report
Introduced in #21839 by @shrushti2000 on Sep 23, 2025
Summary
- Context:
SamlValidatorvalidates admin-entered SAML SSO configuration before it is persisted;validateAzureAdTenantis invoked for Azure AD entity IDs to confirm the configured tenant is valid. - Bug: The tenant-ID format check uses a regex character class
[a-f0-9\-]that admits only lowercase hex digits, so a valid Azure AD tenant GUID entered in uppercase or mixed case (e.g.A1B2C3D4-E5F6-7890-1234-567890ABCDEF) is rejected as "Invalid Azure AD tenant ID format" before the network validation runs. A second case-sensitivity defect in the same method — theissuer.contains(tenantId)comparison — would reject the same input after the network probe if the regex were fixed alone, because Azure's OpenID-config endpoint returns a lowercaseissuereven for an uppercase path-segment GUID. Both are one logical defect: the method treats the tenant GUID as case-sensitive end-to-end instead of normalizing to lowercase. - Actual vs. expected: The validator should accept any valid Azure AD tenant GUID regardless of letter case; instead it fails the config save for any non-lowercase GUID.
- Impact: Configuration-save failure for a narrow input class — an uppercase or mixed-case tenant GUID embedded in the IdP Entity ID. No security or data-integrity consequence; the config simply cannot be saved.
Code with Bug
openmetadata-service/src/main/java/org/openmetadata/service/security/auth/validator/SamlValidator.java
// Validate tenant ID format (should be a GUID)
if (!tenantId.matches("[a-f0-9\\-]{36}") // <-- BUG 🔴 rejects uppercase/mixed-case GUID hex digits
&& !tenantId.equals("common")
&& !tenantId.equals("organizations")
&& !tenantId.equals("consumers")) {
return ValidationErrorBuilder.createFieldError(
ValidationErrorBuilder.FieldPaths.SAML_IDP_ENTITY_ID,
"Invalid Azure AD tenant ID format: " + tenantId);
}// After fetching OpenID config, compare against Azure's issuer
if (!issuer.contains(tenantId) // <-- BUG 🔴 case-sensitive comparison vs lowercase issuer
&& !tenantId.equals("common")
&& !tenantId.equals("organizations")
&& !tenantId.equals("consumers")) {
return ValidationErrorBuilder.createFieldError(
ValidationErrorBuilder.FieldPaths.SAML_IDP_ENTITY_ID,
"Tenant ID mismatch. Expected tenant: " + tenantId + " but issuer is: " + issuer);
}Explanation
validateAzureAdTenantextracts a tenant ID from the Azure AD entity ID and first gates it withtenantId.matches("[a-f0-9\\-]{36}"). This pattern only permits lowercasea-f, so valid GUIDs containingA-Fare rejected immediately with "Invalid Azure AD tenant ID format".- Even if the regex were loosened,
issuer.contains(tenantId)is also case-sensitive. Azure’s OpenID configuration returns a lowercaseissuereven when the request path uses an uppercase GUID, so uppercase/mixed-case input would then fail with "Tenant ID mismatch". - There is no upstream normalization on the validation call path; the admin-provided value reaches
validateAzureAdTenantverbatim.
Failing Test
@Test
void validateSamlConfigurationRejectsUppercaseAzureTenantGuid() {
SamlSSOClientConfig samlConfig = baseConfig("http://localhost/unused");
samlConfig.getIdp().setEntityId("https://sts.windows.net/A1B2C3D4-E5F6-7890-1234-567890ABCDEF/");
samlConfig.getIdp().setIdpX509Certificate(AZURE_CERT);
FieldError error =
validator.validateSamlConfiguration(new AuthenticationConfiguration(), samlConfig);
assertNotNull(error);
assertEquals(ValidationErrorBuilder.FieldPaths.SAML_IDP_ENTITY_ID, error.getField());
assertTrue(error.getError().contains("Invalid Azure AD tenant ID format"));
}Test output:
REPRO_E2E_RESULT: authenticationConfiguration.samlConfiguration.idp.entityId :: Invalid Azure AD tenant ID format: A1B2C3D4-E5F6-7890-1234-567890ABCDEF
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS
Recommended Fix
Normalize the tenant ID to lowercase once, before both the regex check and the issuer comparison:
String normalizedTenantId = tenantId.toLowerCase(Locale.ROOT);
if (!normalizedTenantId.matches("[a-f0-9-]{36}")
&& !normalizedTenantId.equals("common")
&& !normalizedTenantId.equals("organizations")
&& !normalizedTenantId.equals("consumers")) {
return ValidationErrorBuilder.createFieldError(
ValidationErrorBuilder.FieldPaths.SAML_IDP_ENTITY_ID,
"Invalid Azure AD tenant ID format: " + tenantId);
}
// Build openIdConfigUrl using normalizedTenantId, and compare with contains
// using normalizedTenantId (or lowercase the issuer side) to avoid mismatch.History
This bug was introduced in commit eebd3bb. The commit (PR #21839, "Feat(ui): SSO configuration from UI and Scim bot token generate revoke functionality and Group Mapping in settings page") created SamlValidator.java from scratch with 1000 new lines as part of a large multi-author feature adding the entire SSO-from-UI flow (Azure/Okta/Google/Auth0/Cognito/custom-OIDC validators, SCIM bot tokens, group mapping). Both case-sensitivity points — the lowercase-only regex [a-f0-9\\-]{36} and the case-sensitive issuer.contains(tenantId) comparison — were present in this creation commit and never modified by the three subsequent commits to touch the file. The bug slipped in because the new unit tests in the same PR exercised the Azure tenant-ID path exclusively with the lowercase fixture 11111111-2222-3333-4444-555555555555, so the case-only rejection of valid uppercase/mixed-case GUIDs never surfaced in CI.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone ✅
Activity
Combine queued backend fixes: certification warmup, lineage edge auth…