Skip to content

Commit 5f64fcb

Browse files
fix: update integration test user registration to match current registration; We need to keep the IRegistrationCommand.RegisterUser method to JIT user.
1 parent 7e0d322 commit 5f64fcb

File tree

12 files changed

+452
-377
lines changed

12 files changed

+452
-377
lines changed

src/Core/Auth/UserFeatures/Registration/IRegisterUserCommand.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public interface IRegisterUserCommand
88

99
/// <summary>
1010
/// Creates a new user, sends a welcome email, and raises the signup reference event.
11+
/// This method is used for JIT of organization Users.
1112
/// </summary>
1213
/// <param name="user">The <see cref="User"/> to create</param>
1314
/// <returns><see cref="IdentityResult"/></returns>

test/Api.IntegrationTest/Factories/ApiApplicationFactory.cs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using Bit.Identity.Models.Request.Accounts;
1+
using Bit.Core;
2+
using Bit.Core.Auth.Models.Api.Request.Accounts;
3+
using Bit.Core.Enums;
24
using Bit.IntegrationTestCommon.Factories;
35
using Microsoft.AspNetCore.Authentication.JwtBearer;
46
using Microsoft.AspNetCore.TestHost;
@@ -42,13 +44,23 @@ protected override void ConfigureWebHost(IWebHostBuilder builder)
4244
/// <summary>
4345
/// Helper for registering and logging in to a new account
4446
/// </summary>
45-
public async Task<(string Token, string RefreshToken)> LoginWithNewAccount(string email = "integration-test@bitwarden.com", string masterPasswordHash = "master_password_hash")
47+
public async Task<(string Token, string RefreshToken)> LoginWithNewAccount(
48+
string email = "integration-test@bitwarden.com", string masterPasswordHash = "master_password_hash")
4649
{
47-
await _identityApplicationFactory.RegisterAsync(new RegisterRequestModel
48-
{
49-
Email = email,
50-
MasterPasswordHash = masterPasswordHash,
51-
});
50+
await _identityApplicationFactory.RegisterNewIdentityFactoryUserAsync(
51+
new RegisterFinishRequestModel
52+
{
53+
Email = email,
54+
MasterPasswordHash = masterPasswordHash,
55+
Kdf = KdfType.PBKDF2_SHA256,
56+
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
57+
UserAsymmetricKeys = new KeysRequestModel()
58+
{
59+
PublicKey = "public_key",
60+
EncryptedPrivateKey = "private_key"
61+
},
62+
UserSymmetricKey = "sym_key",
63+
});
5264

5365
return await _identityApplicationFactory.TokenFromPasswordAsync(email, masterPasswordHash);
5466
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System.ComponentModel.DataAnnotations;
2+
using AutoFixture;
3+
using Bit.Core.Auth.Models.Api.Request.Accounts;
4+
using Bit.Core.Enums;
5+
using Bit.Core.Utilities;
6+
using Bit.Test.Common.AutoFixture.Attributes;
7+
8+
namespace Bit.Core.Test.Auth.AutoFixture;
9+
10+
internal class RegisterFinishRequestModelCustomization : ICustomization
11+
{
12+
[StrictEmailAddress, StringLength(256)]
13+
public required string Email { get; set; }
14+
public required KdfType Kdf { get; set; }
15+
public required int KdfIterations { get; set; }
16+
public string? EmailVerificationToken { get; set; }
17+
public string? OrgInviteToken { get; set; }
18+
public string? OrgSponsoredFreeFamilyPlanToken { get; set; }
19+
public string? AcceptEmergencyAccessInviteToken { get; set; }
20+
public string? ProviderInviteToken { get; set; }
21+
22+
public void Customize(IFixture fixture)
23+
{
24+
fixture.Customize<RegisterFinishRequestModel>(composer => composer
25+
.With(o => o.Email, Email)
26+
.With(o => o.Kdf, Kdf)
27+
.With(o => o.KdfIterations, KdfIterations)
28+
.With(o => o.EmailVerificationToken, EmailVerificationToken)
29+
.With(o => o.OrgInviteToken, OrgInviteToken)
30+
.With(o => o.OrgSponsoredFreeFamilyPlanToken, OrgSponsoredFreeFamilyPlanToken)
31+
.With(o => o.AcceptEmergencyAccessInviteToken, AcceptEmergencyAccessInviteToken)
32+
.With(o => o.ProviderInviteToken, ProviderInviteToken));
33+
}
34+
}
35+
36+
public class RegisterFinishRequestModelCustomizeAttribute : BitCustomizeAttribute
37+
{
38+
public string _email { get; set; } = "{0}@email.com";
39+
public KdfType _kdf { get; set; } = KdfType.PBKDF2_SHA256;
40+
public int _kdfIterations { get; set; } = AuthConstants.PBKDF2_ITERATIONS.Default;
41+
public string? _emailVerificationToken { get; set; }
42+
public string? _orgInviteToken { get; set; }
43+
public string? _orgSponsoredFreeFamilyPlanToken { get; set; }
44+
public string? _acceptEmergencyAccessInviteToken { get; set; }
45+
public string? _providerInviteToken { get; set; }
46+
47+
public override ICustomization GetCustomization() => new RegisterFinishRequestModelCustomization()
48+
{
49+
Email = _email,
50+
Kdf = _kdf,
51+
KdfIterations = _kdfIterations,
52+
EmailVerificationToken = _emailVerificationToken,
53+
OrgInviteToken = _orgInviteToken,
54+
OrgSponsoredFreeFamilyPlanToken = _orgSponsoredFreeFamilyPlanToken,
55+
AcceptEmergencyAccessInviteToken = _acceptEmergencyAccessInviteToken,
56+
ProviderInviteToken = _providerInviteToken
57+
};
58+
}

test/Events.IntegrationTest/EventsApplicationFactory.cs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using Bit.Identity.Models.Request.Accounts;
1+
using Bit.Core;
2+
using Bit.Core.Auth.Models.Api.Request.Accounts;
3+
using Bit.Core.Enums;
24
using Bit.IntegrationTestCommon.Factories;
35
using Microsoft.AspNetCore.Authentication.JwtBearer;
46
using Microsoft.AspNetCore.Hosting;
@@ -40,11 +42,20 @@ protected override void ConfigureWebHost(IWebHostBuilder builder)
4042
/// </summary>
4143
public async Task<(string Token, string RefreshToken)> LoginWithNewAccount(string email = "integration-test@bitwarden.com", string masterPasswordHash = "master_password_hash")
4244
{
43-
await _identityApplicationFactory.RegisterAsync(new RegisterRequestModel
44-
{
45-
Email = email,
46-
MasterPasswordHash = masterPasswordHash,
47-
});
45+
await _identityApplicationFactory.RegisterNewIdentityFactoryUserAsync(
46+
new RegisterFinishRequestModel
47+
{
48+
Email = email,
49+
MasterPasswordHash = masterPasswordHash,
50+
Kdf = KdfType.PBKDF2_SHA256,
51+
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
52+
UserAsymmetricKeys = new KeysRequestModel()
53+
{
54+
PublicKey = "public_key",
55+
EncryptedPrivateKey = "private_key"
56+
},
57+
UserSymmetricKey = "sym_key",
58+
});
4859

4960
return await _identityApplicationFactory.TokenFromPasswordAsync(email, masterPasswordHash);
5061
}

test/Identity.IntegrationTest/Controllers/AccountsControllerTests.cs

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88
using Bit.Core.Enums;
99
using Bit.Core.Models.Business.Tokenables;
1010
using Bit.Core.Repositories;
11-
using Bit.Core.Services;
1211
using Bit.Core.Tokens;
1312
using Bit.Core.Utilities;
14-
using Bit.Identity.Models.Request.Accounts;
1513
using Bit.IntegrationTestCommon.Factories;
1614
using Bit.Test.Common.AutoFixture.Attributes;
1715
using Microsoft.AspNetCore.DataProtection;
@@ -31,24 +29,6 @@ public AccountsControllerTests(IdentityApplicationFactory factory)
3129
_factory = factory;
3230
}
3331

34-
[Fact]
35-
public async Task PostRegister_Success()
36-
{
37-
var context = await _factory.RegisterAsync(new RegisterRequestModel
38-
{
39-
Email = "test+register@email.com",
40-
MasterPasswordHash = "master_password_hash"
41-
});
42-
43-
Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode);
44-
45-
var database = _factory.GetDatabaseContext();
46-
var user = await database.Users
47-
.SingleAsync(u => u.Email == "test+register@email.com");
48-
49-
Assert.NotNull(user);
50-
}
51-
5232
[Theory]
5333
[BitAutoData("invalidEmail")]
5434
[BitAutoData("")]
@@ -154,23 +134,14 @@ public async Task PostRegisterSendEmailVerification_WhenGivenNewOrExistingUser_W
154134
}
155135

156136
[Theory, BitAutoData]
137+
// marketing emails can stay at top level
157138
public async Task RegistrationWithEmailVerification_WithEmailVerificationToken_Succeeds([Required] string name, bool receiveMarketingEmails,
158139
[StringLength(1000), Required] string masterPasswordHash, [StringLength(50)] string masterPasswordHint, [Required] string userSymmetricKey,
159140
[Required] KeysRequestModel userAsymmetricKeys, int kdfMemory, int kdfParallelism)
160141
{
161142
// Localize substitutions to this test.
162143
var localFactory = new IdentityApplicationFactory();
163144

164-
// First we must substitute the mail service in order to be able to get a valid email verification token
165-
// for the complete registration step
166-
string capturedEmailVerificationToken = null;
167-
localFactory.SubstituteService<IMailService>(mailService =>
168-
{
169-
mailService.SendRegistrationVerificationEmailAsync(Arg.Any<string>(), Arg.Do<string>(t => capturedEmailVerificationToken = t))
170-
.Returns(Task.CompletedTask);
171-
172-
});
173-
174145
// we must first call the send verification email endpoint to trigger the first part of the process
175146
var email = $"test+register+{name}@email.com";
176147
var sendVerificationEmailReqModel = new RegisterSendVerificationEmailRequestModel
@@ -183,15 +154,15 @@ public async Task RegistrationWithEmailVerification_WithEmailVerificationToken_S
183154
var sendEmailVerificationResponseHttpContext = await localFactory.PostRegisterSendEmailVerificationAsync(sendVerificationEmailReqModel);
184155

185156
Assert.Equal(StatusCodes.Status204NoContent, sendEmailVerificationResponseHttpContext.Response.StatusCode);
186-
Assert.NotNull(capturedEmailVerificationToken);
157+
Assert.NotNull(localFactory.RegistrationTokens[email]);
187158

188159
// Now we call the finish registration endpoint with the email verification token
189160
var registerFinishReqModel = new RegisterFinishRequestModel
190161
{
191162
Email = email,
192163
MasterPasswordHash = masterPasswordHash,
193164
MasterPasswordHint = masterPasswordHint,
194-
EmailVerificationToken = capturedEmailVerificationToken,
165+
EmailVerificationToken = localFactory.RegistrationTokens[email],
195166
Kdf = KdfType.PBKDF2_SHA256,
196167
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
197168
UserSymmetricKey = userSymmetricKey,

test/Identity.IntegrationTest/Endpoints/IdentityServerSsoTests.cs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
using System.Security.Claims;
22
using System.Text.Json;
3+
using Bit.Core;
34
using Bit.Core.AdminConsole.Entities;
45
using Bit.Core.AdminConsole.Entities.Provider;
56
using Bit.Core.AdminConsole.Enums.Provider;
67
using Bit.Core.AdminConsole.Repositories;
78
using Bit.Core.Auth.Entities;
89
using Bit.Core.Auth.Enums;
10+
using Bit.Core.Auth.Models.Api.Request.Accounts;
911
using Bit.Core.Auth.Models.Data;
1012
using Bit.Core.Auth.Repositories;
1113
using Bit.Core.Entities;
1214
using Bit.Core.Enums;
1315
using Bit.Core.Models.Data;
1416
using Bit.Core.Repositories;
1517
using Bit.Core.Utilities;
16-
using Bit.Identity.Models.Request.Accounts;
1718
using Bit.IntegrationTestCommon.Factories;
1819
using Bit.Test.Common.Helpers;
1920
using Duende.IdentityModel;
@@ -545,16 +546,15 @@ private static async Task<IdentityApplicationFactory> CreateFactoryAsync(
545546
{
546547
var factory = new IdentityApplicationFactory();
547548

548-
549549
var authorizationCode = new AuthorizationCode
550550
{
551551
ClientId = "web",
552552
CreationTime = DateTime.UtcNow,
553553
Lifetime = (int)TimeSpan.FromMinutes(5).TotalSeconds,
554554
RedirectUri = "https://localhost:8080/sso-connector.html",
555-
RequestedScopes = new[] { "api", "offline_access" },
555+
RequestedScopes = ["api", "offline_access"],
556556
CodeChallenge = challenge.Sha256(),
557-
CodeChallengeMethod = "plain", //
557+
CodeChallengeMethod = "plain",
558558
Subject = null!, // Temporarily set it to null
559559
};
560560

@@ -564,16 +564,20 @@ private static async Task<IdentityApplicationFactory> CreateFactoryAsync(
564564
.Returns(authorizationCode);
565565
});
566566

567-
// This starts the server and finalizes services
568-
var registerResponse = await factory.RegisterAsync(new RegisterRequestModel
569-
{
570-
Email = TestEmail,
571-
MasterPasswordHash = "master_password_hash",
572-
});
573-
574-
var userRepository = factory.Services.GetRequiredService<IUserRepository>();
575-
var user = await userRepository.GetByEmailAsync(TestEmail);
576-
Assert.NotNull(user);
567+
var user = await factory.RegisterNewIdentityFactoryUserAsync(
568+
new RegisterFinishRequestModel
569+
{
570+
Email = TestEmail,
571+
MasterPasswordHash = "masterPasswordHash",
572+
Kdf = KdfType.PBKDF2_SHA256,
573+
KdfIterations = AuthConstants.PBKDF2_ITERATIONS.Default,
574+
UserAsymmetricKeys = new KeysRequestModel()
575+
{
576+
PublicKey = "public_key",
577+
EncryptedPrivateKey = "private_key"
578+
},
579+
UserSymmetricKey = "sym_key",
580+
});
577581

578582
var organizationRepository = factory.Services.GetRequiredService<IOrganizationRepository>();
579583
var organization = await organizationRepository.CreateAsync(new Organization

0 commit comments

Comments
 (0)