mirror of
https://github.com/bitwarden/server.git
synced 2025-02-16 01:51:21 +01:00
CanAccessPremium checks instead of User.Premium
This commit is contained in:
parent
90387cca0c
commit
c41a1e0936
@ -342,9 +342,9 @@ namespace Bit.Api.Controllers
|
||||
throw new BadRequestException("MasterPasswordHash", "Invalid password.");
|
||||
}
|
||||
|
||||
if(premium && !user.Premium)
|
||||
if(premium && !(await _userService.CanAccessPremium(user)))
|
||||
{
|
||||
throw new BadRequestException("Premium membership required.");
|
||||
throw new BadRequestException("Premium status is required.");
|
||||
}
|
||||
|
||||
return user;
|
||||
|
@ -4,19 +4,27 @@ using Microsoft.AspNetCore.Identity;
|
||||
using Bit.Core.Models.Table;
|
||||
using Bit.Core.Enums;
|
||||
using OtpNet;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Core.Identity
|
||||
{
|
||||
public class AuthenticatorTokenProvider : IUserTwoFactorTokenProvider<User>
|
||||
{
|
||||
public Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
|
||||
private readonly IUserService _userService;
|
||||
|
||||
public AuthenticatorTokenProvider(IUserService userService)
|
||||
{
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
public async Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
|
||||
{
|
||||
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.Authenticator);
|
||||
|
||||
var canGenerate = user.TwoFactorProviderIsEnabled(TwoFactorProviderType.Authenticator)
|
||||
&& !string.IsNullOrWhiteSpace((string)provider.MetaData["Key"]);
|
||||
|
||||
return Task.FromResult(canGenerate);
|
||||
if(string.IsNullOrWhiteSpace((string)provider.MetaData["Key"]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.Authenticator, _userService);
|
||||
}
|
||||
|
||||
public Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
||||
|
@ -4,28 +4,37 @@ using Bit.Core.Models.Table;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities.Duo;
|
||||
using Bit.Core.Models;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Core.Identity
|
||||
{
|
||||
public class DuoWebTokenProvider : IUserTwoFactorTokenProvider<User>
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
public DuoWebTokenProvider(GlobalSettings globalSettings)
|
||||
public DuoWebTokenProvider(
|
||||
IUserService userService,
|
||||
GlobalSettings globalSettings)
|
||||
{
|
||||
_userService = userService;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
|
||||
public async Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
|
||||
{
|
||||
if(!user.Premium)
|
||||
if(!(await _userService.CanAccessPremium(user)))
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.Duo);
|
||||
var canGenerate = user.TwoFactorProviderIsEnabled(TwoFactorProviderType.Duo) && HasProperMetaData(provider);
|
||||
return Task.FromResult(canGenerate);
|
||||
if(!HasProperMetaData(provider))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.Duo, _userService);
|
||||
}
|
||||
|
||||
public Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
||||
|
@ -11,32 +11,40 @@ using U2fLib = U2F.Core.Crypto.U2F;
|
||||
using U2F.Core.Models;
|
||||
using U2F.Core.Exceptions;
|
||||
using System;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Core.Identity
|
||||
{
|
||||
public class U2fTokenProvider : IUserTwoFactorTokenProvider<User>
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private readonly IU2fRepository _u2fRepository;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
public U2fTokenProvider(
|
||||
IUserService userService,
|
||||
IU2fRepository u2fRepository,
|
||||
GlobalSettings globalSettings)
|
||||
{
|
||||
_userService = userService;
|
||||
_u2fRepository = u2fRepository;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
|
||||
public async Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
|
||||
{
|
||||
if(!user.Premium)
|
||||
if(!(await _userService.CanAccessPremium(user)))
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.U2f);
|
||||
var canGenerate = user.TwoFactorProviderIsEnabled(TwoFactorProviderType.U2f) && HasProperMetaData(provider);
|
||||
return Task.FromResult(canGenerate);
|
||||
if(!HasProperMetaData(provider))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.U2f, _userService);
|
||||
}
|
||||
|
||||
public async Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
||||
|
@ -4,30 +4,37 @@ using Bit.Core.Models.Table;
|
||||
using Bit.Core.Enums;
|
||||
using YubicoDotNetClient;
|
||||
using System.Linq;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Core.Identity
|
||||
{
|
||||
public class YubicoOtpTokenProvider : IUserTwoFactorTokenProvider<User>
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
public YubicoOtpTokenProvider(GlobalSettings globalSettings)
|
||||
public YubicoOtpTokenProvider(
|
||||
IUserService userService,
|
||||
GlobalSettings globalSettings)
|
||||
{
|
||||
_userService = userService;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
public Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
|
||||
public async Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
|
||||
{
|
||||
if(!user.Premium)
|
||||
if(!(await _userService.CanAccessPremium(user)))
|
||||
{
|
||||
return Task.FromResult(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
var provider = user.GetTwoFactorProvider(TwoFactorProviderType.YubiKey);
|
||||
var canGenerate = user.TwoFactorProviderIsEnabled(TwoFactorProviderType.YubiKey)
|
||||
&& (provider?.MetaData.Values.Any(v => !string.IsNullOrWhiteSpace((string)v)) ?? false);
|
||||
if(!provider?.MetaData.Values.Any(v => !string.IsNullOrWhiteSpace((string)v)) ?? true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Task.FromResult(canGenerate);
|
||||
return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.YubiKey, _userService);
|
||||
}
|
||||
|
||||
public Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
||||
|
@ -162,8 +162,13 @@ namespace Bit.Core.IdentityServer
|
||||
|
||||
if(user.GetTwoFactorProviders() != null)
|
||||
{
|
||||
enabledProviders.AddRange(
|
||||
user.GetTwoFactorProviders().Where(p => user.TwoFactorProviderIsEnabled(p.Key)));
|
||||
foreach(var p in user.GetTwoFactorProviders())
|
||||
{
|
||||
if(await user.TwoFactorProviderIsEnabledAsync(p.Key, _userService))
|
||||
{
|
||||
enabledProviders.Add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!enabledProviders.Any())
|
||||
@ -273,13 +278,14 @@ namespace Bit.Core.IdentityServer
|
||||
case TwoFactorProviderType.YubiKey:
|
||||
case TwoFactorProviderType.U2f:
|
||||
case TwoFactorProviderType.Remember:
|
||||
if(type != TwoFactorProviderType.Remember && !user.TwoFactorProviderIsEnabled(type))
|
||||
if(type != TwoFactorProviderType.Remember &&
|
||||
!(await user.TwoFactorProviderIsEnabledAsync(type, _userService)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return await _userManager.VerifyTwoFactorTokenAsync(user, type.ToString(), token);
|
||||
case TwoFactorProviderType.Email:
|
||||
if(!user.TwoFactorProviderIsEnabled(type))
|
||||
if(!(await user.TwoFactorProviderIsEnabledAsync(type, _userService)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -305,7 +311,7 @@ namespace Bit.Core.IdentityServer
|
||||
case TwoFactorProviderType.U2f:
|
||||
case TwoFactorProviderType.Email:
|
||||
case TwoFactorProviderType.YubiKey:
|
||||
if(!user.TwoFactorProviderIsEnabled(type))
|
||||
if(!(await user.TwoFactorProviderIsEnabledAsync(type, _userService)))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace Bit.Core.Models.Data
|
||||
Use2fa = organization.Use2fa;
|
||||
Using2fa = organization.Use2fa && organization.TwoFactorProviders != null &&
|
||||
organization.TwoFactorProviders != "{}";
|
||||
UsersGetPremium = organization.UsersGetPremium;
|
||||
Enabled = organization.Enabled;
|
||||
}
|
||||
|
||||
@ -21,6 +22,7 @@ namespace Bit.Core.Models.Data
|
||||
public bool UseEvents { get; set; }
|
||||
public bool Use2fa { get; set; }
|
||||
public bool Using2fa { get; set; }
|
||||
public bool UsersGetPremium { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Exceptions;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.Core.Models.Table
|
||||
{
|
||||
@ -92,15 +93,21 @@ namespace Bit.Core.Models.Table
|
||||
_twoFactorProviders = providers;
|
||||
}
|
||||
|
||||
public bool TwoFactorProviderIsEnabled(TwoFactorProviderType provider)
|
||||
public async Task<bool> TwoFactorProviderIsEnabledAsync(TwoFactorProviderType provider,
|
||||
IUserService userService)
|
||||
{
|
||||
var providers = GetTwoFactorProviders();
|
||||
if(providers == null || !providers.ContainsKey(provider))
|
||||
if(providers == null || !providers.ContainsKey(provider) || !providers[provider].Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return providers[provider].Enabled && (Premium || !TwoFactorProvider.RequiresPremium(provider));
|
||||
if(!TwoFactorProvider.RequiresPremium(provider))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return await userService.CanAccessPremium(this);
|
||||
}
|
||||
|
||||
public bool TwoFactorIsEnabled()
|
||||
@ -111,7 +118,7 @@ namespace Bit.Core.Models.Table
|
||||
return false;
|
||||
}
|
||||
|
||||
return providers.Any(p => (p.Value?.Enabled ?? false) &&
|
||||
return providers.Any(p => (p.Value?.Enabled ?? false) &&
|
||||
(Premium || !TwoFactorProvider.RequiresPremium(p.Key)));
|
||||
}
|
||||
|
||||
|
@ -53,5 +53,6 @@ namespace Bit.Core.Services
|
||||
Task UpdatePremiumExpirationAsync(Guid userId, DateTime? expirationDate);
|
||||
Task<UserLicense> GenerateLicenseAsync(User user, BillingInfo billingInfo = null);
|
||||
Task<bool> CheckPasswordAsync(User user, string password);
|
||||
Task<bool> CanAccessPremium(User user);
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ namespace Bit.Core.Services
|
||||
private readonly IEnumerable<IPasswordValidator<User>> _passwordValidators;
|
||||
private readonly ILicensingService _licenseService;
|
||||
private readonly IEventService _eventService;
|
||||
private readonly IApplicationCacheService _applicationCacheService;
|
||||
private readonly IDataProtector _organizationServiceDataProtector;
|
||||
private readonly CurrentContext _currentContext;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
@ -61,6 +62,7 @@ namespace Bit.Core.Services
|
||||
ILogger<UserManager<User>> logger,
|
||||
ILicensingService licenseService,
|
||||
IEventService eventService,
|
||||
IApplicationCacheService applicationCacheService,
|
||||
IDataProtectionProvider dataProtectionProvider,
|
||||
CurrentContext currentContext,
|
||||
GlobalSettings globalSettings)
|
||||
@ -87,6 +89,7 @@ namespace Bit.Core.Services
|
||||
_passwordValidators = passwordValidators;
|
||||
_licenseService = licenseService;
|
||||
_eventService = eventService;
|
||||
_applicationCacheService = applicationCacheService;
|
||||
_organizationServiceDataProtector = dataProtectionProvider.CreateProtector(
|
||||
"OrganizationServiceDataProtector");
|
||||
_currentContext = currentContext;
|
||||
@ -822,6 +825,22 @@ namespace Bit.Core.Services
|
||||
return success;
|
||||
}
|
||||
|
||||
public async Task<bool> CanAccessPremium(User user)
|
||||
{
|
||||
if(user.Premium)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(!_currentContext?.Organizations?.Any() ?? true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
|
||||
return _currentContext.Organizations.Any(o => orgAbilities.ContainsKey(o.Id) &&
|
||||
orgAbilities[o.Id].UsersGetPremium);
|
||||
}
|
||||
|
||||
private async Task<IdentityResult> UpdatePasswordHash(User user, string newPassword,
|
||||
bool validatePassword = true, bool refreshStamp = true)
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ BEGIN
|
||||
ELSE
|
||||
0
|
||||
END AS [Using2fa],
|
||||
[UsersGetPremium],
|
||||
[Enabled]
|
||||
FROM
|
||||
[dbo].[Organization]
|
||||
|
27
util/Setup/DbScripts/2018-08-28_00_PremiumOrgAbilities.sql
Normal file
27
util/Setup/DbScripts/2018-08-28_00_PremiumOrgAbilities.sql
Normal file
@ -0,0 +1,27 @@
|
||||
IF OBJECT_ID('[dbo].[Organization_ReadAbilities]') IS NOT NULL
|
||||
BEGIN
|
||||
DROP PROCEDURE [dbo].[Organization_ReadAbilities]
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE PROCEDURE [dbo].[Organization_ReadAbilities]
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON
|
||||
|
||||
SELECT
|
||||
[Id],
|
||||
[UseEvents],
|
||||
[Use2fa],
|
||||
CASE
|
||||
WHEN [Use2fa] = 1 AND [TwoFactorProviders] IS NOT NULL AND [TwoFactorProviders] != '{}' THEN
|
||||
1
|
||||
ELSE
|
||||
0
|
||||
END AS [Using2fa],
|
||||
[UsersGetPremium],
|
||||
[Enabled]
|
||||
FROM
|
||||
[dbo].[Organization]
|
||||
END
|
||||
GO
|
Loading…
Reference in New Issue
Block a user