mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-23 22:46:49 +01:00
Move Bearer to Greenfield
This commit is contained in:
parent
f2b62bce8e
commit
aafedd7ccb
5 changed files with 77 additions and 20 deletions
|
@ -3,10 +3,10 @@ namespace BTCPayServer.Abstractions.Constants
|
|||
public class AuthenticationSchemes
|
||||
{
|
||||
public const string Cookie = "Identity.Application";
|
||||
public const string Bearer = "Identity.Bearer";
|
||||
public const string Bitpay = "Bitpay";
|
||||
public const string Greenfield = "Greenfield.APIKeys,Greenfield.Basic";
|
||||
public const string Greenfield = "Greenfield.APIKeys,Greenfield.Basic,Greenfield.Bearer";
|
||||
public const string GreenfieldAPIKeys = "Greenfield.APIKeys";
|
||||
public const string GreenfieldBasic = "Greenfield.Basic";
|
||||
public const string GreenfieldBearer = "Greenfield.Bearer";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ public class BlockHeaders : IEnumerable<RPCBlockHeader>
|
|||
}
|
||||
}
|
||||
|
||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Bearer)]
|
||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.GreenfieldBearer)]
|
||||
public class BTCPayAppHub : Hub<IBTCPayAppHubClient>, IBTCPayAppHubServer
|
||||
{
|
||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||
|
|
|
@ -6,14 +6,9 @@ using BTCPayApp.CommonServer;
|
|||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Common;
|
||||
using BTCPayServer.Controllers;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Events;
|
||||
using BTCPayServer.Security.Greenfield;
|
||||
using BTCPayServer.Services;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.Stores;
|
||||
using Microsoft.AspNetCore.Authentication.BearerToken;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
@ -23,27 +18,19 @@ using Microsoft.AspNetCore.Identity;
|
|||
using Microsoft.AspNetCore.Identity.Data;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NBitcoin;
|
||||
using NBitcoin.DataEncoders;
|
||||
using NBXplorer;
|
||||
using NicolasDorier.RateLimits;
|
||||
|
||||
namespace BTCPayServer.App;
|
||||
|
||||
[ApiController]
|
||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Bearer)]
|
||||
[Authorize(AuthenticationSchemes = AuthenticationSchemes.GreenfieldBearer)]
|
||||
[Route("btcpayapp")]
|
||||
public class BtcPayAppController(
|
||||
APIKeyRepository apiKeyRepository,
|
||||
StoreRepository storeRepository,
|
||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||
IExplorerClientProvider explorerClientProvider,
|
||||
EventAggregator eventAggregator,
|
||||
SignInManager<ApplicationUser> signInManager,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
TimeProvider timeProvider,
|
||||
PaymentMethodHandlerDictionary handlers,
|
||||
IFileService fileService,
|
||||
ISettingsRepository settingsRepository,
|
||||
UriResolver uriResolver,
|
||||
IOptionsMonitor<BearerTokenOptions> bearerTokenOptions)
|
||||
|
@ -130,7 +117,7 @@ public class BtcPayAppController(
|
|||
return TypedResults.Problem(message, statusCode: 401);
|
||||
}
|
||||
|
||||
signInManager.AuthenticationScheme = AuthenticationSchemes.Bearer;
|
||||
signInManager.AuthenticationScheme = AuthenticationSchemes.GreenfieldBearer;
|
||||
var signInResult = await signInManager.PasswordSignInAsync(login.Email, login.Password, true, true);
|
||||
if (signInResult.RequiresTwoFactor)
|
||||
{
|
||||
|
@ -154,7 +141,7 @@ public class BtcPayAppController(
|
|||
[RateLimitsFilter(ZoneLimits.Login, Scope = RateLimitsScope.RemoteAddress)]
|
||||
public async Task<Results<Ok<AccessTokenResponse>, UnauthorizedHttpResult, SignInHttpResult, ChallengeHttpResult>> Refresh(RefreshRequest refresh)
|
||||
{
|
||||
const string scheme = AuthenticationSchemes.Bearer;
|
||||
const string scheme = AuthenticationSchemes.GreenfieldBearer;
|
||||
var authenticationTicket = bearerTokenOptions.Get(scheme).RefreshTokenProtector.Unprotect(refresh.RefreshToken);
|
||||
var expiresUtc = authenticationTicket?.Properties.ExpiresUtc;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace BTCPayServer.Security
|
|||
|
||||
public static AuthenticationBuilder AddBearerAuthentication(this AuthenticationBuilder builder)
|
||||
{
|
||||
builder.AddBearerToken(AuthenticationSchemes.Bearer, options =>
|
||||
builder.AddBearerToken(AuthenticationSchemes.GreenfieldBearer, options =>
|
||||
{
|
||||
options.BearerTokenExpiration = TimeSpan.FromMinutes(30.0);
|
||||
options.RefreshTokenExpiration = TimeSpan.FromDays(3.0);
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
#nullable enable
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Client;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Options;
|
||||
using AuthenticationSchemes = BTCPayServer.Abstractions.Constants.AuthenticationSchemes;
|
||||
using StoreData = BTCPayServer.Client.Models.StoreData;
|
||||
|
||||
namespace BTCPayServer.Security.GreenField;
|
||||
|
||||
public class BearerAuthorizationHandler(IOptionsMonitor<IdentityOptions> identityOptions)
|
||||
: AuthorizationHandler<PolicyRequirement>
|
||||
{
|
||||
//TODO: In the future, we will add these store permissions to actual aspnet roles, and remove this class.
|
||||
private static readonly PermissionSet _serverAdminRolePermissions = new([Permission.Create(Policies.CanViewStoreSettings)]);
|
||||
|
||||
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PolicyRequirement requirement)
|
||||
{
|
||||
if (context.User.Identity?.AuthenticationType != AuthenticationSchemes.GreenfieldBearer)
|
||||
return;
|
||||
|
||||
var userId = context.User.Claims.FirstOrDefault(c => c.Type == identityOptions.CurrentValue.ClaimsIdentity.UserIdClaimType)?.Value;
|
||||
if (string.IsNullOrEmpty(userId))
|
||||
return;
|
||||
|
||||
StoreData? store = null;
|
||||
var success = false;
|
||||
var isAdmin = context.User.IsInRole(Roles.ServerAdmin);
|
||||
var storeId = context.Resource as string;
|
||||
var policy = requirement.Policy;
|
||||
var requiredUnscoped = false;
|
||||
if (policy.EndsWith(':'))
|
||||
{
|
||||
policy = policy[..^1];
|
||||
requiredUnscoped = true;
|
||||
}
|
||||
|
||||
if (Policies.IsServerPolicy(policy) && isAdmin)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
else if (Policies.IsUserPolicy(policy) && userId is not null)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
else if (Policies.IsStorePolicy(policy))
|
||||
{
|
||||
if (isAdmin && storeId is not null)
|
||||
{
|
||||
success = _serverAdminRolePermissions.HasPermission(policy, storeId);
|
||||
}
|
||||
|
||||
/*if (!success && store?.HasPermission(userId, policy) is true)
|
||||
{
|
||||
success = true;
|
||||
}*/
|
||||
|
||||
if (!success && store is null && requiredUnscoped)
|
||||
{
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue