mirror of
https://github.com/bitwarden/server.git
synced 2025-05-20 19:14:32 -05: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.");
|
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;
|
return user;
|
||||||
|
@ -4,19 +4,27 @@ using Microsoft.AspNetCore.Identity;
|
|||||||
using Bit.Core.Models.Table;
|
using Bit.Core.Models.Table;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using OtpNet;
|
using OtpNet;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
|
||||||
namespace Bit.Core.Identity
|
namespace Bit.Core.Identity
|
||||||
{
|
{
|
||||||
public class AuthenticatorTokenProvider : IUserTwoFactorTokenProvider<User>
|
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 provider = user.GetTwoFactorProvider(TwoFactorProviderType.Authenticator);
|
||||||
|
if(string.IsNullOrWhiteSpace((string)provider.MetaData["Key"]))
|
||||||
var canGenerate = user.TwoFactorProviderIsEnabled(TwoFactorProviderType.Authenticator)
|
{
|
||||||
&& !string.IsNullOrWhiteSpace((string)provider.MetaData["Key"]);
|
return false;
|
||||||
|
}
|
||||||
return Task.FromResult(canGenerate);
|
return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.Authenticator, _userService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
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.Enums;
|
||||||
using Bit.Core.Utilities.Duo;
|
using Bit.Core.Utilities.Duo;
|
||||||
using Bit.Core.Models;
|
using Bit.Core.Models;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
|
||||||
namespace Bit.Core.Identity
|
namespace Bit.Core.Identity
|
||||||
{
|
{
|
||||||
public class DuoWebTokenProvider : IUserTwoFactorTokenProvider<User>
|
public class DuoWebTokenProvider : IUserTwoFactorTokenProvider<User>
|
||||||
{
|
{
|
||||||
|
private readonly IUserService _userService;
|
||||||
private readonly GlobalSettings _globalSettings;
|
private readonly GlobalSettings _globalSettings;
|
||||||
|
|
||||||
public DuoWebTokenProvider(GlobalSettings globalSettings)
|
public DuoWebTokenProvider(
|
||||||
|
IUserService userService,
|
||||||
|
GlobalSettings globalSettings)
|
||||||
{
|
{
|
||||||
|
_userService = userService;
|
||||||
_globalSettings = globalSettings;
|
_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 provider = user.GetTwoFactorProvider(TwoFactorProviderType.Duo);
|
||||||
var canGenerate = user.TwoFactorProviderIsEnabled(TwoFactorProviderType.Duo) && HasProperMetaData(provider);
|
if(!HasProperMetaData(provider))
|
||||||
return Task.FromResult(canGenerate);
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.Duo, _userService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
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.Models;
|
||||||
using U2F.Core.Exceptions;
|
using U2F.Core.Exceptions;
|
||||||
using System;
|
using System;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
|
||||||
namespace Bit.Core.Identity
|
namespace Bit.Core.Identity
|
||||||
{
|
{
|
||||||
public class U2fTokenProvider : IUserTwoFactorTokenProvider<User>
|
public class U2fTokenProvider : IUserTwoFactorTokenProvider<User>
|
||||||
{
|
{
|
||||||
|
private readonly IUserService _userService;
|
||||||
private readonly IU2fRepository _u2fRepository;
|
private readonly IU2fRepository _u2fRepository;
|
||||||
private readonly GlobalSettings _globalSettings;
|
private readonly GlobalSettings _globalSettings;
|
||||||
|
|
||||||
public U2fTokenProvider(
|
public U2fTokenProvider(
|
||||||
|
IUserService userService,
|
||||||
IU2fRepository u2fRepository,
|
IU2fRepository u2fRepository,
|
||||||
GlobalSettings globalSettings)
|
GlobalSettings globalSettings)
|
||||||
{
|
{
|
||||||
|
_userService = userService;
|
||||||
_u2fRepository = u2fRepository;
|
_u2fRepository = u2fRepository;
|
||||||
_globalSettings = globalSettings;
|
_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 provider = user.GetTwoFactorProvider(TwoFactorProviderType.U2f);
|
||||||
var canGenerate = user.TwoFactorProviderIsEnabled(TwoFactorProviderType.U2f) && HasProperMetaData(provider);
|
if(!HasProperMetaData(provider))
|
||||||
return Task.FromResult(canGenerate);
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.U2f, _userService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
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 Bit.Core.Enums;
|
||||||
using YubicoDotNetClient;
|
using YubicoDotNetClient;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
|
||||||
namespace Bit.Core.Identity
|
namespace Bit.Core.Identity
|
||||||
{
|
{
|
||||||
public class YubicoOtpTokenProvider : IUserTwoFactorTokenProvider<User>
|
public class YubicoOtpTokenProvider : IUserTwoFactorTokenProvider<User>
|
||||||
{
|
{
|
||||||
|
private readonly IUserService _userService;
|
||||||
private readonly GlobalSettings _globalSettings;
|
private readonly GlobalSettings _globalSettings;
|
||||||
|
|
||||||
public YubicoOtpTokenProvider(GlobalSettings globalSettings)
|
public YubicoOtpTokenProvider(
|
||||||
|
IUserService userService,
|
||||||
|
GlobalSettings globalSettings)
|
||||||
{
|
{
|
||||||
|
_userService = userService;
|
||||||
_globalSettings = globalSettings;
|
_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 provider = user.GetTwoFactorProvider(TwoFactorProviderType.YubiKey);
|
||||||
var canGenerate = user.TwoFactorProviderIsEnabled(TwoFactorProviderType.YubiKey)
|
if(!provider?.MetaData.Values.Any(v => !string.IsNullOrWhiteSpace((string)v)) ?? true)
|
||||||
&& (provider?.MetaData.Values.Any(v => !string.IsNullOrWhiteSpace((string)v)) ?? false);
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return Task.FromResult(canGenerate);
|
return await user.TwoFactorProviderIsEnabledAsync(TwoFactorProviderType.YubiKey, _userService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
public Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
|
||||||
|
@ -162,8 +162,13 @@ namespace Bit.Core.IdentityServer
|
|||||||
|
|
||||||
if(user.GetTwoFactorProviders() != null)
|
if(user.GetTwoFactorProviders() != null)
|
||||||
{
|
{
|
||||||
enabledProviders.AddRange(
|
foreach(var p in user.GetTwoFactorProviders())
|
||||||
user.GetTwoFactorProviders().Where(p => user.TwoFactorProviderIsEnabled(p.Key)));
|
{
|
||||||
|
if(await user.TwoFactorProviderIsEnabledAsync(p.Key, _userService))
|
||||||
|
{
|
||||||
|
enabledProviders.Add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!enabledProviders.Any())
|
if(!enabledProviders.Any())
|
||||||
@ -273,13 +278,14 @@ namespace Bit.Core.IdentityServer
|
|||||||
case TwoFactorProviderType.YubiKey:
|
case TwoFactorProviderType.YubiKey:
|
||||||
case TwoFactorProviderType.U2f:
|
case TwoFactorProviderType.U2f:
|
||||||
case TwoFactorProviderType.Remember:
|
case TwoFactorProviderType.Remember:
|
||||||
if(type != TwoFactorProviderType.Remember && !user.TwoFactorProviderIsEnabled(type))
|
if(type != TwoFactorProviderType.Remember &&
|
||||||
|
!(await user.TwoFactorProviderIsEnabledAsync(type, _userService)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return await _userManager.VerifyTwoFactorTokenAsync(user, type.ToString(), token);
|
return await _userManager.VerifyTwoFactorTokenAsync(user, type.ToString(), token);
|
||||||
case TwoFactorProviderType.Email:
|
case TwoFactorProviderType.Email:
|
||||||
if(!user.TwoFactorProviderIsEnabled(type))
|
if(!(await user.TwoFactorProviderIsEnabledAsync(type, _userService)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -305,7 +311,7 @@ namespace Bit.Core.IdentityServer
|
|||||||
case TwoFactorProviderType.U2f:
|
case TwoFactorProviderType.U2f:
|
||||||
case TwoFactorProviderType.Email:
|
case TwoFactorProviderType.Email:
|
||||||
case TwoFactorProviderType.YubiKey:
|
case TwoFactorProviderType.YubiKey:
|
||||||
if(!user.TwoFactorProviderIsEnabled(type))
|
if(!(await user.TwoFactorProviderIsEnabledAsync(type, _userService)))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ namespace Bit.Core.Models.Data
|
|||||||
Use2fa = organization.Use2fa;
|
Use2fa = organization.Use2fa;
|
||||||
Using2fa = organization.Use2fa && organization.TwoFactorProviders != null &&
|
Using2fa = organization.Use2fa && organization.TwoFactorProviders != null &&
|
||||||
organization.TwoFactorProviders != "{}";
|
organization.TwoFactorProviders != "{}";
|
||||||
|
UsersGetPremium = organization.UsersGetPremium;
|
||||||
Enabled = organization.Enabled;
|
Enabled = organization.Enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ namespace Bit.Core.Models.Data
|
|||||||
public bool UseEvents { get; set; }
|
public bool UseEvents { get; set; }
|
||||||
public bool Use2fa { get; set; }
|
public bool Use2fa { get; set; }
|
||||||
public bool Using2fa { get; set; }
|
public bool Using2fa { get; set; }
|
||||||
|
public bool UsersGetPremium { get; set; }
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Bit.Core.Models.Table
|
namespace Bit.Core.Models.Table
|
||||||
{
|
{
|
||||||
@ -92,15 +93,21 @@ namespace Bit.Core.Models.Table
|
|||||||
_twoFactorProviders = providers;
|
_twoFactorProviders = providers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TwoFactorProviderIsEnabled(TwoFactorProviderType provider)
|
public async Task<bool> TwoFactorProviderIsEnabledAsync(TwoFactorProviderType provider,
|
||||||
|
IUserService userService)
|
||||||
{
|
{
|
||||||
var providers = GetTwoFactorProviders();
|
var providers = GetTwoFactorProviders();
|
||||||
if(providers == null || !providers.ContainsKey(provider))
|
if(providers == null || !providers.ContainsKey(provider) || !providers[provider].Enabled)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return providers[provider].Enabled && (Premium || !TwoFactorProvider.RequiresPremium(provider));
|
if(!TwoFactorProvider.RequiresPremium(provider))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await userService.CanAccessPremium(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TwoFactorIsEnabled()
|
public bool TwoFactorIsEnabled()
|
||||||
|
@ -53,5 +53,6 @@ namespace Bit.Core.Services
|
|||||||
Task UpdatePremiumExpirationAsync(Guid userId, DateTime? expirationDate);
|
Task UpdatePremiumExpirationAsync(Guid userId, DateTime? expirationDate);
|
||||||
Task<UserLicense> GenerateLicenseAsync(User user, BillingInfo billingInfo = null);
|
Task<UserLicense> GenerateLicenseAsync(User user, BillingInfo billingInfo = null);
|
||||||
Task<bool> CheckPasswordAsync(User user, string password);
|
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 IEnumerable<IPasswordValidator<User>> _passwordValidators;
|
||||||
private readonly ILicensingService _licenseService;
|
private readonly ILicensingService _licenseService;
|
||||||
private readonly IEventService _eventService;
|
private readonly IEventService _eventService;
|
||||||
|
private readonly IApplicationCacheService _applicationCacheService;
|
||||||
private readonly IDataProtector _organizationServiceDataProtector;
|
private readonly IDataProtector _organizationServiceDataProtector;
|
||||||
private readonly CurrentContext _currentContext;
|
private readonly CurrentContext _currentContext;
|
||||||
private readonly GlobalSettings _globalSettings;
|
private readonly GlobalSettings _globalSettings;
|
||||||
@ -61,6 +62,7 @@ namespace Bit.Core.Services
|
|||||||
ILogger<UserManager<User>> logger,
|
ILogger<UserManager<User>> logger,
|
||||||
ILicensingService licenseService,
|
ILicensingService licenseService,
|
||||||
IEventService eventService,
|
IEventService eventService,
|
||||||
|
IApplicationCacheService applicationCacheService,
|
||||||
IDataProtectionProvider dataProtectionProvider,
|
IDataProtectionProvider dataProtectionProvider,
|
||||||
CurrentContext currentContext,
|
CurrentContext currentContext,
|
||||||
GlobalSettings globalSettings)
|
GlobalSettings globalSettings)
|
||||||
@ -87,6 +89,7 @@ namespace Bit.Core.Services
|
|||||||
_passwordValidators = passwordValidators;
|
_passwordValidators = passwordValidators;
|
||||||
_licenseService = licenseService;
|
_licenseService = licenseService;
|
||||||
_eventService = eventService;
|
_eventService = eventService;
|
||||||
|
_applicationCacheService = applicationCacheService;
|
||||||
_organizationServiceDataProtector = dataProtectionProvider.CreateProtector(
|
_organizationServiceDataProtector = dataProtectionProvider.CreateProtector(
|
||||||
"OrganizationServiceDataProtector");
|
"OrganizationServiceDataProtector");
|
||||||
_currentContext = currentContext;
|
_currentContext = currentContext;
|
||||||
@ -822,6 +825,22 @@ namespace Bit.Core.Services
|
|||||||
return success;
|
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,
|
private async Task<IdentityResult> UpdatePasswordHash(User user, string newPassword,
|
||||||
bool validatePassword = true, bool refreshStamp = true)
|
bool validatePassword = true, bool refreshStamp = true)
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,7 @@ BEGIN
|
|||||||
ELSE
|
ELSE
|
||||||
0
|
0
|
||||||
END AS [Using2fa],
|
END AS [Using2fa],
|
||||||
|
[UsersGetPremium],
|
||||||
[Enabled]
|
[Enabled]
|
||||||
FROM
|
FROM
|
||||||
[dbo].[Organization]
|
[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…
x
Reference in New Issue
Block a user