1
0
mirror of https://github.com/bitwarden/server.git synced 2025-01-22 21:51:22 +01:00

catch u2f exceptions

This commit is contained in:
Kyle Spearrin 2018-10-10 15:21:54 -04:00
parent cbab6eb9d7
commit b5a4bad637
3 changed files with 97 additions and 78 deletions

View File

@ -218,11 +218,16 @@ namespace Bit.Api.Controllers
public async Task<TwoFactorU2fResponseModel> PutU2f([FromBody]TwoFactorU2fRequestModel model)
{
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);
return response;
}
[HttpDelete("u2f")]
public async Task<TwoFactorU2fResponseModel> DeleteU2f([FromBody]TwoFactorU2fDeleteRequestModel model)
{

View File

@ -10,7 +10,6 @@ using System.Linq;
using U2fLib = U2F.Core.Crypto.U2F;
using U2F.Core.Models;
using U2F.Core.Exceptions;
using U2F.Core.Utils;
using System;
using Bit.Core.Services;
using Microsoft.Extensions.DependencyInjection;
@ -67,37 +66,44 @@ namespace Bit.Core.Identity
await _u2fRepository.DeleteManyByUserIdAsync(user.Id);
var challengeBytes = U2fLib.Crypto.GenerateChallenge();
var challenges = new List<object>();
foreach(var key in keys)
try
{
var registration = new DeviceRegistration(key.Item2.KeyHandleBytes, key.Item2.PublicKeyBytes,
key.Item2.CertificateBytes, key.Item2.Counter);
var auth = U2fLib.StartAuthentication(Utilities.CoreHelpers.U2fAppIdUrl(_globalSettings), registration,
challengeBytes);
// TODO: Maybe move this to a bulk create?
await _u2fRepository.CreateAsync(new U2f
var challengeBytes = U2fLib.Crypto.GenerateChallenge();
var challenges = new List<object>();
foreach(var key in keys)
{
AppId = auth.AppId,
Challenge = auth.Challenge,
KeyHandle = auth.KeyHandle,
Version = auth.Version,
UserId = user.Id,
CreationDate = DateTime.UtcNow
});
var registration = new DeviceRegistration(key.Item2.KeyHandleBytes, key.Item2.PublicKeyBytes,
key.Item2.CertificateBytes, key.Item2.Counter);
var auth = U2fLib.StartAuthentication(Utilities.CoreHelpers.U2fAppIdUrl(_globalSettings), registration,
challengeBytes);
challenges.Add(new
{
appId = auth.AppId,
challenge = auth.Challenge,
keyHandle = auth.KeyHandle,
version = auth.Version
});
// TODO: Maybe move this to a bulk create?
await _u2fRepository.CreateAsync(new U2f
{
AppId = auth.AppId,
Challenge = auth.Challenge,
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)

View File

@ -19,6 +19,7 @@ using Bit.Core.Utilities;
using System.IO;
using Newtonsoft.Json;
using Microsoft.AspNetCore.DataProtection;
using U2F.Core.Exceptions;
namespace Bit.Core.Services
{
@ -322,60 +323,67 @@ namespace Bit.Core.Services
var registerResponse = BaseModel.FromJson<RegisterResponse>(deviceResponse);
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);
try
{
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
var providers = user.GetTwoFactorProviders();
if(providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.U2f);
if(provider == null)
{
provider = new TwoFactorProvider();
}
if(provider.MetaData == null)
{
provider.MetaData = new Dictionary<string, object>();
}
// Add device
var providers = user.GetTwoFactorProviders();
if(providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.U2f);
if(provider == null)
{
provider = new TwoFactorProvider();
}
if(provider.MetaData == null)
{
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;
}
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)