btcpayserver/BTCPayServer/Security/GreenField/APIKeyExtensions.cs
d11n 2e458af4fb
App: Authentication updates (#6536)
- Updates API key extraction to also accept "Bearer" auth header. This is necessary for non-cookie based SignalR connections.
- Adds authentication related models to the client lib
- Succeeds and replaces #6484.
2025-01-16 14:34:57 +09:00

68 lines
2.8 KiB
C#

using System;
using System.Linq;
using System.Text.RegularExpressions;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Client;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Primitives;
namespace BTCPayServer.Security.Greenfield
{
public static class APIKeyExtensions
{
public static bool GetAPIKey(this HttpContext httpContext, out StringValues apiKey)
{
apiKey = default;
if (httpContext.Request.Headers.TryGetValue("Authorization", out var value))
{
var match = Regex.Match(value.ToString(), @"^(token|bearer)\s+(\S+)", RegexOptions.IgnoreCase);
if (!match.Success) return false;
apiKey = match.Groups[2].Value;
return true;
}
return false;
}
public static AuthenticationBuilder AddAPIKeyAuthentication(this AuthenticationBuilder builder)
{
builder.AddScheme<GreenfieldAuthenticationOptions, APIKeysAuthenticationHandler>(AuthenticationSchemes.GreenfieldAPIKeys,
o => { });
builder.AddScheme<GreenfieldAuthenticationOptions, BasicAuthenticationHandler>(AuthenticationSchemes.GreenfieldBasic,
o => { });
return builder;
}
public static IServiceCollection AddAPIKeyAuthentication(this IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<APIKeyRepository>();
serviceCollection.AddScoped<IAuthorizationHandler, GreenfieldAuthorizationHandler>();
serviceCollection.AddScoped<IAuthorizationHandler, LocalGreenfieldAuthorizationHandler>();
return serviceCollection;
}
public static string[] GetPermissions(this AuthorizationHandlerContext context)
{
return context.User.Claims.Where(c =>
c.Type.Equals(GreenfieldConstants.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(GreenfieldConstants.ClaimTypes.Permission, StringComparison.InvariantCultureIgnoreCase)))
{
if (Permission.TryParse(claim.Value, out var claimPermission))
{
if (claimPermission.Contains(permission))
{
return true;
}
}
}
return false;
}
}
}