1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-08 21:22:20 -05:00

configure duo 2fa

This commit is contained in:
Kyle Spearrin 2017-06-21 14:19:07 -04:00
parent 2ce47edadf
commit 50c0b3e752
4 changed files with 119 additions and 6 deletions

View File

@ -77,8 +77,7 @@ namespace Bit.Api.Controllers
[HttpPut("yubikey")]
[HttpPost("yubikey")]
public async Task<TwoFactorYubiKeyResponseModel> PutYubiKey(
[FromBody]UpdateTwoFactorYubicoOtpRequestModel model)
public async Task<TwoFactorYubiKeyResponseModel> PutYubiKey([FromBody]UpdateTwoFactorYubicoOtpRequestModel model)
{
var user = await CheckPasswordAsync(model.MasterPasswordHash);
model.ToUser(user);
@ -94,6 +93,25 @@ namespace Bit.Api.Controllers
return response;
}
[HttpPost("get-duo")]
public async Task<TwoFactorDuoResponseModel> GetDuo([FromBody]TwoFactorRequestModel model)
{
var user = await CheckPasswordAsync(model.MasterPasswordHash);
var response = new TwoFactorDuoResponseModel(user);
return response;
}
[HttpPut("duo")]
[HttpPost("duo")]
public async Task<TwoFactorDuoResponseModel> PutDuo([FromBody]UpdateTwoFactorDuoRequestModel model)
{
var user = await CheckPasswordAsync(model.MasterPasswordHash);
model.ToUser(user);
await _userService.UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.Duo);
var response = new TwoFactorDuoResponseModel(user);
return response;
}
public async Task ValidateYubiKeyAsync(User user, string name, string value)
{
if(string.IsNullOrWhiteSpace(value) || value.Length == 12)
@ -148,12 +166,11 @@ namespace Bit.Api.Controllers
[HttpPut("disable")]
[HttpPost("disable")]
public async Task<TwoFactorEmailResponseModel> PutDisable([FromBody]TwoFactorProviderRequestModel model)
public async Task<TwoFactorProviderResponseModel> PutDisable([FromBody]TwoFactorProviderRequestModel model)
{
var user = await CheckPasswordAsync(model.MasterPasswordHash);
await _userService.DisableTwoFactorProviderAsync(user, model.Type.Value);
var response = new TwoFactorEmailResponseModel(user);
var response = new TwoFactorProviderResponseModel(model.Type.Value, user);
return response;
}

View File

@ -2,6 +2,8 @@
using Bit.Core.Models.Table;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System;
using System.Linq;
namespace Bit.Core.Models.Api
{
@ -36,7 +38,7 @@ namespace Bit.Core.Models.Api
}
}
public class UpdateTwoFactorDuoRequestModel : TwoFactorRequestModel
public class UpdateTwoFactorDuoRequestModel : TwoFactorRequestModel, IValidatableObject
{
[Required]
[StringLength(50)]
@ -47,6 +49,40 @@ namespace Bit.Core.Models.Api
[Required]
[StringLength(50)]
public string Host { get; set; }
public User ToUser(User extistingUser)
{
var providers = extistingUser.GetTwoFactorProviders();
if(providers == null)
{
providers = new Dictionary<TwoFactorProviderType, TwoFactorProvider>();
}
else if(providers.ContainsKey(TwoFactorProviderType.Duo))
{
providers.Remove(TwoFactorProviderType.Duo);
}
providers.Add(TwoFactorProviderType.Duo, new TwoFactorProvider
{
MetaData = new Dictionary<string, string>
{
["SKey"] = SecretKey,
["IKey"] = IntegrationKey,
["Host"] = Host
},
Enabled = true
});
extistingUser.SetTwoFactorProviders(providers);
return extistingUser;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if(!Host.StartsWith("api-") || !Host.EndsWith(".duosecurity.com") || Host.Count(s => s == '.') != 2)
{
yield return new ValidationResult("Host is invalid.", new string[] { nameof(Host) });
}
}
}
public class UpdateTwoFactorYubicoOtpRequestModel : TwoFactorRequestModel, IValidatableObject

View File

@ -0,0 +1,46 @@
using System;
using Bit.Core.Enums;
using Bit.Core.Models.Table;
namespace Bit.Core.Models.Api
{
public class TwoFactorDuoResponseModel : ResponseModel
{
public TwoFactorDuoResponseModel(User user)
: base("twoFactorDuo")
{
if(user == null)
{
throw new ArgumentNullException(nameof(user));
}
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.Duo);
if(provider?.MetaData != null && provider.MetaData.Count > 0)
{
Enabled = provider.Enabled;
if(provider.MetaData.ContainsKey("Host"))
{
Host = provider.MetaData["Host"];
}
if(provider.MetaData.ContainsKey("SKey"))
{
SecretKey = provider.MetaData["SKey"];
}
if(provider.MetaData.ContainsKey("IKey"))
{
IntegrationKey = provider.MetaData["IKey"];
}
}
else
{
Enabled = false;
}
}
public bool Enabled { get; set; }
public string Host { get; set; }
public string SecretKey { get; set; }
public string IntegrationKey { get; set; }
}
}

View File

@ -1,5 +1,6 @@
using System;
using Bit.Core.Enums;
using Bit.Core.Models.Table;
namespace Bit.Core.Models.Api
{
@ -17,6 +18,19 @@ namespace Bit.Core.Models.Api
Type = type;
}
public TwoFactorProviderResponseModel(TwoFactorProviderType type, User user)
: base("twoFactorProvider")
{
if(user == null)
{
throw new ArgumentNullException(nameof(user));
}
var provider = user.GetTwoFactorProvider(type);
Enabled = provider?.Enabled ?? false;
Type = type;
}
public bool Enabled { get; set; }
public TwoFactorProviderType Type { get; set; }
}