mirror of
https://github.com/bitwarden/server.git
synced 2025-04-17 19:18:16 -05:00
update u2f lib. send 2fa login email
This commit is contained in:
parent
64189067cd
commit
59b8438a0f
@ -207,6 +207,24 @@ namespace Bit.Api.Controllers
|
|||||||
await _userService.SendTwoFactorEmailAsync(user);
|
await _userService.SendTwoFactorEmailAsync(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpPost("send-email-login")]
|
||||||
|
public async Task SendEmailLogin([FromBody]TwoFactorEmailRequestModel model)
|
||||||
|
{
|
||||||
|
var user = await _userManager.FindByEmailAsync(model.Email.ToLowerInvariant());
|
||||||
|
if(user != null)
|
||||||
|
{
|
||||||
|
if(await _userManager.CheckPasswordAsync(user, model.MasterPasswordHash))
|
||||||
|
{
|
||||||
|
await _userService.SendTwoFactorEmailAsync(user);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(2000);
|
||||||
|
throw new BadRequestException("Cannot send two-factor email.");
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPut("email")]
|
[HttpPut("email")]
|
||||||
[HttpPost("email")]
|
[HttpPost("email")]
|
||||||
public async Task<TwoFactorEmailResponseModel> PutEmail([FromBody]UpdateTwoFactorEmailRequestModel model)
|
public async Task<TwoFactorEmailResponseModel> PutEmail([FromBody]UpdateTwoFactorEmailRequestModel model)
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
<PackageReference Include="Serilog.Extensions.Logging" Version="1.4.0" />
|
<PackageReference Include="Serilog.Extensions.Logging" Version="1.4.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.AzureDocumentDB" Version="3.6.1" />
|
<PackageReference Include="Serilog.Sinks.AzureDocumentDB" Version="3.6.1" />
|
||||||
<PackageReference Include="Stripe.net" Version="7.8.0" />
|
<PackageReference Include="Stripe.net" Version="7.8.0" />
|
||||||
<PackageReference Include="u2flib" Version="1.0.5" />
|
<PackageReference Include="U2F.Core" Version="1.0.3" />
|
||||||
<PackageReference Include="WindowsAzure.Storage" Version="8.1.1" />
|
<PackageReference Include="WindowsAzure.Storage" Version="8.1.1" />
|
||||||
<PackageReference Include="Otp.NET" Version="1.0.1" />
|
<PackageReference Include="Otp.NET" Version="1.0.1" />
|
||||||
<PackageReference Include="YubicoDotNetClient" Version="1.0.0" />
|
<PackageReference Include="YubicoDotNetClient" Version="1.0.0" />
|
||||||
|
@ -7,10 +7,9 @@ using Bit.Core.Repositories;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using u2flib.Data;
|
using U2fLib = U2F.Core.Crypto.U2F;
|
||||||
using u2flib;
|
using U2F.Core.Models;
|
||||||
using u2flib.Data.Messages;
|
using U2F.Core.Exceptions;
|
||||||
using u2flib.Exceptions;
|
|
||||||
|
|
||||||
namespace Bit.Core.Identity
|
namespace Bit.Core.Identity
|
||||||
{
|
{
|
||||||
@ -62,7 +61,7 @@ namespace Bit.Core.Identity
|
|||||||
{
|
{
|
||||||
var registration = new DeviceRegistration(key.KeyHandleBytes, key.PublicKeyBytes,
|
var registration = new DeviceRegistration(key.KeyHandleBytes, key.PublicKeyBytes,
|
||||||
key.CertificateBytes, key.Counter);
|
key.CertificateBytes, key.Counter);
|
||||||
var auth = U2F.StartAuthentication(Utilities.CoreHelpers.U2fAppIdUrl(_globalSettings), registration);
|
var auth = U2fLib.StartAuthentication(Utilities.CoreHelpers.U2fAppIdUrl(_globalSettings), registration);
|
||||||
|
|
||||||
// Maybe move this to a bulk create when we support more than 1 key?
|
// Maybe move this to a bulk create when we support more than 1 key?
|
||||||
await _u2fRepository.CreateAsync(new U2f
|
await _u2fRepository.CreateAsync(new U2f
|
||||||
@ -113,7 +112,7 @@ namespace Bit.Core.Identity
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var authenticateResponse = DataObject.FromJson<AuthenticateResponse>(token);
|
var authenticateResponse = BaseModel.FromJson<AuthenticateResponse>(token);
|
||||||
var key = keys.FirstOrDefault(f => f.KeyHandle == authenticateResponse.KeyHandle);
|
var key = keys.FirstOrDefault(f => f.KeyHandle == authenticateResponse.KeyHandle);
|
||||||
|
|
||||||
if(key == null)
|
if(key == null)
|
||||||
@ -141,7 +140,7 @@ namespace Bit.Core.Identity
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var auth = new StartedAuthentication(challenge.Challenge, challenge.AppId, challenge.KeyHandle);
|
var auth = new StartedAuthentication(challenge.Challenge, challenge.AppId, challenge.KeyHandle);
|
||||||
U2F.FinishAuthentication(auth, authenticateResponse, registration);
|
U2fLib.FinishAuthentication(auth, authenticateResponse, registration);
|
||||||
}
|
}
|
||||||
catch(U2fException)
|
catch(U2fException)
|
||||||
{
|
{
|
||||||
|
@ -120,7 +120,14 @@ namespace Bit.Core.IdentityServer
|
|||||||
{
|
{
|
||||||
var providerKeys = new List<byte>();
|
var providerKeys = new List<byte>();
|
||||||
var providers = new Dictionary<byte, Dictionary<string, object>>();
|
var providers = new Dictionary<byte, Dictionary<string, object>>();
|
||||||
foreach(var provider in user.GetTwoFactorProviders().Where(p => p.Value.Enabled))
|
var enabledProviders = user.GetTwoFactorProviders()?.Where(p => p.Value.Enabled);
|
||||||
|
if(enabledProviders == null)
|
||||||
|
{
|
||||||
|
BuildErrorResult(false, context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var provider in enabledProviders)
|
||||||
{
|
{
|
||||||
providerKeys.Add((byte)provider.Key);
|
providerKeys.Add((byte)provider.Key);
|
||||||
var infoDict = await BuildTwoFactorParams(user, provider.Key, provider.Value);
|
var infoDict = await BuildTwoFactorParams(user, provider.Key, provider.Value);
|
||||||
@ -133,6 +140,12 @@ namespace Bit.Core.IdentityServer
|
|||||||
{ "TwoFactorProviders", providers.Keys },
|
{ "TwoFactorProviders", providers.Keys },
|
||||||
{ "TwoFactorProviders2", providers }
|
{ "TwoFactorProviders2", providers }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(enabledProviders.Count() == 1 && enabledProviders.First().Key == TwoFactorProviderType.Email)
|
||||||
|
{
|
||||||
|
// Send email now if this is their only 2FA method
|
||||||
|
await _userService.SendTwoFactorEmailAsync(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildErrorResult(bool twoFactorRequest, ResourceOwnerPasswordValidationContext context)
|
private void BuildErrorResult(bool twoFactorRequest, ResourceOwnerPasswordValidationContext context)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using u2flib.Util;
|
using U2F.Core.Utils;
|
||||||
|
|
||||||
namespace Bit.Core.Models
|
namespace Bit.Core.Models
|
||||||
{
|
{
|
||||||
|
@ -12,10 +12,9 @@ using Bit.Core.Enums;
|
|||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Bit.Core.Models;
|
using Bit.Core.Models;
|
||||||
using Bit.Core.Models.Business;
|
using Bit.Core.Models.Business;
|
||||||
using u2flib.Data.Messages;
|
using U2fLib = U2F.Core.Crypto.U2F;
|
||||||
using u2flib.Util;
|
using U2F.Core.Models;
|
||||||
using u2flib;
|
using U2F.Core.Utils;
|
||||||
using u2flib.Data;
|
|
||||||
|
|
||||||
namespace Bit.Core.Services
|
namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
@ -220,7 +219,7 @@ namespace Bit.Core.Services
|
|||||||
public async Task<U2fRegistration> StartU2fRegistrationAsync(User user)
|
public async Task<U2fRegistration> StartU2fRegistrationAsync(User user)
|
||||||
{
|
{
|
||||||
await _u2fRepository.DeleteManyByUserIdAsync(user.Id);
|
await _u2fRepository.DeleteManyByUserIdAsync(user.Id);
|
||||||
var reg = U2F.StartRegistration(Utilities.CoreHelpers.U2fAppIdUrl(_globalSettings));
|
var reg = U2fLib.StartRegistration(Utilities.CoreHelpers.U2fAppIdUrl(_globalSettings));
|
||||||
await _u2fRepository.CreateAsync(new U2f
|
await _u2fRepository.CreateAsync(new U2f
|
||||||
{
|
{
|
||||||
AppId = reg.AppId,
|
AppId = reg.AppId,
|
||||||
@ -250,11 +249,11 @@ namespace Bit.Core.Services
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var registerResponse = DataObject.FromJson<RegisterResponse>(deviceResponse);
|
var registerResponse = BaseModel.FromJson<RegisterResponse>(deviceResponse);
|
||||||
|
|
||||||
var challenge = challenges.OrderBy(i => i.Id).Last(i => i.KeyHandle == null);
|
var challenge = challenges.OrderBy(i => i.Id).Last(i => i.KeyHandle == null);
|
||||||
var statedReg = new StartedRegistration(challenge.Challenge, challenge.AppId);
|
var statedReg = new StartedRegistration(challenge.Challenge, challenge.AppId);
|
||||||
var reg = U2F.FinishRegistration(statedReg, registerResponse);
|
var reg = U2fLib.FinishRegistration(statedReg, registerResponse);
|
||||||
|
|
||||||
await _u2fRepository.DeleteManyByUserIdAsync(user.Id);
|
await _u2fRepository.DeleteManyByUserIdAsync(user.Id);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user