1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-15 23:40:48 -05:00
bitwarden/test/Core.Test/Auth/Services/TwoFactorEmailServiceTests.cs
2025-06-14 11:47:26 -04:00

255 lines
10 KiB
C#

using Bit.Core.Auth.Enums;
using Bit.Core.Auth.Models;
using Bit.Core.Auth.Services;
using Bit.Core.Context;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Bit.Test.Common.AutoFixture;
using Bit.Test.Common.AutoFixture.Attributes;
using Core.Auth.Enums;
using Microsoft.AspNetCore.Identity;
using NSubstitute;
using Xunit;
namespace Bit.Core.Test.Auth.Services;
[SutProviderCustomize]
public class TwoFactorEmailServiceTests
{
[Theory, BitAutoData]
public async Task SendTwoFactorEmailAsync_Success(SutProvider<TwoFactorEmailService> sutProvider, User user)
{
var email = user.Email.ToLowerInvariant();
var token = "thisisatokentocompare";
var IpAddress = "1.1.1.1";
var deviceType = DeviceType.Android;
var context = sutProvider.GetDependency<ICurrentContext>();
context.DeviceType = deviceType;
context.IpAddress = IpAddress;
var userTwoFactorTokenProvider = Substitute.For<IUserTwoFactorTokenProvider<User>>();
userTwoFactorTokenProvider
.CanGenerateTwoFactorTokenAsync(Arg.Any<UserManager<User>>(), user)
.Returns(Task.FromResult(true));
userTwoFactorTokenProvider
.GenerateAsync("TwoFactor", Arg.Any<UserManager<User>>(), user)
.Returns(Task.FromResult(token));
var userManager = sutProvider.GetDependency<UserManager<User>>();
userManager.RegisterTokenProvider(CoreHelpers.CustomProviderName(TwoFactorProviderType.Email), userTwoFactorTokenProvider);
user.SetTwoFactorProviders(new Dictionary<TwoFactorProviderType, TwoFactorProvider>
{
[TwoFactorProviderType.Email] = new TwoFactorProvider
{
MetaData = new Dictionary<string, object> { ["Email"] = email },
Enabled = true
}
});
await sutProvider.Sut.SendTwoFactorEmailAsync(user);
await sutProvider.GetDependency<IMailService>()
.Received(1)
.SendTwoFactorEmailAsync(email, user.Email, token, IpAddress, deviceType.ToString(),
TwoFactorEmailPurpose.Login);
}
[Theory, BitAutoData]
public async Task SendTwoFactorSetupEmailAsync_Success(SutProvider<TwoFactorEmailService> sutProvider, User user)
{
var email = user.Email.ToLowerInvariant();
var token = "thisisatokentocompare";
var IpAddress = "1.1.1.1";
var deviceType = DeviceType.Android;
var context = sutProvider.GetDependency<ICurrentContext>();
context.DeviceType = deviceType;
context.IpAddress = IpAddress;
var userTwoFactorTokenProvider = Substitute.For<IUserTwoFactorTokenProvider<User>>();
userTwoFactorTokenProvider
.CanGenerateTwoFactorTokenAsync(Arg.Any<UserManager<User>>(), user)
.Returns(Task.FromResult(true));
userTwoFactorTokenProvider
.GenerateAsync("TwoFactor", Arg.Any<UserManager<User>>(), user)
.Returns(Task.FromResult(token));
var userManager = sutProvider.GetDependency<UserManager<User>>();
userManager.RegisterTokenProvider(CoreHelpers.CustomProviderName(TwoFactorProviderType.Email), userTwoFactorTokenProvider);
user.SetTwoFactorProviders(new Dictionary<TwoFactorProviderType, TwoFactorProvider>
{
[TwoFactorProviderType.Email] = new TwoFactorProvider
{
MetaData = new Dictionary<string, object> { ["Email"] = email },
Enabled = true
}
});
await sutProvider.Sut.SendTwoFactorEmailAsync(user);
await sutProvider.GetDependency<IMailService>()
.Received(1)
.SendTwoFactorEmailAsync(email, user.Email, token, IpAddress, deviceType.ToString(),
TwoFactorEmailPurpose.Login);
}
[Theory, BitAutoData]
public async Task SendNewDeviceVerificationEmailAsync_Success(SutProvider<TwoFactorEmailService> sutProvider, User user)
{
var email = user.Email.ToLowerInvariant();
var token = "thisisatokentocompare";
var IpAddress = "1.1.1.1";
var deviceType = DeviceType.Android;
var context = sutProvider.GetDependency<ICurrentContext>();
context.DeviceType = deviceType;
context.IpAddress = IpAddress;
var userTwoFactorTokenProvider = Substitute.For<IUserTwoFactorTokenProvider<User>>();
userTwoFactorTokenProvider
.CanGenerateTwoFactorTokenAsync(Arg.Any<UserManager<User>>(), user)
.Returns(Task.FromResult(true));
userTwoFactorTokenProvider
.GenerateAsync("otp:" + user.Email, Arg.Any<UserManager<User>>(), user)
.Returns(Task.FromResult(token));
var userManager = sutProvider.GetDependency<UserManager<User>>();
userManager.RegisterTokenProvider(TokenOptions.DefaultEmailProvider, userTwoFactorTokenProvider);
await sutProvider.Sut.SendNewDeviceVerificationEmailAsync(user);
await sutProvider.GetDependency<IMailService>()
.Received(1)
.SendTwoFactorEmailAsync(email, user.Email, token, IpAddress, deviceType.ToString(),
TwoFactorEmailPurpose.NewDeviceVerification);
}
[Theory, BitAutoData]
public async Task SendTwoFactorEmailAsync_ExceptionBecauseNoProviderOnUser(SutProvider<TwoFactorEmailService> sutProvider, User user)
{
user.TwoFactorProviders = null;
await Assert.ThrowsAsync<ArgumentNullException>("No email.", () => sutProvider.Sut.SendTwoFactorEmailAsync(user));
}
[Theory, BitAutoData]
public async Task SendTwoFactorEmailAsync_ExceptionBecauseNoProviderMetadataOnUser(SutProvider<TwoFactorEmailService> sutProvider, User user)
{
user.SetTwoFactorProviders(new Dictionary<TwoFactorProviderType, TwoFactorProvider>
{
[TwoFactorProviderType.Email] = new TwoFactorProvider
{
MetaData = null,
Enabled = true
}
});
await Assert.ThrowsAsync<ArgumentNullException>("No email.", () => sutProvider.Sut.SendTwoFactorEmailAsync(user));
}
[Theory, BitAutoData]
public async Task SendTwoFactorEmailAsync_ExceptionBecauseNoProviderEmailMetadataOnUser(SutProvider<TwoFactorEmailService> sutProvider, User user)
{
user.SetTwoFactorProviders(new Dictionary<TwoFactorProviderType, TwoFactorProvider>
{
[TwoFactorProviderType.Email] = new TwoFactorProvider
{
MetaData = new Dictionary<string, object> { ["qweqwe"] = user.Email.ToLowerInvariant() },
Enabled = true
}
});
await Assert.ThrowsAsync<ArgumentNullException>("No email.", () => sutProvider.Sut.SendTwoFactorEmailAsync(user));
}
[Theory, BitAutoData]
public async Task SendNewDeviceVerificationEmailAsync_ExceptionBecauseUserNull(SutProvider<TwoFactorEmailService> sutProvider)
{
await Assert.ThrowsAsync<ArgumentNullException>(() => sutProvider.Sut.SendNewDeviceVerificationEmailAsync(null));
}
[Theory]
[BitAutoData(DeviceType.UnknownBrowser, "Unknown Browser")]
[BitAutoData(DeviceType.Android, "Android")]
public async Task SendTwoFactorEmailAsync_DeviceMatches(DeviceType deviceType, string deviceTypeName,
SutProvider<TwoFactorEmailService> sutProvider,
User user)
{
var email = user.Email.ToLowerInvariant();
var token = "thisisatokentocompare";
var IpAddress = "1.1.1.1";
var context = sutProvider.GetDependency<ICurrentContext>();
context.DeviceType = deviceType;
context.IpAddress = IpAddress;
var userTwoFactorTokenProvider = Substitute.For<IUserTwoFactorTokenProvider<User>>();
userTwoFactorTokenProvider
.CanGenerateTwoFactorTokenAsync(Arg.Any<UserManager<User>>(), user)
.Returns(Task.FromResult(true));
userTwoFactorTokenProvider
.GenerateAsync("TwoFactor", Arg.Any<UserManager<User>>(), user)
.Returns(Task.FromResult(token));
var userManager = sutProvider.GetDependency<UserManager<User>>();
userManager.RegisterTokenProvider(CoreHelpers.CustomProviderName(TwoFactorProviderType.Email), userTwoFactorTokenProvider);
user.SetTwoFactorProviders(new Dictionary<TwoFactorProviderType, TwoFactorProvider>
{
[TwoFactorProviderType.Email] = new TwoFactorProvider
{
MetaData = new Dictionary<string, object> { ["Email"] = email },
Enabled = true
}
});
await sutProvider.Sut.SendTwoFactorEmailAsync(user);
await sutProvider.GetDependency<IMailService>()
.Received(1)
.SendTwoFactorEmailAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(), deviceTypeName, TwoFactorEmailPurpose.Login);
}
[Theory, BitAutoData]
public async Task SendTwoFactorEmailAsync_NullDeviceTypeShouldSendUnkownBrowserType(SutProvider<TwoFactorEmailService> sutProvider, User user)
{
var email = user.Email.ToLowerInvariant();
var token = "thisisatokentocompare";
var IpAddress = "1.1.1.1";
var userTwoFactorTokenProvider = Substitute.For<IUserTwoFactorTokenProvider<User>>();
userTwoFactorTokenProvider
.CanGenerateTwoFactorTokenAsync(Arg.Any<UserManager<User>>(), user)
.Returns(Task.FromResult(true));
userTwoFactorTokenProvider
.GenerateAsync("TwoFactor", Arg.Any<UserManager<User>>(), user)
.Returns(Task.FromResult(token));
var context = Substitute.For<ICurrentContext>();
context.DeviceType = null;
context.IpAddress = IpAddress;
var userManager = sutProvider.GetDependency<UserManager<User>>();
userManager.RegisterTokenProvider(CoreHelpers.CustomProviderName(TwoFactorProviderType.Email), userTwoFactorTokenProvider);
user.SetTwoFactorProviders(new Dictionary<TwoFactorProviderType, TwoFactorProvider>
{
[TwoFactorProviderType.Email] = new TwoFactorProvider
{
MetaData = new Dictionary<string, object> { ["Email"] = email },
Enabled = true
}
});
await sutProvider.Sut.SendTwoFactorEmailAsync(user);
await sutProvider.GetDependency<IMailService>()
.Received(1)
.SendTwoFactorEmailAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(), "Unknown Browser", Arg.Any<TwoFactorEmailPurpose>());
}
}