mirror of
https://github.com/bitwarden/server
synced 2025-12-10 21:33:41 +00:00
* feat: add static enumeration helper class * test: add enumeration helper class unit tests * feat: implement NeverAuthenticateValidator * test: unit and integration tests SendNeverAuthenticateValidator * test: use static class for common integration test setup for Send Access unit and integration tests * test: update tests to use static helper
169 lines
6.3 KiB
C#
169 lines
6.3 KiB
C#
using Bit.Core.Services;
|
|
using Bit.Core.Tools.Models.Data;
|
|
using Bit.Core.Tools.SendFeatures.Queries.Interfaces;
|
|
using Bit.Core.Utilities;
|
|
using Bit.Identity.IdentityServer.RequestValidators.SendAccess;
|
|
using Bit.IntegrationTestCommon.Factories;
|
|
using Duende.IdentityModel;
|
|
using NSubstitute;
|
|
using Xunit;
|
|
|
|
namespace Bit.Identity.IntegrationTest.RequestValidation.SendAccess;
|
|
|
|
public class SendNeverAuthenticateRequestValidatorIntegrationTests(
|
|
IdentityApplicationFactory _factory) : IClassFixture<IdentityApplicationFactory>
|
|
{
|
|
/// <summary>
|
|
/// To support the static hashing function <see cref="EnumerationProtectionHelpers.GetIndexForInputHash"/> theses GUIDs and Key must be hardcoded
|
|
/// </summary>
|
|
private static readonly string _testHashKey = "test-key-123456789012345678901234567890";
|
|
// These Guids are static and ensure the correct index for each error type
|
|
private static readonly Guid _invalidSendGuid = Guid.Parse("1b35fbf3-a14a-4d48-82b7-2adc34fdae6f");
|
|
private static readonly Guid _emailSendGuid = Guid.Parse("bc8e2ef5-a0bd-44d2-bdb7-5902be6f5c41");
|
|
private static readonly Guid _passwordSendGuid = Guid.Parse("da36fa27-f0e8-4701-a585-d3d8c2f67c4b");
|
|
|
|
[Fact]
|
|
public async Task SendAccess_NeverAuthenticateSend_NoParameters_ReturnsInvalidSendId()
|
|
{
|
|
// Arrange
|
|
var client = ConfigureTestHttpClient(_invalidSendGuid);
|
|
var requestBody = SendAccessTestUtilities.CreateTokenRequestBody(_invalidSendGuid);
|
|
|
|
// Act
|
|
var response = await client.PostAsync("/connect/token", requestBody);
|
|
|
|
// Assert
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
Assert.Contains(OidcConstants.TokenErrors.InvalidGrant, content);
|
|
|
|
var expectedError = SendAccessConstants.SendIdGuidValidatorResults.InvalidSendId;
|
|
Assert.Contains(expectedError, content);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SendAccess_NeverAuthenticateSend_ReturnsEmailRequired()
|
|
{
|
|
// Arrange
|
|
var client = ConfigureTestHttpClient(_emailSendGuid);
|
|
var requestBody = SendAccessTestUtilities.CreateTokenRequestBody(_emailSendGuid);
|
|
|
|
// Act
|
|
var response = await client.PostAsync("/connect/token", requestBody);
|
|
|
|
// Assert
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
// should be invalid grant
|
|
Assert.Contains(OidcConstants.TokenErrors.InvalidRequest, content);
|
|
|
|
// Try to compel the invalid email error
|
|
var expectedError = SendAccessConstants.EmailOtpValidatorResults.EmailRequired;
|
|
Assert.Contains(expectedError, content);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SendAccess_NeverAuthenticateSend_WithEmail_ReturnsEmailInvalid()
|
|
{
|
|
// Arrange
|
|
var email = "test@example.com";
|
|
var client = ConfigureTestHttpClient(_emailSendGuid);
|
|
var requestBody = SendAccessTestUtilities.CreateTokenRequestBody(_emailSendGuid, email: email);
|
|
|
|
// Act
|
|
var response = await client.PostAsync("/connect/token", requestBody);
|
|
|
|
// Assert
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
// should be invalid grant
|
|
Assert.Contains(OidcConstants.TokenErrors.InvalidGrant, content);
|
|
|
|
// Try to compel the invalid email error
|
|
var expectedError = SendAccessConstants.EmailOtpValidatorResults.EmailInvalid;
|
|
Assert.Contains(expectedError, content);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SendAccess_NeverAuthenticateSend_ReturnsPasswordRequired()
|
|
{
|
|
// Arrange
|
|
var client = ConfigureTestHttpClient(_passwordSendGuid);
|
|
|
|
var requestBody = SendAccessTestUtilities.CreateTokenRequestBody(_passwordSendGuid);
|
|
|
|
// Act
|
|
var response = await client.PostAsync("/connect/token", requestBody);
|
|
|
|
// Assert
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
Assert.Contains(OidcConstants.TokenErrors.InvalidGrant, content);
|
|
|
|
var expectedError = SendAccessConstants.PasswordValidatorResults.RequestPasswordIsRequired;
|
|
Assert.Contains(expectedError, content);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SendAccess_NeverAuthenticateSend_WithPassword_ReturnsPasswordInvalid()
|
|
{
|
|
// Arrange
|
|
var password = "test-password-hash";
|
|
|
|
var client = ConfigureTestHttpClient(_passwordSendGuid);
|
|
|
|
var requestBody = SendAccessTestUtilities.CreateTokenRequestBody(_passwordSendGuid, password: password);
|
|
|
|
// Act
|
|
var response = await client.PostAsync("/connect/token", requestBody);
|
|
|
|
// Assert
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
Assert.Contains(OidcConstants.TokenErrors.InvalidRequest, content);
|
|
|
|
var expectedError = SendAccessConstants.PasswordValidatorResults.RequestPasswordDoesNotMatch;
|
|
Assert.Contains(expectedError, content);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SendAccess_NeverAuthenticateSend_ConsistentResponse_SameSendId()
|
|
{
|
|
// Arrange
|
|
var client = ConfigureTestHttpClient(_emailSendGuid);
|
|
|
|
var requestBody1 = SendAccessTestUtilities.CreateTokenRequestBody(_emailSendGuid);
|
|
var requestBody2 = SendAccessTestUtilities.CreateTokenRequestBody(_emailSendGuid);
|
|
|
|
// Act
|
|
var response1 = await client.PostAsync("/connect/token", requestBody1);
|
|
var response2 = await client.PostAsync("/connect/token", requestBody2);
|
|
|
|
// Assert
|
|
var content1 = await response1.Content.ReadAsStringAsync();
|
|
var content2 = await response2.Content.ReadAsStringAsync();
|
|
|
|
Assert.Equal(content1, content2);
|
|
}
|
|
|
|
private HttpClient ConfigureTestHttpClient(Guid sendId)
|
|
{
|
|
_factory.UpdateConfiguration(
|
|
"globalSettings:sendDefaultHashKey", _testHashKey);
|
|
return _factory.WithWebHostBuilder(builder =>
|
|
{
|
|
builder.ConfigureServices(services =>
|
|
{
|
|
var featureService = Substitute.For<IFeatureService>();
|
|
featureService.IsEnabled(Arg.Any<string>()).Returns(true);
|
|
services.AddSingleton(featureService);
|
|
|
|
var sendAuthQuery = Substitute.For<ISendAuthenticationQuery>();
|
|
sendAuthQuery.GetAuthenticationMethod(sendId)
|
|
.Returns(new NeverAuthenticate());
|
|
services.AddSingleton(sendAuthQuery);
|
|
});
|
|
}).CreateClient();
|
|
}
|
|
}
|