mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
add u2f tests
This commit is contained in:
130
BTCPayServer.Tests/U2FTests.cs
Normal file
130
BTCPayServer.Tests/U2FTests.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Controllers;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Models.AccountViewModels;
|
||||
using BTCPayServer.Tests.Logging;
|
||||
using BTCPayServer.U2F;
|
||||
using BTCPayServer.U2F.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using U2F.Core.Models;
|
||||
using U2F.Core.Utils;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace BTCPayServer.Tests
|
||||
{
|
||||
public class U2FTests
|
||||
{
|
||||
public const int TestTimeout = 60_000;
|
||||
|
||||
public U2FTests(ITestOutputHelper helper)
|
||||
{
|
||||
Logs.Tester = new XUnitLog(helper) {Name = "Tests"};
|
||||
Logs.LogProvider = new XUnitLogProvider(helper);
|
||||
}
|
||||
|
||||
|
||||
[Fact(Timeout = TestTimeout)]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task U2ftest()
|
||||
{
|
||||
using (var tester = ServerTester.Create())
|
||||
{
|
||||
await tester.StartAsync();
|
||||
var user = tester.NewAccount();
|
||||
user.GrantAccess();
|
||||
user.RegisterDerivationScheme("BTC");
|
||||
|
||||
var accountController = tester.PayTester.GetController<AccountController>();
|
||||
var manageController = user.GetController<ManageController>();
|
||||
var mock = new MockU2FService(tester.PayTester.GetService<ApplicationDbContextFactory>());
|
||||
manageController._u2FService = mock;
|
||||
accountController._u2FService = mock;
|
||||
|
||||
Assert
|
||||
.IsType<RedirectToActionResult>(await accountController.Login(new LoginViewModel()
|
||||
{
|
||||
Email = user.RegisterDetails.Email, Password = user.RegisterDetails.Password
|
||||
}));
|
||||
|
||||
Assert.Empty(Assert.IsType<U2FAuthenticationViewModel>(Assert
|
||||
.IsType<ViewResult>(await manageController.U2FAuthentication()).Model).Devices);
|
||||
|
||||
var addDeviceVM = Assert.IsType<AddU2FDeviceViewModel>(Assert
|
||||
.IsType<ViewResult>(manageController.AddU2FDevice("testdevice")).Model);
|
||||
|
||||
Assert.NotEmpty(addDeviceVM.Challenge);
|
||||
Assert.Equal(addDeviceVM.Name, "testdevice");
|
||||
Assert.NotEmpty(addDeviceVM.Version);
|
||||
Assert.Null(addDeviceVM.DeviceResponse);
|
||||
|
||||
var devReg = new DeviceRegistration(Guid.NewGuid().ToByteArray(), Guid.NewGuid().ToByteArray(),
|
||||
Guid.NewGuid().ToByteArray(), 1);
|
||||
|
||||
mock.GetDevReg = () => devReg;
|
||||
mock.StartedAuthentication = () =>
|
||||
new StartedAuthentication("chocolate", addDeviceVM.AppId,
|
||||
devReg.KeyHandle.ByteArrayToBase64String());
|
||||
addDeviceVM.DeviceResponse = new RegisterResponse("ss",
|
||||
Convert.ToBase64String(Encoding.UTF8.GetBytes("{typ:'x', challenge: 'fff'}"))).ToJson();
|
||||
Assert
|
||||
.IsType<RedirectToActionResult>(await manageController.AddU2FDevice(addDeviceVM));
|
||||
|
||||
Assert.Single(Assert.IsType<U2FAuthenticationViewModel>(Assert
|
||||
.IsType<ViewResult>(await manageController.U2FAuthentication()).Model).Devices);
|
||||
|
||||
var secondaryLoginViewModel = Assert.IsType<SecondaryLoginViewModel>(Assert
|
||||
.IsType<ViewResult>(await accountController.Login(new LoginViewModel()
|
||||
{
|
||||
Email = user.RegisterDetails.Email, Password = user.RegisterDetails.Password
|
||||
})).Model);
|
||||
Assert.NotNull(secondaryLoginViewModel.LoginWithU2FViewModel);
|
||||
Assert.Single(secondaryLoginViewModel.LoginWithU2FViewModel.Challenges);
|
||||
Assert.Equal(secondaryLoginViewModel.LoginWithU2FViewModel.Challenge,
|
||||
secondaryLoginViewModel.LoginWithU2FViewModel.Challenges.First().challenge);
|
||||
|
||||
secondaryLoginViewModel.LoginWithU2FViewModel.DeviceResponse = new AuthenticateResponse(
|
||||
Convert.ToBase64String(Encoding.UTF8.GetBytes(
|
||||
"{typ:'x', challenge: '" + secondaryLoginViewModel.LoginWithU2FViewModel.Challenge + "'}")),
|
||||
"dd", devReg.KeyHandle.ByteArrayToBase64String()).ToJson();
|
||||
Assert
|
||||
.IsType<RedirectToActionResult>(
|
||||
await accountController.LoginWithU2F(secondaryLoginViewModel.LoginWithU2FViewModel));
|
||||
}
|
||||
}
|
||||
|
||||
public class MockU2FService : U2FService
|
||||
{
|
||||
public Func<DeviceRegistration> GetDevReg;
|
||||
public Func<StartedAuthentication> StartedAuthentication;
|
||||
|
||||
public MockU2FService(ApplicationDbContextFactory contextFactory) : base(contextFactory)
|
||||
{
|
||||
}
|
||||
|
||||
protected override StartedRegistration StartDeviceRegistrationCore(string appId)
|
||||
{
|
||||
return global::U2F.Core.Crypto.U2F.StartRegistration(appId);
|
||||
}
|
||||
|
||||
protected override DeviceRegistration FinishRegistrationCore(StartedRegistration startedRegistration,
|
||||
RegisterResponse registerResponse)
|
||||
{
|
||||
return GetDevReg();
|
||||
}
|
||||
|
||||
protected override StartedAuthentication StartAuthenticationCore(string appId, U2FDevice registeredDevice)
|
||||
{
|
||||
return StartedAuthentication();
|
||||
}
|
||||
|
||||
protected override void FinishAuthenticationCore(StartedAuthentication authentication,
|
||||
AuthenticateResponse authenticateResponse, DeviceRegistration registration)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ namespace BTCPayServer.Controllers
|
||||
SettingsRepository _SettingsRepository;
|
||||
Configuration.BTCPayServerOptions _Options;
|
||||
private readonly BTCPayServerEnvironment _btcPayServerEnvironment;
|
||||
private readonly U2FService _u2FService;
|
||||
public U2FService _u2FService;
|
||||
ILogger _logger;
|
||||
|
||||
public AccountController(
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace BTCPayServer.Controllers
|
||||
private readonly ILogger _logger;
|
||||
private readonly UrlEncoder _urlEncoder;
|
||||
IWebHostEnvironment _Env;
|
||||
private readonly U2FService _u2FService;
|
||||
public U2FService _u2FService;
|
||||
private readonly BTCPayServerEnvironment _btcPayServerEnvironment;
|
||||
StoreRepository _StoreRepository;
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace BTCPayServer.U2F
|
||||
|
||||
public ServerRegisterResponse StartDeviceRegistration(string userId, string appId)
|
||||
{
|
||||
var startedRegistration = global::U2F.Core.Crypto.U2F.StartRegistration(appId);
|
||||
var startedRegistration = StartDeviceRegistrationCore(appId);
|
||||
|
||||
UserAuthenticationRequests.AddOrReplace(userId, new List<U2FDeviceAuthenticationRequest>()
|
||||
{
|
||||
@@ -104,7 +104,7 @@ namespace BTCPayServer.U2F
|
||||
|
||||
var startedRegistration =
|
||||
new StartedRegistration(authenticationRequest.Challenge, authenticationRequest.AppId);
|
||||
var registration = global::U2F.Core.Crypto.U2F.FinishRegistration(startedRegistration, registerResponse);
|
||||
var registration = FinishRegistrationCore(startedRegistration, registerResponse);
|
||||
|
||||
UserAuthenticationRequests.AddOrReplace(userId, new List<U2FDeviceAuthenticationRequest>());
|
||||
using (var context = _contextFactory.CreateContext())
|
||||
@@ -174,7 +174,7 @@ namespace BTCPayServer.U2F
|
||||
{
|
||||
authentication = new StartedAuthentication(challengeAuthenticationRequestMatch.Challenge, authenticationRequest.AppId, authenticationRequest.KeyHandle);
|
||||
}
|
||||
global::U2F.Core.Crypto.U2F.FinishAuthentication(authentication, authenticateResponse, registration);
|
||||
FinishAuthenticationCore(authentication, authenticateResponse, registration);
|
||||
|
||||
UserAuthenticationRequests.AddOrReplace(userId, new List<U2FDeviceAuthenticationRequest>());
|
||||
|
||||
@@ -201,9 +201,7 @@ namespace BTCPayServer.U2F
|
||||
var serverChallenges = new List<ServerChallenge>();
|
||||
foreach (var registeredDevice in devices)
|
||||
{
|
||||
var challenge = global::U2F.Core.Crypto.U2F.StartAuthentication(appId,
|
||||
new DeviceRegistration(registeredDevice.KeyHandle, registeredDevice.PublicKey,
|
||||
registeredDevice.AttestationCert, (uint)registeredDevice.Counter));
|
||||
var challenge = StartAuthenticationCore(appId, registeredDevice);
|
||||
serverChallenges.Add(new ServerChallenge()
|
||||
{
|
||||
challenge = challenge.Challenge,
|
||||
@@ -226,5 +224,28 @@ namespace BTCPayServer.U2F
|
||||
return serverChallenges;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual StartedRegistration StartDeviceRegistrationCore(string appId)
|
||||
{
|
||||
return global::U2F.Core.Crypto.U2F.StartRegistration(appId);
|
||||
}
|
||||
|
||||
protected virtual DeviceRegistration FinishRegistrationCore(StartedRegistration startedRegistration, RegisterResponse registerResponse)
|
||||
{
|
||||
return global::U2F.Core.Crypto.U2F.FinishRegistration(startedRegistration, registerResponse);
|
||||
}
|
||||
|
||||
protected virtual StartedAuthentication StartAuthenticationCore(string appId, U2FDevice registeredDevice)
|
||||
{
|
||||
return global::U2F.Core.Crypto.U2F.StartAuthentication(appId,
|
||||
new DeviceRegistration(registeredDevice.KeyHandle, registeredDevice.PublicKey,
|
||||
registeredDevice.AttestationCert, (uint)registeredDevice.Counter));
|
||||
}
|
||||
|
||||
protected virtual void FinishAuthenticationCore(StartedAuthentication authentication,
|
||||
AuthenticateResponse authenticateResponse, DeviceRegistration registration)
|
||||
{
|
||||
global::U2F.Core.Crypto.U2F.FinishAuthentication(authentication, authenticateResponse, registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user