1515using Bit . Core . Utilities ;
1616using Microsoft . AspNetCore . DataProtection ;
1717using Microsoft . AspNetCore . Identity ;
18+ using Microsoft . Extensions . Logging ;
1819using Newtonsoft . Json ;
1920
2021namespace Bit . Core . Auth . UserFeatures . Registration . Implementations ;
2122
2223public class RegisterUserCommand : IRegisterUserCommand
2324{
25+ private readonly ILogger < RegisterUserCommand > _logger ;
2426 private readonly IGlobalSettings _globalSettings ;
2527 private readonly IOrganizationUserRepository _organizationUserRepository ;
2628 private readonly IOrganizationRepository _organizationRepository ;
2729 private readonly IPolicyRepository _policyRepository ;
30+ private readonly IOrganizationDomainRepository _organizationDomainRepository ;
31+ private readonly IFeatureService _featureService ;
2832
2933 private readonly IDataProtectorTokenFactory < OrgUserInviteTokenable > _orgUserInviteTokenDataFactory ;
3034 private readonly IDataProtectorTokenFactory < RegistrationEmailVerificationTokenable > _registrationEmailVerificationTokenDataFactory ;
@@ -37,28 +41,32 @@ public class RegisterUserCommand : IRegisterUserCommand
3741 private readonly IValidateRedemptionTokenCommand _validateRedemptionTokenCommand ;
3842
3943 private readonly IDataProtectorTokenFactory < EmergencyAccessInviteTokenable > _emergencyAccessInviteTokenDataFactory ;
40- private readonly IFeatureService _featureService ;
4144
4245 private readonly string _disabledUserRegistrationExceptionMsg = "Open registration has been disabled by the system administrator." ;
4346
4447 public RegisterUserCommand (
48+ ILogger < RegisterUserCommand > logger ,
4549 IGlobalSettings globalSettings ,
4650 IOrganizationUserRepository organizationUserRepository ,
4751 IOrganizationRepository organizationRepository ,
4852 IPolicyRepository policyRepository ,
53+ IOrganizationDomainRepository organizationDomainRepository ,
54+ IFeatureService featureService ,
4955 IDataProtectionProvider dataProtectionProvider ,
5056 IDataProtectorTokenFactory < OrgUserInviteTokenable > orgUserInviteTokenDataFactory ,
5157 IDataProtectorTokenFactory < RegistrationEmailVerificationTokenable > registrationEmailVerificationTokenDataFactory ,
5258 IUserService userService ,
5359 IMailService mailService ,
5460 IValidateRedemptionTokenCommand validateRedemptionTokenCommand ,
55- IDataProtectorTokenFactory < EmergencyAccessInviteTokenable > emergencyAccessInviteTokenDataFactory ,
56- IFeatureService featureService )
61+ IDataProtectorTokenFactory < EmergencyAccessInviteTokenable > emergencyAccessInviteTokenDataFactory )
5762 {
63+ _logger = logger ;
5864 _globalSettings = globalSettings ;
5965 _organizationUserRepository = organizationUserRepository ;
6066 _organizationRepository = organizationRepository ;
6167 _policyRepository = policyRepository ;
68+ _organizationDomainRepository = organizationDomainRepository ;
69+ _featureService = featureService ;
6270
6371 _organizationServiceDataProtector = dataProtectionProvider . CreateProtector (
6472 "OrganizationServiceDataProtector" ) ;
@@ -77,6 +85,8 @@ public RegisterUserCommand(
7785
7886 public async Task < IdentityResult > RegisterUser ( User user )
7987 {
88+ await ValidateEmailDomainNotBlockedAsync ( user . Email ) ;
89+
8090 var result = await _userService . CreateUserAsync ( user ) ;
8191 if ( result == IdentityResult . Success )
8292 {
@@ -102,6 +112,11 @@ public async Task<IdentityResult> RegisterUserViaOrganizationInviteToken(User us
102112 {
103113 TryValidateOrgInviteToken ( orgInviteToken , orgUserId , user ) ;
104114 var orgUser = await SetUserEmail2FaIfOrgPolicyEnabledAsync ( orgUserId , user ) ;
115+ if ( orgUser == null && orgUserId . HasValue )
116+ {
117+ throw new BadRequestException ( "Invalid organization user invitation." ) ;
118+ }
119+ await ValidateEmailDomainNotBlockedAsync ( user . Email , orgUser ? . OrganizationId ) ;
105120
106121 user . ApiKey = CoreHelpers . SecureRandomString ( 30 ) ;
107122
@@ -265,6 +280,8 @@ public async Task<IdentityResult> RegisterUserViaEmailVerificationToken(User use
265280 string emailVerificationToken )
266281 {
267282 ValidateOpenRegistrationAllowed ( ) ;
283+ await ValidateEmailDomainNotBlockedAsync ( user . Email ) ;
284+
268285 var tokenable = ValidateRegistrationEmailVerificationTokenable ( emailVerificationToken , user . Email ) ;
269286
270287 user . EmailVerified = true ;
@@ -284,6 +301,7 @@ public async Task<IdentityResult> RegisterUserViaOrganizationSponsoredFreeFamily
284301 string orgSponsoredFreeFamilyPlanInviteToken )
285302 {
286303 ValidateOpenRegistrationAllowed ( ) ;
304+ await ValidateEmailDomainNotBlockedAsync ( user . Email ) ;
287305 await ValidateOrgSponsoredFreeFamilyPlanInviteToken ( orgSponsoredFreeFamilyPlanInviteToken , user . Email ) ;
288306
289307 user . EmailVerified = true ;
@@ -304,6 +322,7 @@ public async Task<IdentityResult> RegisterUserViaAcceptEmergencyAccessInviteToke
304322 string acceptEmergencyAccessInviteToken , Guid acceptEmergencyAccessId )
305323 {
306324 ValidateOpenRegistrationAllowed ( ) ;
325+ await ValidateEmailDomainNotBlockedAsync ( user . Email ) ;
307326 ValidateAcceptEmergencyAccessInviteToken ( acceptEmergencyAccessInviteToken , acceptEmergencyAccessId , user . Email ) ;
308327
309328 user . EmailVerified = true ;
@@ -322,6 +341,7 @@ public async Task<IdentityResult> RegisterUserViaProviderInviteToken(User user,
322341 string providerInviteToken , Guid providerUserId )
323342 {
324343 ValidateOpenRegistrationAllowed ( ) ;
344+ await ValidateEmailDomainNotBlockedAsync ( user . Email ) ;
325345 ValidateProviderInviteToken ( providerInviteToken , providerUserId , user . Email ) ;
326346
327347 user . EmailVerified = true ;
@@ -387,6 +407,28 @@ private RegistrationEmailVerificationTokenable ValidateRegistrationEmailVerifica
387407 return tokenable ;
388408 }
389409
410+ private async Task ValidateEmailDomainNotBlockedAsync ( string email , Guid ? excludeOrganizationId = null )
411+ {
412+ // Only check if feature flag is enabled
413+ if ( ! _featureService . IsEnabled ( FeatureFlagKeys . BlockClaimedDomainAccountCreation ) )
414+ {
415+ return ;
416+ }
417+
418+ var emailDomain = EmailValidation . GetDomain ( email ) ;
419+
420+ var isDomainBlocked = await _organizationDomainRepository . HasVerifiedDomainWithBlockClaimedDomainPolicyAsync (
421+ emailDomain , excludeOrganizationId ) ;
422+ if ( isDomainBlocked )
423+ {
424+ _logger . LogInformation (
425+ "User registration blocked by domain claim policy. Domain: {Domain}, ExcludedOrgId: {ExcludedOrgId}" ,
426+ emailDomain ,
427+ excludeOrganizationId ) ;
428+ throw new BadRequestException ( "This email address is claimed by an organization using Bitwarden." ) ;
429+ }
430+ }
431+
390432 /// <summary>
391433 /// We send different welcome emails depending on whether the user is joining a free/family or an enterprise organization. If information to populate the
392434 /// email isn't present we send the standard individual welcome email.
0 commit comments