From bead4f1d5a3ac5b337eca748499e50d2825ee3a5 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Mon, 15 Dec 2025 15:19:17 -0500 Subject: [PATCH] validate and email on sso privisioning (#6734) --- .../Implementations/RegisterUserCommand.cs | 3 + .../Registration/RegisterUserCommandTests.cs | 86 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/src/Core/Auth/UserFeatures/Registration/Implementations/RegisterUserCommand.cs b/src/Core/Auth/UserFeatures/Registration/Implementations/RegisterUserCommand.cs index be85a858a3..4a0e9c2cf5 100644 --- a/src/Core/Auth/UserFeatures/Registration/Implementations/RegisterUserCommand.cs +++ b/src/Core/Auth/UserFeatures/Registration/Implementations/RegisterUserCommand.cs @@ -99,6 +99,9 @@ public class RegisterUserCommand : IRegisterUserCommand public async Task RegisterSSOAutoProvisionedUserAsync(User user, Organization organization) { + // Validate that the email domain is not blocked by another organization's policy + await ValidateEmailDomainNotBlockedAsync(user.Email, organization.Id); + var result = await _userService.CreateUserAsync(user); if (result == IdentityResult.Success) { diff --git a/test/Core.Test/Auth/UserFeatures/Registration/RegisterUserCommandTests.cs b/test/Core.Test/Auth/UserFeatures/Registration/RegisterUserCommandTests.cs index 92a3f3fb10..ae669398c5 100644 --- a/test/Core.Test/Auth/UserFeatures/Registration/RegisterUserCommandTests.cs +++ b/test/Core.Test/Auth/UserFeatures/Registration/RegisterUserCommandTests.cs @@ -1382,4 +1382,90 @@ public class RegisterUserCommandTests .Received(1) .SendOrganizationUserWelcomeEmailAsync(user, organization.DisplayName()); } + + [Theory, BitAutoData] + public async Task RegisterSSOAutoProvisionedUserAsync_WithBlockedDomain_ThrowsException( + User user, + Organization organization, + SutProvider sutProvider) + { + // Arrange + user.Email = "user@blocked-domain.com"; + + sutProvider.GetDependency() + .IsEnabled(FeatureFlagKeys.BlockClaimedDomainAccountCreation) + .Returns(true); + + sutProvider.GetDependency() + .HasVerifiedDomainWithBlockClaimedDomainPolicyAsync("blocked-domain.com", organization.Id) + .Returns(true); + + // Act & Assert + var exception = await Assert.ThrowsAsync(() => + sutProvider.Sut.RegisterSSOAutoProvisionedUserAsync(user, organization)); + Assert.Equal("This email address is claimed by an organization using Bitwarden.", exception.Message); + } + + [Theory, BitAutoData] + public async Task RegisterSSOAutoProvisionedUserAsync_WithOwnClaimedDomain_Succeeds( + User user, + Organization organization, + SutProvider sutProvider) + { + // Arrange + user.Email = "user@company-domain.com"; + + sutProvider.GetDependency() + .IsEnabled(FeatureFlagKeys.BlockClaimedDomainAccountCreation) + .Returns(true); + + // Domain is claimed by THIS organization, so it should be allowed + sutProvider.GetDependency() + .HasVerifiedDomainWithBlockClaimedDomainPolicyAsync("company-domain.com", organization.Id) + .Returns(false); // Not blocked because organization.Id is excluded + + sutProvider.GetDependency() + .CreateUserAsync(user) + .Returns(IdentityResult.Success); + + // Act + var result = await sutProvider.Sut.RegisterSSOAutoProvisionedUserAsync(user, organization); + + // Assert + Assert.True(result.Succeeded); + await sutProvider.GetDependency() + .Received(1) + .CreateUserAsync(user); + } + + [Theory, BitAutoData] + public async Task RegisterSSOAutoProvisionedUserAsync_WithNonClaimedDomain_Succeeds( + User user, + Organization organization, + SutProvider sutProvider) + { + // Arrange + user.Email = "user@unclaimed-domain.com"; + + sutProvider.GetDependency() + .IsEnabled(FeatureFlagKeys.BlockClaimedDomainAccountCreation) + .Returns(true); + + sutProvider.GetDependency() + .HasVerifiedDomainWithBlockClaimedDomainPolicyAsync("unclaimed-domain.com", organization.Id) + .Returns(false); // Domain is not claimed by any org + + sutProvider.GetDependency() + .CreateUserAsync(user) + .Returns(IdentityResult.Success); + + // Act + var result = await sutProvider.Sut.RegisterSSOAutoProvisionedUserAsync(user, organization); + + // Assert + Assert.True(result.Succeeded); + await sutProvider.GetDependency() + .Received(1) + .CreateUserAsync(user); + } }