Browse Source

Normalize SSO default organization UUID before lookup

Uuid::parse_str also accepts uppercase, braced and non-hyphenated
forms, but stored organization uuids are lowercase hyphenated and
compared as strings. A non-canonical SSO_DEFAULT_ORGANIZATION_UUID
passed validation but failed every first SSO sign-in with
"organization does not exist". Normalize the value to the canonical
form before the database lookup.
pull/7422/head
tom27052006 1 week ago
parent
commit
4e2bde6da3
  1. 28
      src/sso.rs

28
src/sso.rs

@ -363,7 +363,7 @@ async fn enroll_user_in_default_organization(user: &User, conn: &DbConn) -> ApiR
let Some(org_uuid) = CONFIG.sso_default_organization_uuid() else {
return Ok(());
};
let org_id = OrganizationId::from(org_uuid);
let org_id = normalize_organization_uuid(&org_uuid)?;
if Membership::find_by_user_and_org(&user.uuid, &org_id, conn).await.is_some() {
return Ok(());
@ -380,6 +380,15 @@ async fn enroll_user_in_default_organization(user: &User, conn: &DbConn) -> ApiR
Ok(())
}
// `Uuid::parse_str` also accepts non-canonical forms (uppercase, braced, without hyphens),
// while stored organization uuids are always lowercase hyphenated and compared as strings.
fn normalize_organization_uuid(org_uuid: &str) -> ApiResult<OrganizationId> {
let Ok(parsed) = uuid::Uuid::parse_str(org_uuid) else {
err!("`SSO_DEFAULT_ORGANIZATION_UUID` must be a valid UUID")
};
Ok(OrganizationId::from(parsed.to_string()))
}
fn new_default_sso_membership(user_uuid: UserId, org_id: OrganizationId) -> Membership {
let mut membership = Membership::new(user_uuid, org_id, None);
membership.status = MembershipStatus::Accepted as i32;
@ -405,6 +414,23 @@ mod default_organization_tests {
assert_eq!(membership.atype, MembershipType::User as i32);
assert!(membership.invited_by_email.is_none());
}
#[test]
fn normalizes_organization_uuid_to_canonical_form() {
for input in [
"1B2C3D4E-5F60-7182-93A4-B5C6D7E8F901",
"{1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901}",
"1b2c3d4e5f60718293a4b5c6d7e8f901",
] {
let org_id = normalize_organization_uuid(input).expect("valid UUID form should be accepted");
assert_eq!(org_id.to_string(), "1b2c3d4e-5f60-7182-93a4-b5c6d7e8f901");
}
}
#[test]
fn rejects_invalid_organization_uuid() {
assert!(normalize_organization_uuid("not-a-uuid").is_err());
}
}
// We always return a refresh_token (with no refresh_token some secrets are not displayed in the web front).

Loading…
Cancel
Save