mirror of
https://github.com/bitwarden/server.git
synced 2025-04-15 10:08:14 -05:00
catch u2f exceptions
This commit is contained in:
parent
cbab6eb9d7
commit
b5a4bad637
@ -218,7 +218,12 @@ namespace Bit.Api.Controllers
|
|||||||
public async Task<TwoFactorU2fResponseModel> PutU2f([FromBody]TwoFactorU2fRequestModel model)
|
public async Task<TwoFactorU2fResponseModel> PutU2f([FromBody]TwoFactorU2fRequestModel model)
|
||||||
{
|
{
|
||||||
var user = await CheckAsync(model.MasterPasswordHash, true);
|
var user = await CheckAsync(model.MasterPasswordHash, true);
|
||||||
await _userService.CompleteU2fRegistrationAsync(user, model.Id.Value, model.Name, model.DeviceResponse);
|
var success = await _userService.CompleteU2fRegistrationAsync(
|
||||||
|
user, model.Id.Value, model.Name, model.DeviceResponse);
|
||||||
|
if(!success)
|
||||||
|
{
|
||||||
|
throw new BadRequestException("Unable to complete U2F key registration.");
|
||||||
|
}
|
||||||
var response = new TwoFactorU2fResponseModel(user);
|
var response = new TwoFactorU2fResponseModel(user);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ using System.Linq;
|
|||||||
using U2fLib = U2F.Core.Crypto.U2F;
|
using U2fLib = U2F.Core.Crypto.U2F;
|
||||||
using U2F.Core.Models;
|
using U2F.Core.Models;
|
||||||
using U2F.Core.Exceptions;
|
using U2F.Core.Exceptions;
|
||||||
using U2F.Core.Utils;
|
|
||||||
using System;
|
using System;
|
||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@ -67,37 +66,44 @@ namespace Bit.Core.Identity
|
|||||||
|
|
||||||
await _u2fRepository.DeleteManyByUserIdAsync(user.Id);
|
await _u2fRepository.DeleteManyByUserIdAsync(user.Id);
|
||||||
|
|
||||||
var challengeBytes = U2fLib.Crypto.GenerateChallenge();
|
try
|
||||||
var challenges = new List<object>();
|
|
||||||
foreach(var key in keys)
|
|
||||||
{
|
{
|
||||||
var registration = new DeviceRegistration(key.Item2.KeyHandleBytes, key.Item2.PublicKeyBytes,
|
var challengeBytes = U2fLib.Crypto.GenerateChallenge();
|
||||||
key.Item2.CertificateBytes, key.Item2.Counter);
|
var challenges = new List<object>();
|
||||||
var auth = U2fLib.StartAuthentication(Utilities.CoreHelpers.U2fAppIdUrl(_globalSettings), registration,
|
foreach(var key in keys)
|
||||||
challengeBytes);
|
|
||||||
|
|
||||||
// TODO: Maybe move this to a bulk create?
|
|
||||||
await _u2fRepository.CreateAsync(new U2f
|
|
||||||
{
|
{
|
||||||
AppId = auth.AppId,
|
var registration = new DeviceRegistration(key.Item2.KeyHandleBytes, key.Item2.PublicKeyBytes,
|
||||||
Challenge = auth.Challenge,
|
key.Item2.CertificateBytes, key.Item2.Counter);
|
||||||
KeyHandle = auth.KeyHandle,
|
var auth = U2fLib.StartAuthentication(Utilities.CoreHelpers.U2fAppIdUrl(_globalSettings), registration,
|
||||||
Version = auth.Version,
|
challengeBytes);
|
||||||
UserId = user.Id,
|
|
||||||
CreationDate = DateTime.UtcNow
|
|
||||||
});
|
|
||||||
|
|
||||||
challenges.Add(new
|
// TODO: Maybe move this to a bulk create?
|
||||||
{
|
await _u2fRepository.CreateAsync(new U2f
|
||||||
appId = auth.AppId,
|
{
|
||||||
challenge = auth.Challenge,
|
AppId = auth.AppId,
|
||||||
keyHandle = auth.KeyHandle,
|
Challenge = auth.Challenge,
|
||||||
version = auth.Version
|
KeyHandle = auth.KeyHandle,
|
||||||
});
|
Version = auth.Version,
|
||||||
|
UserId = user.Id,
|
||||||
|
CreationDate = DateTime.UtcNow
|
||||||
|
});
|
||||||
|
|
||||||
|
challenges.Add(new
|
||||||
|
{
|
||||||
|
appId = auth.AppId,
|
||||||
|
challenge = auth.Challenge,
|
||||||
|
keyHandle = auth.KeyHandle,
|
||||||
|
version = auth.Version
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = JsonConvert.SerializeObject(challenges);
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
catch(U2fException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var token = JsonConvert.SerializeObject(challenges);
|
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> ValidateAsync(string purpose, string token, UserManager<User> manager, User user)
|
public async Task<bool> ValidateAsync(string purpose, string token, UserManager<User> manager, User user)
|
||||||
|
@ -19,6 +19,7 @@ using Bit.Core.Utilities;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Microsoft.AspNetCore.DataProtection;
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
|
using U2F.Core.Exceptions;
|
||||||
|
|
||||||
namespace Bit.Core.Services
|
namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
@ -322,60 +323,67 @@ namespace Bit.Core.Services
|
|||||||
|
|
||||||
var registerResponse = BaseModel.FromJson<RegisterResponse>(deviceResponse);
|
var registerResponse = BaseModel.FromJson<RegisterResponse>(deviceResponse);
|
||||||
|
|
||||||
var challenge = challenges.OrderBy(i => i.Id).Last(i => i.KeyHandle == null);
|
try
|
||||||
var startedReg = new StartedRegistration(challenge.Challenge, challenge.AppId);
|
{
|
||||||
var reg = U2fLib.FinishRegistration(startedReg, registerResponse);
|
var challenge = challenges.OrderBy(i => i.Id).Last(i => i.KeyHandle == null);
|
||||||
|
var startedReg = new StartedRegistration(challenge.Challenge, challenge.AppId);
|
||||||
|
var reg = U2fLib.FinishRegistration(startedReg, registerResponse);
|
||||||
|
|
||||||
await _u2fRepository.DeleteManyByUserIdAsync(user.Id);
|
await _u2fRepository.DeleteManyByUserIdAsync(user.Id);
|
||||||
|
|
||||||
// Add device
|
// Add device
|
||||||
var providers = user.GetTwoFactorProviders();
|
var providers = user.GetTwoFactorProviders();
|
||||||
if(providers == null)
|
if(providers == null)
|
||||||
{
|
{
|
||||||
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
|
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
|
||||||
}
|
}
|
||||||
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.U2f);
|
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.U2f);
|
||||||
if(provider == null)
|
if(provider == null)
|
||||||
{
|
{
|
||||||
provider = new TwoFactorProvider();
|
provider = new TwoFactorProvider();
|
||||||
}
|
}
|
||||||
if(provider.MetaData == null)
|
if(provider.MetaData == null)
|
||||||
{
|
{
|
||||||
provider.MetaData = new Dictionary<string, object>();
|
provider.MetaData = new Dictionary<string, object>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(provider.MetaData.Count >= 5)
|
if(provider.MetaData.Count >= 5)
|
||||||
|
{
|
||||||
|
// Can only register up to 5 keys
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var keyId = $"Key{id}";
|
||||||
|
if(provider.MetaData.ContainsKey(keyId))
|
||||||
|
{
|
||||||
|
provider.MetaData.Remove(keyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
provider.Enabled = true;
|
||||||
|
provider.MetaData.Add(keyId, new TwoFactorProvider.U2fMetaData
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
KeyHandle = reg.KeyHandle == null ? null : Utils.ByteArrayToBase64String(reg.KeyHandle),
|
||||||
|
PublicKey = reg.PublicKey == null ? null : Utils.ByteArrayToBase64String(reg.PublicKey),
|
||||||
|
Certificate = reg.AttestationCert == null ? null : Utils.ByteArrayToBase64String(reg.AttestationCert),
|
||||||
|
Compromised = false,
|
||||||
|
Counter = reg.Counter
|
||||||
|
});
|
||||||
|
|
||||||
|
if(providers.ContainsKey(TwoFactorProviderType.U2f))
|
||||||
|
{
|
||||||
|
providers.Remove(TwoFactorProviderType.U2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
providers.Add(TwoFactorProviderType.U2f, provider);
|
||||||
|
user.SetTwoFactorProviders(providers);
|
||||||
|
await UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.U2f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(U2fException)
|
||||||
{
|
{
|
||||||
// Can only register up to 5 keys
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var keyId = $"Key{id}";
|
|
||||||
if(provider.MetaData.ContainsKey(keyId))
|
|
||||||
{
|
|
||||||
provider.MetaData.Remove(keyId);
|
|
||||||
}
|
|
||||||
|
|
||||||
provider.Enabled = true;
|
|
||||||
provider.MetaData.Add(keyId, new TwoFactorProvider.U2fMetaData
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
KeyHandle = reg.KeyHandle == null ? null : Utils.ByteArrayToBase64String(reg.KeyHandle),
|
|
||||||
PublicKey = reg.PublicKey == null ? null : Utils.ByteArrayToBase64String(reg.PublicKey),
|
|
||||||
Certificate = reg.AttestationCert == null ? null : Utils.ByteArrayToBase64String(reg.AttestationCert),
|
|
||||||
Compromised = false,
|
|
||||||
Counter = reg.Counter
|
|
||||||
});
|
|
||||||
|
|
||||||
if(providers.ContainsKey(TwoFactorProviderType.U2f))
|
|
||||||
{
|
|
||||||
providers.Remove(TwoFactorProviderType.U2f);
|
|
||||||
}
|
|
||||||
|
|
||||||
providers.Add(TwoFactorProviderType.U2f, provider);
|
|
||||||
user.SetTwoFactorProviders(providers);
|
|
||||||
await UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.U2f);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> DeleteU2fKeyAsync(User user, int id)
|
public async Task<bool> DeleteU2fKeyAsync(User user, int id)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user