Skip to content

Commit 8f0886b

Browse files
kspearrinike-kottlowski
authored andcommitted
[PM-30391] fix for org context on sso provisioning (#6797)
* fix for org context on sso provisioning * tests are no longer needed since there is no logic on feature flag * lint fixes (cherry picked from commit 2442d2d)
1 parent 8a79bfa commit 8f0886b

File tree

2 files changed

+4
-145
lines changed

2 files changed

+4
-145
lines changed

bitwarden_license/src/Sso/Controllers/AccountController.cs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -680,22 +680,10 @@ await _organizationService.AdjustSeatsAsync(organization.Id,
680680
ApiKey = CoreHelpers.SecureRandomString(30)
681681
};
682682

683-
/*
684-
The feature flag is checked here so that we can send the new MJML welcome email templates.
685-
The other organization invites flows have an OrganizationUser allowing the RegisterUserCommand the ability
686-
to fetch the Organization. The old method RegisterUser(User) here does not have that context, so we need
687-
to use a new method RegisterSSOAutoProvisionedUserAsync(User, Organization) to send the correct email.
688-
[PM-28057]: Prefer RegisterSSOAutoProvisionedUserAsync for SSO auto-provisioned users.
689-
TODO: Remove Feature flag: PM-28221
690-
*/
691-
if (_featureService.IsEnabled(FeatureFlagKeys.MjmlWelcomeEmailTemplates))
692-
{
693-
await _registerUserCommand.RegisterSSOAutoProvisionedUserAsync(newUser, organization);
694-
}
695-
else
696-
{
697-
await _registerUserCommand.RegisterUser(newUser);
698-
}
683+
// Always use RegisterSSOAutoProvisionedUserAsync to ensure organization context is available
684+
// for domain validation (BlockClaimedDomainAccountCreation policy) and welcome emails.
685+
// The feature flag logic for welcome email templates is handled internally by RegisterUserCommand.
686+
await _registerUserCommand.RegisterSSOAutoProvisionedUserAsync(newUser, organization);
699687

700688
// If the organization has 2fa policy enabled, make sure to default jit user 2fa to email
701689
var twoFactorPolicy =

bitwarden_license/test/SSO.Test/Controllers/AccountControllerTest.cs

Lines changed: 0 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using Bit.Core.Auth.Models.Business.Tokenables;
77
using Bit.Core.Auth.Models.Data;
88
using Bit.Core.Auth.Repositories;
9-
using Bit.Core.Auth.UserFeatures.Registration;
109
using Bit.Core.Entities;
1110
using Bit.Core.Enums;
1211
using Bit.Core.Repositories;
@@ -21,7 +20,6 @@
2120
using Duende.IdentityServer.Services;
2221
using Microsoft.AspNetCore.Authentication;
2322
using Microsoft.AspNetCore.Http;
24-
using Microsoft.AspNetCore.Identity;
2523
using Microsoft.AspNetCore.Mvc;
2624
using Microsoft.Extensions.DependencyInjection;
2725
using NSubstitute;
@@ -1013,133 +1011,6 @@ public async Task ExternalCallback_Measurements_FlagOnVsOff_Comparisons(
10131011
}
10141012
}
10151013

1016-
[Theory, BitAutoData]
1017-
public async Task AutoProvisionUserAsync_WithFeatureFlagEnabled_CallsRegisterSSOAutoProvisionedUser(
1018-
SutProvider<AccountController> sutProvider)
1019-
{
1020-
// Arrange
1021-
var orgId = Guid.NewGuid();
1022-
var providerUserId = "ext-new-user";
1023-
var email = "[email protected]";
1024-
var organization = new Organization { Id = orgId, Name = "Test Org", Seats = null };
1025-
1026-
// No existing user (JIT provisioning scenario)
1027-
sutProvider.GetDependency<IUserRepository>().GetByEmailAsync(email).Returns((User?)null);
1028-
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(orgId).Returns(organization);
1029-
sutProvider.GetDependency<IOrganizationUserRepository>().GetByOrganizationEmailAsync(orgId, email)
1030-
.Returns((OrganizationUser?)null);
1031-
1032-
// Feature flag enabled
1033-
sutProvider.GetDependency<IFeatureService>()
1034-
.IsEnabled(FeatureFlagKeys.MjmlWelcomeEmailTemplates)
1035-
.Returns(true);
1036-
1037-
// Mock the RegisterSSOAutoProvisionedUserAsync to return success
1038-
sutProvider.GetDependency<IRegisterUserCommand>()
1039-
.RegisterSSOAutoProvisionedUserAsync(Arg.Any<User>(), Arg.Any<Organization>())
1040-
.Returns(IdentityResult.Success);
1041-
1042-
var claims = new[]
1043-
{
1044-
new Claim(JwtClaimTypes.Email, email),
1045-
new Claim(JwtClaimTypes.Name, "New User")
1046-
} as IEnumerable<Claim>;
1047-
var config = new SsoConfigurationData();
1048-
1049-
var method = typeof(AccountController).GetMethod(
1050-
"CreateUserAndOrgUserConditionallyAsync",
1051-
BindingFlags.Instance | BindingFlags.NonPublic);
1052-
Assert.NotNull(method);
1053-
1054-
// Act
1055-
var task = (Task<(User user, Organization organization, OrganizationUser orgUser)>)method!.Invoke(
1056-
sutProvider.Sut,
1057-
new object[]
1058-
{
1059-
orgId.ToString(),
1060-
providerUserId,
1061-
claims,
1062-
null!,
1063-
config
1064-
})!;
1065-
1066-
var result = await task;
1067-
1068-
// Assert
1069-
await sutProvider.GetDependency<IRegisterUserCommand>().Received(1)
1070-
.RegisterSSOAutoProvisionedUserAsync(
1071-
Arg.Is<User>(u => u.Email == email && u.Name == "New User"),
1072-
Arg.Is<Organization>(o => o.Id == orgId && o.Name == "Test Org"));
1073-
1074-
Assert.NotNull(result.user);
1075-
Assert.Equal(email, result.user.Email);
1076-
Assert.Equal(organization.Id, result.organization.Id);
1077-
}
1078-
1079-
[Theory, BitAutoData]
1080-
public async Task AutoProvisionUserAsync_WithFeatureFlagDisabled_CallsRegisterUserInstead(
1081-
SutProvider<AccountController> sutProvider)
1082-
{
1083-
// Arrange
1084-
var orgId = Guid.NewGuid();
1085-
var providerUserId = "ext-legacy-user";
1086-
var email = "[email protected]";
1087-
var organization = new Organization { Id = orgId, Name = "Test Org", Seats = null };
1088-
1089-
// No existing user (JIT provisioning scenario)
1090-
sutProvider.GetDependency<IUserRepository>().GetByEmailAsync(email).Returns((User?)null);
1091-
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(orgId).Returns(organization);
1092-
sutProvider.GetDependency<IOrganizationUserRepository>().GetByOrganizationEmailAsync(orgId, email)
1093-
.Returns((OrganizationUser?)null);
1094-
1095-
// Feature flag disabled
1096-
sutProvider.GetDependency<IFeatureService>()
1097-
.IsEnabled(FeatureFlagKeys.MjmlWelcomeEmailTemplates)
1098-
.Returns(false);
1099-
1100-
// Mock the RegisterUser to return success
1101-
sutProvider.GetDependency<IRegisterUserCommand>()
1102-
.RegisterUser(Arg.Any<User>())
1103-
.Returns(IdentityResult.Success);
1104-
1105-
var claims = new[]
1106-
{
1107-
new Claim(JwtClaimTypes.Email, email),
1108-
new Claim(JwtClaimTypes.Name, "Legacy User")
1109-
} as IEnumerable<Claim>;
1110-
var config = new SsoConfigurationData();
1111-
1112-
var method = typeof(AccountController).GetMethod(
1113-
"CreateUserAndOrgUserConditionallyAsync",
1114-
BindingFlags.Instance | BindingFlags.NonPublic);
1115-
Assert.NotNull(method);
1116-
1117-
// Act
1118-
var task = (Task<(User user, Organization organization, OrganizationUser orgUser)>)method!.Invoke(
1119-
sutProvider.Sut,
1120-
new object[]
1121-
{
1122-
orgId.ToString(),
1123-
providerUserId,
1124-
claims,
1125-
null!,
1126-
config
1127-
})!;
1128-
1129-
var result = await task;
1130-
1131-
// Assert
1132-
await sutProvider.GetDependency<IRegisterUserCommand>().Received(1)
1133-
.RegisterUser(Arg.Is<User>(u => u.Email == email && u.Name == "Legacy User"));
1134-
1135-
// Verify the new method was NOT called
1136-
await sutProvider.GetDependency<IRegisterUserCommand>().DidNotReceive()
1137-
.RegisterSSOAutoProvisionedUserAsync(Arg.Any<User>(), Arg.Any<Organization>());
1138-
1139-
Assert.NotNull(result.user);
1140-
Assert.Equal(email, result.user.Email);
1141-
}
1142-
11431014
[Theory, BitAutoData]
11441015
public void ExternalChallenge_WithMatchingOrgId_Succeeds(
11451016
SutProvider<AccountController> sutProvider,

0 commit comments

Comments
 (0)