mirror of
https://github.com/bitwarden/server.git
synced 2024-12-12 15:26:48 +01:00
296 lines
10 KiB
C#
296 lines
10 KiB
C#
|
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);
|
|||
|
}
|
|||
|
}
|