mirror of
https://github.com/bitwarden/server.git
synced 2026-02-08 09:53:14 +08:00
Revert filescoped (#2227)
* Revert "Add git blame entry (#2226)" This reverts commit239286737d. * Revert "Turn on file scoped namespaces (#2225)" This reverts commit34fb4cca2a.
This commit is contained in:
@@ -10,145 +10,146 @@ using Fido2NetLib.Objects;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Bit.Core.Identity;
|
||||
|
||||
public class WebAuthnTokenProvider : IUserTwoFactorTokenProvider<User>
|
||||
namespace Bit.Core.Identity
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IFido2 _fido2;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
public WebAuthnTokenProvider(IServiceProvider serviceProvider, IFido2 fido2, GlobalSettings globalSettings)
|
||||
public class WebAuthnTokenProvider : IUserTwoFactorTokenProvider<User>
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_fido2 = fido2;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IFido2 _fido2;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
public async Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
|
||||
{
|
||||
var userService = _serviceProvider.GetRequiredService<IUserService>();
|
||||
if (!(await userService.CanAccessPremium(user)))
|
||||
public WebAuthnTokenProvider(IServiceProvider serviceProvider, IFido2 fido2, GlobalSettings globalSettings)
|
||||
{
|
||||
return false;
|
||||
_serviceProvider = serviceProvider;
|
||||
_fido2 = fido2;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
var webAuthnProvider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn);
|
||||
if (!HasProperMetaData(webAuthnProvider))
|
||||
public async Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
|
||||
{
|
||||
return false;
|
||||
var userService = _serviceProvider.GetRequiredService<IUserService>();
|
||||
if (!(await userService.CanAccessPremium(user)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var webAuthnProvider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn);
|
||||
if (!HasProperMetaData(webAuthnProvider))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return await userService.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.WebAuthn, user);
|
||||
}
|
||||
|
||||
return await userService.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.WebAuthn, user);
|
||||
}
|
||||
|
||||
public async Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
||||
{
|
||||
var userService = _serviceProvider.GetRequiredService<IUserService>();
|
||||
if (!(await userService.CanAccessPremium(user)))
|
||||
public async Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
||||
{
|
||||
return null;
|
||||
var userService = _serviceProvider.GetRequiredService<IUserService>();
|
||||
if (!(await userService.CanAccessPremium(user)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn);
|
||||
var keys = LoadKeys(provider);
|
||||
var existingCredentials = keys.Select(key => key.Item2.Descriptor).ToList();
|
||||
|
||||
if (existingCredentials.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var exts = new AuthenticationExtensionsClientInputs()
|
||||
{
|
||||
UserVerificationMethod = true,
|
||||
AppID = CoreHelpers.U2fAppIdUrl(_globalSettings),
|
||||
};
|
||||
|
||||
var options = _fido2.GetAssertionOptions(existingCredentials, UserVerificationRequirement.Discouraged, exts);
|
||||
|
||||
// TODO: Remove this when newtonsoft legacy converters are gone
|
||||
provider.MetaData["login"] = JsonSerializer.Serialize(options);
|
||||
|
||||
var providers = user.GetTwoFactorProviders();
|
||||
providers[TwoFactorProviderType.WebAuthn] = provider;
|
||||
user.SetTwoFactorProviders(providers);
|
||||
await userService.UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.WebAuthn, logEvent: false);
|
||||
|
||||
return options.ToJson();
|
||||
}
|
||||
|
||||
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn);
|
||||
var keys = LoadKeys(provider);
|
||||
var existingCredentials = keys.Select(key => key.Item2.Descriptor).ToList();
|
||||
|
||||
if (existingCredentials.Count == 0)
|
||||
public async Task<bool> ValidateAsync(string purpose, string token, UserManager<User> manager, User user)
|
||||
{
|
||||
return null;
|
||||
var userService = _serviceProvider.GetRequiredService<IUserService>();
|
||||
if (!(await userService.CanAccessPremium(user)) || string.IsNullOrWhiteSpace(token))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn);
|
||||
var keys = LoadKeys(provider);
|
||||
|
||||
if (!provider.MetaData.ContainsKey("login"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var clientResponse = JsonSerializer.Deserialize<AuthenticatorAssertionRawResponse>(token,
|
||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
|
||||
var jsonOptions = provider.MetaData["login"].ToString();
|
||||
var options = AssertionOptions.FromJson(jsonOptions);
|
||||
|
||||
var webAuthCred = keys.Find(k => k.Item2.Descriptor.Id.SequenceEqual(clientResponse.Id));
|
||||
|
||||
if (webAuthCred == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IsUserHandleOwnerOfCredentialIdAsync callback = (args) => Task.FromResult(true);
|
||||
|
||||
var res = await _fido2.MakeAssertionAsync(clientResponse, options, webAuthCred.Item2.PublicKey, webAuthCred.Item2.SignatureCounter, callback);
|
||||
|
||||
provider.MetaData.Remove("login");
|
||||
|
||||
// Update SignatureCounter
|
||||
webAuthCred.Item2.SignatureCounter = res.Counter;
|
||||
|
||||
var providers = user.GetTwoFactorProviders();
|
||||
providers[TwoFactorProviderType.WebAuthn].MetaData[webAuthCred.Item1] = webAuthCred.Item2;
|
||||
user.SetTwoFactorProviders(providers);
|
||||
await userService.UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.WebAuthn, logEvent: false);
|
||||
|
||||
return res.Status == "ok";
|
||||
}
|
||||
|
||||
var exts = new AuthenticationExtensionsClientInputs()
|
||||
private bool HasProperMetaData(TwoFactorProvider provider)
|
||||
{
|
||||
UserVerificationMethod = true,
|
||||
AppID = CoreHelpers.U2fAppIdUrl(_globalSettings),
|
||||
};
|
||||
|
||||
var options = _fido2.GetAssertionOptions(existingCredentials, UserVerificationRequirement.Discouraged, exts);
|
||||
|
||||
// TODO: Remove this when newtonsoft legacy converters are gone
|
||||
provider.MetaData["login"] = JsonSerializer.Serialize(options);
|
||||
|
||||
var providers = user.GetTwoFactorProviders();
|
||||
providers[TwoFactorProviderType.WebAuthn] = provider;
|
||||
user.SetTwoFactorProviders(providers);
|
||||
await userService.UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.WebAuthn, logEvent: false);
|
||||
|
||||
return options.ToJson();
|
||||
}
|
||||
|
||||
public async Task<bool> ValidateAsync(string purpose, string token, UserManager<User> manager, User user)
|
||||
{
|
||||
var userService = _serviceProvider.GetRequiredService<IUserService>();
|
||||
if (!(await userService.CanAccessPremium(user)) || string.IsNullOrWhiteSpace(token))
|
||||
{
|
||||
return false;
|
||||
return provider?.MetaData?.Any() ?? false;
|
||||
}
|
||||
|
||||
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn);
|
||||
var keys = LoadKeys(provider);
|
||||
|
||||
if (!provider.MetaData.ContainsKey("login"))
|
||||
private List<Tuple<string, TwoFactorProvider.WebAuthnData>> LoadKeys(TwoFactorProvider provider)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var keys = new List<Tuple<string, TwoFactorProvider.WebAuthnData>>();
|
||||
if (!HasProperMetaData(provider))
|
||||
{
|
||||
return keys;
|
||||
}
|
||||
|
||||
var clientResponse = JsonSerializer.Deserialize<AuthenticatorAssertionRawResponse>(token,
|
||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
// Support up to 5 keys
|
||||
for (var i = 1; i <= 5; i++)
|
||||
{
|
||||
var keyName = $"Key{i}";
|
||||
if (provider.MetaData.ContainsKey(keyName))
|
||||
{
|
||||
var key = new TwoFactorProvider.WebAuthnData((dynamic)provider.MetaData[keyName]);
|
||||
|
||||
var jsonOptions = provider.MetaData["login"].ToString();
|
||||
var options = AssertionOptions.FromJson(jsonOptions);
|
||||
keys.Add(new Tuple<string, TwoFactorProvider.WebAuthnData>(keyName, key));
|
||||
}
|
||||
}
|
||||
|
||||
var webAuthCred = keys.Find(k => k.Item2.Descriptor.Id.SequenceEqual(clientResponse.Id));
|
||||
|
||||
if (webAuthCred == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IsUserHandleOwnerOfCredentialIdAsync callback = (args) => Task.FromResult(true);
|
||||
|
||||
var res = await _fido2.MakeAssertionAsync(clientResponse, options, webAuthCred.Item2.PublicKey, webAuthCred.Item2.SignatureCounter, callback);
|
||||
|
||||
provider.MetaData.Remove("login");
|
||||
|
||||
// Update SignatureCounter
|
||||
webAuthCred.Item2.SignatureCounter = res.Counter;
|
||||
|
||||
var providers = user.GetTwoFactorProviders();
|
||||
providers[TwoFactorProviderType.WebAuthn].MetaData[webAuthCred.Item1] = webAuthCred.Item2;
|
||||
user.SetTwoFactorProviders(providers);
|
||||
await userService.UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.WebAuthn, logEvent: false);
|
||||
|
||||
return res.Status == "ok";
|
||||
}
|
||||
|
||||
private bool HasProperMetaData(TwoFactorProvider provider)
|
||||
{
|
||||
return provider?.MetaData?.Any() ?? false;
|
||||
}
|
||||
|
||||
private List<Tuple<string, TwoFactorProvider.WebAuthnData>> LoadKeys(TwoFactorProvider provider)
|
||||
{
|
||||
var keys = new List<Tuple<string, TwoFactorProvider.WebAuthnData>>();
|
||||
if (!HasProperMetaData(provider))
|
||||
{
|
||||
return keys;
|
||||
}
|
||||
|
||||
// Support up to 5 keys
|
||||
for (var i = 1; i <= 5; i++)
|
||||
{
|
||||
var keyName = $"Key{i}";
|
||||
if (provider.MetaData.ContainsKey(keyName))
|
||||
{
|
||||
var key = new TwoFactorProvider.WebAuthnData((dynamic)provider.MetaData[keyName]);
|
||||
|
||||
keys.Add(new Tuple<string, TwoFactorProvider.WebAuthnData>(keyName, key));
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user