From 76818fa3856aee2a9058069099da35ea499e76f5 Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Fri, 27 Mar 2020 12:44:21 +0900 Subject: [PATCH] Rename API Keys folder to GreenField --- .../APIKeys/APIKeyAuthenticationHandler.cs | 100 ------------------ .../APIKeys/APIKeyAuthenticationOptions.cs | 8 -- .../APIKeys/APIKeyAuthorizationHandler.cs | 96 ----------------- .../Security/APIKeys/APIKeyConstants.cs | 15 --- .../Security/APIKeys/APIKeyExtensions.cs | 64 ----------- .../Security/APIKeys/APIKeyRepository.cs | 72 ------------- 6 files changed, 355 deletions(-) delete mode 100644 BTCPayServer/Security/APIKeys/APIKeyAuthenticationHandler.cs delete mode 100644 BTCPayServer/Security/APIKeys/APIKeyAuthenticationOptions.cs delete mode 100644 BTCPayServer/Security/APIKeys/APIKeyAuthorizationHandler.cs delete mode 100644 BTCPayServer/Security/APIKeys/APIKeyConstants.cs delete mode 100644 BTCPayServer/Security/APIKeys/APIKeyExtensions.cs delete mode 100644 BTCPayServer/Security/APIKeys/APIKeyRepository.cs diff --git a/BTCPayServer/Security/APIKeys/APIKeyAuthenticationHandler.cs b/BTCPayServer/Security/APIKeys/APIKeyAuthenticationHandler.cs deleted file mode 100644 index bfb9b4c7e..000000000 --- a/BTCPayServer/Security/APIKeys/APIKeyAuthenticationHandler.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Text; -using System.Text.Encodings.Web; -using System.Threading.Tasks; -using BTCPayServer.Client; -using BTCPayServer.Data; -using BTCPayServer.Security.Bitpay; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace BTCPayServer.Security.APIKeys -{ - public class APIKeyAuthenticationHandler : AuthenticationHandler - { - private readonly APIKeyRepository _apiKeyRepository; - private readonly IOptionsMonitor _identityOptions; - private readonly SignInManager _signInManager; - private readonly UserManager _userManager; - - public APIKeyAuthenticationHandler( - APIKeyRepository apiKeyRepository, - IOptionsMonitor identityOptions, - IOptionsMonitor options, - ILoggerFactory logger, - UrlEncoder encoder, - ISystemClock clock, - SignInManager signInManager, - UserManager userManager) : base(options, logger, encoder, clock) - { - _apiKeyRepository = apiKeyRepository; - _identityOptions = identityOptions; - _signInManager = signInManager; - _userManager = userManager; - } - - protected override async Task HandleAuthenticateAsync() - { - var res = await HandleApiKeyAuthenticateResult(); - if (res.None) - { - return await HandleBasicAuthenticateAsync(); - } - - return res; - } - - private async Task HandleApiKeyAuthenticateResult() - { - if (!Context.Request.HttpContext.GetAPIKey(out var apiKey) || string.IsNullOrEmpty(apiKey)) - return AuthenticateResult.NoResult(); - - var key = await _apiKeyRepository.GetKey(apiKey); - - if (key == null) - { - return AuthenticateResult.Fail("ApiKey authentication failed"); - } - - List claims = new List(); - claims.Add(new Claim(_identityOptions.CurrentValue.ClaimsIdentity.UserIdClaimType, key.UserId)); - claims.AddRange(Permission.ToPermissions(key.Permissions).Select(permission => - new Claim(APIKeyConstants.ClaimTypes.Permission, permission.ToString()))); - return AuthenticateResult.Success(new AuthenticationTicket( - new ClaimsPrincipal(new ClaimsIdentity(claims, APIKeyConstants.AuthenticationType)), - APIKeyConstants.AuthenticationType)); - } - - private async Task HandleBasicAuthenticateAsync() - { - string authHeader = Context.Request.Headers["Authorization"]; - - if (authHeader == null || !authHeader.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase)) return AuthenticateResult.NoResult(); - var encodedUsernamePassword = authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim(); - var decodedUsernamePassword = - Encoding.UTF8.GetString(Convert.FromBase64String(encodedUsernamePassword)).Split(':'); - var username = decodedUsernamePassword[0]; - var password = decodedUsernamePassword[1]; - - var result = await _signInManager.PasswordSignInAsync(username, password, true, true); - if (!result.Succeeded) return AuthenticateResult.Fail(result.ToString()); - - var user = await _userManager.FindByNameAsync(username); - var claims = new List() - { - new Claim(_identityOptions.CurrentValue.ClaimsIdentity.UserIdClaimType, user.Id), - new Claim(APIKeyConstants.ClaimTypes.Permission, - Permission.Create(Policies.Unrestricted).ToString()) - }; - - return AuthenticateResult.Success(new AuthenticationTicket( - new ClaimsPrincipal(new ClaimsIdentity(claims, APIKeyConstants.AuthenticationType)), - APIKeyConstants.AuthenticationType)); - } - } -} diff --git a/BTCPayServer/Security/APIKeys/APIKeyAuthenticationOptions.cs b/BTCPayServer/Security/APIKeys/APIKeyAuthenticationOptions.cs deleted file mode 100644 index d03e796cd..000000000 --- a/BTCPayServer/Security/APIKeys/APIKeyAuthenticationOptions.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Microsoft.AspNetCore.Authentication; - -namespace BTCPayServer.Security.Bitpay -{ - public class APIKeyAuthenticationOptions : AuthenticationSchemeOptions - { - } -} diff --git a/BTCPayServer/Security/APIKeys/APIKeyAuthorizationHandler.cs b/BTCPayServer/Security/APIKeys/APIKeyAuthorizationHandler.cs deleted file mode 100644 index 2b5b147e0..000000000 --- a/BTCPayServer/Security/APIKeys/APIKeyAuthorizationHandler.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using BTCPayServer.Client; -using BTCPayServer.Data; -using BTCPayServer.Services.Stores; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Identity; - -namespace BTCPayServer.Security.APIKeys -{ - public class APIKeyAuthorizationHandler : AuthorizationHandler - - { - private readonly HttpContext _HttpContext; - private readonly UserManager _userManager; - private readonly StoreRepository _storeRepository; - - public APIKeyAuthorizationHandler(IHttpContextAccessor httpContextAccessor, - UserManager userManager, - StoreRepository storeRepository) - { - _HttpContext = httpContextAccessor.HttpContext; - _userManager = userManager; - _storeRepository = storeRepository; - } - - protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, - PolicyRequirement requirement) - { - if (context.User.Identity.AuthenticationType != APIKeyConstants.AuthenticationType) - return; - - bool success = false; - switch (requirement.Policy) - { - case Policies.CanModifyProfile: - case Policies.CanViewProfile: - case Policies.Unrestricted: - success = context.HasPermission(Permission.Create(requirement.Policy)); - break; - - case Policies.CanViewStoreSettings: - case Policies.CanModifyStoreSettings: - var storeId = _HttpContext.GetImplicitStoreId(); - var userid = _userManager.GetUserId(context.User); - // Specific store action - if (storeId != null) - { - if (context.HasPermission(Permission.Create(requirement.Policy, storeId))) - { - if (string.IsNullOrEmpty(userid)) - break; - var store = await _storeRepository.FindStore((string)storeId, userid); - if (store == null) - break; - success = true; - _HttpContext.SetStoreData(store); - } - } - else - { - var stores = await _storeRepository.GetStoresByUserId(userid); - List permissionedStores = new List(); - foreach (var store in stores) - { - if (context.HasPermission(Permission.Create(requirement.Policy, store.Id))) - permissionedStores.Add(store); - } - _HttpContext.SetStoresData(stores.ToArray()); - success = true; - } - break; - case Policies.CanCreateUser: - case Policies.CanModifyServerSettings: - if (context.HasPermission(Permission.Create(requirement.Policy))) - { - var user = await _userManager.GetUserAsync(context.User); - if (user == null) - break; - if (!await _userManager.IsInRoleAsync(user, Roles.ServerAdmin)) - break; - success = true; - } - break; - } - - if (success) - { - context.Succeed(requirement); - } - } - } -} diff --git a/BTCPayServer/Security/APIKeys/APIKeyConstants.cs b/BTCPayServer/Security/APIKeys/APIKeyConstants.cs deleted file mode 100644 index 3ec317a53..000000000 --- a/BTCPayServer/Security/APIKeys/APIKeyConstants.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using BTCPayServer.Client; - -namespace BTCPayServer.Security.APIKeys -{ - public static class APIKeyConstants - { - public const string AuthenticationType = "APIKey"; - - public static class ClaimTypes - { - public const string Permission = "APIKey.Permission"; - } - } -} diff --git a/BTCPayServer/Security/APIKeys/APIKeyExtensions.cs b/BTCPayServer/Security/APIKeys/APIKeyExtensions.cs deleted file mode 100644 index 8671b6992..000000000 --- a/BTCPayServer/Security/APIKeys/APIKeyExtensions.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Linq; -using BTCPayServer.Client; -using BTCPayServer.Security.Bitpay; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Primitives; - -namespace BTCPayServer.Security.APIKeys -{ - public static class APIKeyExtensions - { - public static bool GetAPIKey(this HttpContext httpContext, out StringValues apiKey) - { - if (httpContext.Request.Headers.TryGetValue("Authorization", out var value) && - value.ToString().StartsWith("token ", StringComparison.InvariantCultureIgnoreCase)) - { - apiKey = value.ToString().Substring("token ".Length); - return true; - } - - return false; - } - - public static AuthenticationBuilder AddAPIKeyAuthentication(this AuthenticationBuilder builder) - { - builder.AddScheme(AuthenticationSchemes.Greenfield, - o => { }); - return builder; - } - - public static IServiceCollection AddAPIKeyAuthentication(this IServiceCollection serviceCollection) - { - serviceCollection.AddSingleton(); - serviceCollection.AddScoped(); - return serviceCollection; - } - - public static string[] GetPermissions(this AuthorizationHandlerContext context) - { - return context.User.Claims.Where(c => - c.Type.Equals(APIKeyConstants.ClaimTypes.Permission, StringComparison.InvariantCultureIgnoreCase)) - .Select(claim => claim.Value).ToArray(); - } - - public static bool HasPermission(this AuthorizationHandlerContext context, Permission permission) - { - foreach (var claim in context.User.Claims.Where(c => - c.Type.Equals(APIKeyConstants.ClaimTypes.Permission, StringComparison.InvariantCultureIgnoreCase))) - { - if (Permission.TryParse(claim.Value, out var claimPermission)) - { - if (claimPermission.Contains(permission)) - { - return true; - } - } - } - return false; - } - } -} diff --git a/BTCPayServer/Security/APIKeys/APIKeyRepository.cs b/BTCPayServer/Security/APIKeys/APIKeyRepository.cs deleted file mode 100644 index c30fd7a8c..000000000 --- a/BTCPayServer/Security/APIKeys/APIKeyRepository.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using BTCPayServer.Data; -using Microsoft.EntityFrameworkCore; - -namespace BTCPayServer.Security.APIKeys -{ - public class APIKeyRepository - { - private readonly ApplicationDbContextFactory _applicationDbContextFactory; - - public APIKeyRepository(ApplicationDbContextFactory applicationDbContextFactory) - { - _applicationDbContextFactory = applicationDbContextFactory; - } - - public async Task GetKey(string apiKey) - { - using (var context = _applicationDbContextFactory.CreateContext()) - { - return await EntityFrameworkQueryableExtensions.SingleOrDefaultAsync(context.ApiKeys, - data => data.Id == apiKey && data.Type != APIKeyType.Legacy); - } - } - - public async Task> GetKeys(APIKeyQuery query) - { - using (var context = _applicationDbContextFactory.CreateContext()) - { - var queryable = context.ApiKeys.AsQueryable(); - if (query?.UserId != null && query.UserId.Any()) - { - queryable = queryable.Where(data => query.UserId.Contains(data.UserId)); - } - - return await queryable.ToListAsync(); - } - } - - public async Task CreateKey(APIKeyData key) - { - if (key.Type == APIKeyType.Legacy || !string.IsNullOrEmpty(key.StoreId) || string.IsNullOrEmpty(key.UserId)) - { - throw new InvalidOperationException("cannot save a bitpay legacy api key with this repository"); - } - - using (var context = _applicationDbContextFactory.CreateContext()) - { - await context.ApiKeys.AddAsync(key); - await context.SaveChangesAsync(); - } - } - - public async Task Remove(string id, string getUserId) - { - using (var context = _applicationDbContextFactory.CreateContext()) - { - var key = await EntityFrameworkQueryableExtensions.SingleOrDefaultAsync(context.ApiKeys, - data => data.Id == id && data.UserId == getUserId); - context.ApiKeys.Remove(key); - await context.SaveChangesAsync(); - } - } - - public class APIKeyQuery - { - public string[] UserId { get; set; } - } - } -}