You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
10 KiB
295 lines
10 KiB
using Bit.Api.Auth.Controllers; |
|
using Bit.Api.Auth.Models.Request; |
|
using Bit.Api.Auth.Models.Request.Accounts; |
|
using Bit.Api.Auth.Models.Response.TwoFactor; |
|
using Bit.Core.AdminConsole.Entities; |
|
using Bit.Core.Auth.Identity.TokenProviders; |
|
using Bit.Core.Context; |
|
using Bit.Core.Entities; |
|
using Bit.Core.Exceptions; |
|
using Bit.Core.Repositories; |
|
using Bit.Core.Services; |
|
using Bit.Test.Common.AutoFixture; |
|
using Bit.Test.Common.AutoFixture.Attributes; |
|
using NSubstitute; |
|
using Xunit; |
|
|
|
namespace Bit.Api.Test.Auth.Controllers; |
|
|
|
[ControllerCustomize(typeof(TwoFactorController))] |
|
[SutProviderCustomize] |
|
public class TwoFactorControllerTests |
|
{ |
|
[Theory, BitAutoData] |
|
public async Task CheckAsync_UserNull_ThrowsUnauthorizedException(SecretVerificationRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
sutProvider.GetDependency<IUserService>() |
|
.GetUserByPrincipalAsync(default) |
|
.ReturnsForAnyArgs(null as User); |
|
|
|
// Act |
|
var result = () => sutProvider.Sut.GetDuo(request); |
|
|
|
// Assert |
|
await Assert.ThrowsAsync<UnauthorizedAccessException>(result); |
|
} |
|
|
|
[Theory, BitAutoData] |
|
public async Task CheckAsync_BadSecret_ThrowsBadRequestException(User user, SecretVerificationRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
sutProvider.GetDependency<IUserService>() |
|
.GetUserByPrincipalAsync(default) |
|
.ReturnsForAnyArgs(user); |
|
|
|
sutProvider.GetDependency<IUserService>() |
|
.VerifySecretAsync(default, default) |
|
.ReturnsForAnyArgs(false); |
|
|
|
// Act |
|
try |
|
{ |
|
await sutProvider.Sut.GetDuo(request); |
|
} |
|
catch (BadRequestException e) |
|
{ |
|
// Assert |
|
Assert.Equal("The model state is invalid.", e.Message); |
|
} |
|
} |
|
|
|
[Theory, BitAutoData] |
|
public async Task CheckAsync_CannotAccessPremium_ThrowsBadRequestException(User user, SecretVerificationRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
sutProvider.GetDependency<IUserService>() |
|
.GetUserByPrincipalAsync(default) |
|
.ReturnsForAnyArgs(user); |
|
|
|
sutProvider.GetDependency<IUserService>() |
|
.VerifySecretAsync(default, default) |
|
.ReturnsForAnyArgs(true); |
|
|
|
sutProvider.GetDependency<IUserService>() |
|
.CanAccessPremium(default) |
|
.ReturnsForAnyArgs(false); |
|
|
|
// Act |
|
try |
|
{ |
|
await sutProvider.Sut.GetDuo(request); |
|
} |
|
catch (BadRequestException e) |
|
{ |
|
// Assert |
|
Assert.Equal("Premium status is required.", e.Message); |
|
} |
|
} |
|
|
|
[Theory, BitAutoData] |
|
public async Task GetDuo_Success(User user, SecretVerificationRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
user.TwoFactorProviders = GetUserTwoFactorDuoProvidersJson(); |
|
SetupCheckAsyncToPass(sutProvider, user); |
|
|
|
// Act |
|
var result = await sutProvider.Sut.GetDuo(request); |
|
|
|
// Assert |
|
Assert.NotNull(result); |
|
Assert.IsType<TwoFactorDuoResponseModel>(result); |
|
} |
|
|
|
[Theory, BitAutoData] |
|
public async Task PutDuo_InvalidConfiguration_ThrowsBadRequestException(User user, UpdateTwoFactorDuoRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
SetupCheckAsyncToPass(sutProvider, user); |
|
sutProvider.GetDependency<IDuoUniversalTokenService>() |
|
.ValidateDuoConfiguration(default, default, default) |
|
.Returns(false); |
|
|
|
// Act |
|
try |
|
{ |
|
await sutProvider.Sut.PutDuo(request); |
|
} |
|
catch (BadRequestException e) |
|
{ |
|
// Assert |
|
Assert.Equal("Duo configuration settings are not valid. Please re-check the Duo Admin panel.", e.Message); |
|
} |
|
} |
|
|
|
[Theory, BitAutoData] |
|
public async Task PutDuo_Success(User user, UpdateTwoFactorDuoRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
user.TwoFactorProviders = GetUserTwoFactorDuoProvidersJson(); |
|
SetupCheckAsyncToPass(sutProvider, user); |
|
|
|
sutProvider.GetDependency<IDuoUniversalTokenService>() |
|
.ValidateDuoConfiguration(default, default, default) |
|
.ReturnsForAnyArgs(true); |
|
|
|
// Act |
|
var result = await sutProvider.Sut.PutDuo(request); |
|
|
|
// Assert |
|
Assert.NotNull(result); |
|
Assert.IsType<TwoFactorDuoResponseModel>(result); |
|
Assert.Equal(user.TwoFactorProviders, request.ToUser(user).TwoFactorProviders); |
|
} |
|
|
|
[Theory, BitAutoData] |
|
public async Task CheckOrganizationAsync_ManagePolicies_ThrowsNotFoundException( |
|
User user, Organization organization, SecretVerificationRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
organization.TwoFactorProviders = GetOrganizationTwoFactorDuoProvidersJson(); |
|
SetupCheckAsyncToPass(sutProvider, user); |
|
|
|
sutProvider.GetDependency<ICurrentContext>() |
|
.ManagePolicies(default) |
|
.ReturnsForAnyArgs(false); |
|
|
|
// Act |
|
var result = () => sutProvider.Sut.GetOrganizationDuo(organization.Id.ToString(), request); |
|
|
|
// Assert |
|
await Assert.ThrowsAsync<NotFoundException>(result); |
|
} |
|
|
|
[Theory, BitAutoData] |
|
public async Task CheckOrganizationAsync_GetByIdAsync_ThrowsNotFoundException( |
|
User user, Organization organization, SecretVerificationRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
organization.TwoFactorProviders = GetOrganizationTwoFactorDuoProvidersJson(); |
|
SetupCheckAsyncToPass(sutProvider, user); |
|
|
|
sutProvider.GetDependency<ICurrentContext>() |
|
.ManagePolicies(default) |
|
.ReturnsForAnyArgs(true); |
|
|
|
sutProvider.GetDependency<IOrganizationRepository>() |
|
.GetByIdAsync(default) |
|
.ReturnsForAnyArgs(null as Organization); |
|
|
|
// Act |
|
var result = () => sutProvider.Sut.GetOrganizationDuo(organization.Id.ToString(), request); |
|
|
|
// Assert |
|
await Assert.ThrowsAsync<NotFoundException>(result); |
|
} |
|
|
|
[Theory, BitAutoData] |
|
public async Task GetOrganizationDuo_Success( |
|
User user, Organization organization, SecretVerificationRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
organization.TwoFactorProviders = GetOrganizationTwoFactorDuoProvidersJson(); |
|
SetupCheckAsyncToPass(sutProvider, user); |
|
SetupCheckOrganizationAsyncToPass(sutProvider, organization); |
|
|
|
// Act |
|
var result = await sutProvider.Sut.GetOrganizationDuo(organization.Id.ToString(), request); |
|
|
|
// Assert |
|
Assert.NotNull(result); |
|
Assert.IsType<TwoFactorDuoResponseModel>(result); |
|
} |
|
|
|
[Theory, BitAutoData] |
|
public async Task PutOrganizationDuo_InvalidConfiguration_ThrowsBadRequestException( |
|
User user, Organization organization, UpdateTwoFactorDuoRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
SetupCheckAsyncToPass(sutProvider, user); |
|
SetupCheckOrganizationAsyncToPass(sutProvider, organization); |
|
|
|
sutProvider.GetDependency<IDuoUniversalTokenService>() |
|
.ValidateDuoConfiguration(default, default, default) |
|
.ReturnsForAnyArgs(false); |
|
|
|
// Act |
|
try |
|
{ |
|
await sutProvider.Sut.PutOrganizationDuo(organization.Id.ToString(), request); |
|
} |
|
catch (BadRequestException e) |
|
{ |
|
// Assert |
|
Assert.Equal("Duo configuration settings are not valid. Please re-check the Duo Admin panel.", e.Message); |
|
} |
|
} |
|
|
|
[Theory, BitAutoData] |
|
public async Task PutOrganizationDuo_Success( |
|
User user, Organization organization, UpdateTwoFactorDuoRequestModel request, SutProvider<TwoFactorController> sutProvider) |
|
{ |
|
// Arrange |
|
SetupCheckAsyncToPass(sutProvider, user); |
|
SetupCheckOrganizationAsyncToPass(sutProvider, organization); |
|
organization.TwoFactorProviders = GetUserTwoFactorDuoProvidersJson(); |
|
|
|
sutProvider.GetDependency<IDuoUniversalTokenService>() |
|
.ValidateDuoConfiguration(default, default, default) |
|
.ReturnsForAnyArgs(true); |
|
|
|
// Act |
|
var result = |
|
await sutProvider.Sut.PutOrganizationDuo(organization.Id.ToString(), request); |
|
|
|
// Assert |
|
Assert.NotNull(result); |
|
Assert.IsType<TwoFactorDuoResponseModel>(result); |
|
Assert.Equal(organization.TwoFactorProviders, request.ToOrganization(organization).TwoFactorProviders); |
|
} |
|
|
|
|
|
private string GetUserTwoFactorDuoProvidersJson() |
|
{ |
|
return |
|
"{\"2\":{\"Enabled\":true,\"MetaData\":{\"ClientSecret\":\"secretClientSecret\",\"ClientId\":\"clientId\",\"Host\":\"example.com\"}}}"; |
|
} |
|
|
|
private string GetOrganizationTwoFactorDuoProvidersJson() |
|
{ |
|
return |
|
"{\"6\":{\"Enabled\":true,\"MetaData\":{\"ClientSecret\":\"secretClientSecret\",\"ClientId\":\"clientId\",\"Host\":\"example.com\"}}}"; |
|
} |
|
|
|
/// <summary> |
|
/// Sets up the CheckAsync method to pass. |
|
/// </summary> |
|
/// <param name="sutProvider">uses bit auto data</param> |
|
/// <param name="user">uses bit auto data</param> |
|
private void SetupCheckAsyncToPass(SutProvider<TwoFactorController> sutProvider, User user) |
|
{ |
|
sutProvider.GetDependency<IUserService>() |
|
.GetUserByPrincipalAsync(default) |
|
.ReturnsForAnyArgs(user); |
|
|
|
sutProvider.GetDependency<IUserService>() |
|
.VerifySecretAsync(default, default) |
|
.ReturnsForAnyArgs(true); |
|
|
|
sutProvider.GetDependency<IUserService>() |
|
.CanAccessPremium(default) |
|
.ReturnsForAnyArgs(true); |
|
} |
|
|
|
private void SetupCheckOrganizationAsyncToPass(SutProvider<TwoFactorController> sutProvider, Organization organization) |
|
{ |
|
sutProvider.GetDependency<ICurrentContext>() |
|
.ManagePolicies(default) |
|
.ReturnsForAnyArgs(true); |
|
|
|
sutProvider.GetDependency<IOrganizationRepository>() |
|
.GetByIdAsync(default) |
|
.ReturnsForAnyArgs(organization); |
|
} |
|
}
|
|
|