Clarify legacy access token permission (#7631)
What changed, and why it matters
This commit renames a permission that controls who can manage old-style BitPay-compatible access tokens. The old name, 'Manage access tokens,' sounded like it applied to modern API keys, but it only ever applied to legacy BitPay tokens. The new name, 'Manage legacy access tokens,' makes that clear. The change is mostly a labeling and code-organization cleanup; it does not appear to add or remove any actual security checks, but it may reduce confusion that could lead to users granting more access than intended.
Treat as a low-risk cleanup/refactoring change. Verify during review that no stale references to the old permission name remain and that the migration correctly handles existing Manager roles. No urgent security response is indicated, but confirm the change does not inadvertently alter role assignments in production deployments.
Security signals we found
Permission renamed from CanManageStoreCredentials to CanManageLegacyAccessTokens
Policy definition moved from core services into the Bitpay plugin
Authorization attributes and Razor permission checks updated consistently
Database migration updated to grant renamed permission to Manager role
Swagger documentation updated to list renamed permission
Tests updated to assert same access control behavior under new permission name
No new authorization checks or restrictions introduced
Evidence from the diff
The commit removes the global policy constant Policies.CanManageStoreCredentials (‘btcpay.store.canmanagestorecredentials’) and introduces a Bitpay plugin-specific policy BitpayPolicies.CanManageLegacyAccessTokens (‘btcpay.store.canmanagelegacyaccesstokens’). All [Authorize] attributes, Razor view permission checks, policy definitions, a database migration, and Swagger documentation are updated to use the new permission name. The migration now grants the renamed permission to the Manager role. The permission is still included by CanModifyStoreSettings, so effective access control behavior is unchanged. The test suite is updated to assert the same authorization rules under the new name.
Changed components
BTCPayServer.Client/Permissions.csBTCPayServer.Data/Migrations/20260928000000_AddLegacyAccessTokenManagementToManagerRole.csBTCPayServer/Hosting/BTCPayServerServices.csBTCPayServer/Plugins/Bitpay/BitpayPlugin.csBTCPayServer/Plugins/Bitpay/BitpayPolicies.csBTCPayServer/Plugins/Bitpay/Controllers/UIStoresTokenController.csBTCPayServer/Plugins/Bitpay/Views/ListTokens.cshtmlBTCPayServer/Plugins/Bitpay/Views/NavExtension.cshtmlBTCPayServer/Plugins/Bitpay/Views/RequestPairing.cshtmlBTCPayServer/Plugins/Bitpay/Views/_ViewImports.cshtmlBTCPayServer/wwwroot/swagger/v1/swagger.template.jsonBTCPayServer.Tests/BitpayTests.csInspect captured patch +47 / −41
### BTCPayServer.Client/Permissions.cs
@@ -14,7 +14,6 @@ public class Policies
public const string CanUseLightningNodeInStore = "btcpay.store.canuselightningnode";
public const string CanModifyServerSettings = "btcpay.server.canmodifyserversettings";
public const string CanModifyStoreSettings = "btcpay.store.canmodifystoresettings";
- public const string CanManageStoreCredentials = "btcpay.store.canmanagestorecredentials";
public const string CanModifyWebhooks = "btcpay.store.webhooks.canmodifywebhooks";
public const string CanSendStoreEmail = "btcpay.store.cansendstoreemails";
public const string CanModifyStoreSettingsUnscoped = "btcpay.store.canmodifystoresettings:";
### BTCPayServer.Data/Migrations/20260928000000_AddLegacyAccessTokenManagementToManagerRole.cs
@@ -8,18 +8,18 @@
namespace BTCPayServer.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
- [Migration("20260928000000_AddCredentialManagementToManagerRole")]
- public partial class AddCredentialManagementToManagerRole : Migration
+ [Migration("20260928000000_AddLegacyAccessTokenManagementToManagerRole")]
+ public partial class AddLegacyAccessTokenManagementToManagerRole : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("""
UPDATE "StoreRoles"
- SET "Permissions" = COALESCE("Permissions", ARRAY[]::TEXT[]) || ARRAY['btcpay.store.canmanagestorecredentials']::TEXT[]
+ SET "Permissions" = COALESCE("Permissions", ARRAY[]::TEXT[]) || ARRAY['btcpay.store.canmanagelegacyaccesstokens']::TEXT[]
WHERE "Id" = 'Manager'
AND "StoreDataId" IS NULL
- AND NOT (COALESCE("Permissions", ARRAY[]::TEXT[]) @> ARRAY['btcpay.store.canmanagestorecredentials']::TEXT[]);
+ AND NOT (COALESCE("Permissions", ARRAY[]::TEXT[]) @> ARRAY['btcpay.store.canmanagelegacyaccesstokens']::TEXT[]);
""");
}
}
### BTCPayServer.Tests/BitpayTests.cs
@@ -9,6 +9,7 @@
using BTCPayServer.Client;
using BTCPayServer.Client.Models;
using BTCPayServer.Events;
+using BTCPayServer.Plugins.Bitpay;
using BTCPayServer.Plugins.Bitpay.Controllers;
using BTCPayServer.Plugins.Bitpay.Models;
using BTCPayServer.Plugins.Bitpay.Security;
@@ -57,15 +58,15 @@ public async Task CanUseServerInitiatedPairingCode()
[Fact]
[Trait("Integration", "Integration")]
- public async Task AccessTokensRequireStoreCredentialPermission()
+ public async Task LegacyAccessTokensRequirePermission()
{
using var tester = CreateServerTester();
await tester.StartAsync();
var owner = tester.NewAccount();
await owner.GrantAccessAsync();
var storeRepository = tester.PayTester.GetService<StoreRepository>();
- var credentialsOnly = new StoreRoleId(owner.StoreId, "Credentials only");
- await storeRepository.AddOrUpdateStoreRole(credentialsOnly, [Policies.CanManageStoreCredentials]);
+ var legacyAccessTokensOnly = new StoreRoleId(owner.StoreId, "Legacy access tokens only");
+ await storeRepository.AddOrUpdateStoreRole(legacyAccessTokensOnly, [BitpayPolicies.CanManageLegacyAccessTokens]);
async Task<TestAccount> AddMember(StoreRoleId role)
{
@@ -76,21 +77,21 @@ async Task<TestAccount> AddMember(StoreRoleId role)
return member;
}
- async Task<bool> CanManageAccessTokens(TestAccount account)
+ async Task<bool> CanManageLegacyAccessTokens(TestAccount account)
{
var controller = account.GetController<UIStoresTokenController>();
var authorizationService = controller.HttpContext.RequestServices.GetRequiredService<IAuthorizationService>();
- return (await authorizationService.AuthorizeAsync(controller.User, owner.StoreId, Policies.CanManageStoreCredentials)).Succeeded;
+ return (await authorizationService.AuthorizeAsync(controller.User, owner.StoreId, BitpayPolicies.CanManageLegacyAccessTokens)).Succeeded;
}
- Assert.True(await CanManageAccessTokens(owner));
- Assert.True(await CanManageAccessTokens(await AddMember(StoreRoleId.Manager)));
- Assert.True(await CanManageAccessTokens(await AddMember(credentialsOnly)));
- Assert.False(await CanManageAccessTokens(await AddMember(StoreRoleId.Employee)));
+ Assert.True(await CanManageLegacyAccessTokens(owner));
+ Assert.True(await CanManageLegacyAccessTokens(await AddMember(StoreRoleId.Manager)));
+ Assert.True(await CanManageLegacyAccessTokens(await AddMember(legacyAccessTokensOnly)));
+ Assert.False(await CanManageLegacyAccessTokens(await AddMember(StoreRoleId.Employee)));
// Guests can view store settings, but not the store's access tokens.
var guest = await AddMember(StoreRoleId.Guest);
- Assert.False(await CanManageAccessTokens(guest));
+ Assert.False(await CanManageLegacyAccessTokens(guest));
var guestController = guest.GetController<UIStoresTokenController>();
Assert.IsType<RedirectToActionResult>(await guestController.CreateToken());
Assert.IsType<ChallengeResult>(await guestController.CreateToken2(new CreateTokenViewModel
### BTCPayServer/Hosting/BTCPayServerServices.cs
@@ -554,11 +554,6 @@ CREATE INDEX IF NOT EXISTS idx_invoices_expired_cleanup
Policies.CanSendStoreEmail,
new PermissionDisplay("Send store emails", "Allows sending emails on behalf of all your stores."),
new PermissionDisplay("Send selected stores' emails", "Allows sending emails on behalf of the selected stores.")),
- new PolicyDefinition(
- Policies.CanManageStoreCredentials,
- new PermissionDisplay("Manage access tokens", "Allows managing the access tokens of all your stores."),
- new PermissionDisplay("Manage selected stores' access tokens", "Allows managing the access tokens of the selected stores."),
- includedByPermissions: new[] { Policies.CanModifyStoreSettings }),
new PolicyDefinition(
Policies.CanModifyServerSettings,
new PermissionDisplay("Manage your server", "Grants total control on the server settings of your server."),
### BTCPayServer/Plugins/Bitpay/BitpayPlugin.cs
@@ -23,6 +23,12 @@ public class BitpayPlugin : BaseBTCPayServerPlugin
public override void Execute(IServiceCollection services)
{
+ services.AddPolicyDefinitions(
+ new PolicyDefinition(
+ BitpayPolicies.CanManageLegacyAccessTokens,
+ new PermissionDisplay("Manage legacy access tokens", "Allows managing the legacy access tokens of all your stores."),
+ new PermissionDisplay("Manage selected stores' legacy access tokens", "Allows managing the legacy access tokens of the selected stores."),
+ includedByPermissions: [Policies.CanModifyStoreSettings]));
services.AddSingleton<IHostedService, BitpayIPNSender>();
var userAgent = BTCPayServerEnvironment.GetUserAgentHeaderValue();
services.AddHttpClient(BitpayIPNSender.NamedClient)
@@ -41,7 +47,7 @@ public override void Execute(IServiceCollection services)
services.AddStaticSearch(new ActionResultItemViewModel()
{
- RequiredPolicy = Policies.CanManageStoreCredentials,
+ RequiredPolicy = BitpayPolicies.CanManageLegacyAccessTokens,
Title = "View the access tokens (for legacy API access)",
Action = nameof(UIStoresTokenController.ListTokens),
Controller = "UIStoresToken",
### BTCPayServer/Plugins/Bitpay/BitpayPolicies.cs
@@ -0,0 +1,6 @@
+namespace BTCPayServer.Plugins.Bitpay;
+
+public static class BitpayPolicies
+{
+ public const string CanManageLegacyAccessTokens = "btcpay.store.canmanagelegacyaccesstokens";
+}
### BTCPayServer/Plugins/Bitpay/Controllers/UIStoresTokenController.cs
@@ -4,7 +4,6 @@
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Models;
-using BTCPayServer.Client;
using BTCPayServer.Controllers;
using BTCPayServer.Data;
using BTCPayServer.Models;
@@ -24,7 +23,7 @@ namespace BTCPayServer.Plugins.Bitpay.Controllers;
[Route("stores")]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
-[Authorize(Policy = Policies.CanManageStoreCredentials, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
+[Authorize(Policy = BitpayPolicies.CanManageLegacyAccessTokens, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[Area(BitpayPlugin.Area)]
public class UIStoresTokenController(
TokenRepository tokenRepository,
@@ -44,7 +43,7 @@ public class UIStoresTokenController(
public bool StoreNotConfigured { get; set; }
public string? GeneratedPairingCode { get; set; }
[HttpGet("{storeId}/tokens")]
- [Authorize(Policy = Policies.CanManageStoreCredentials, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
+ [Authorize(Policy = BitpayPolicies.CanManageLegacyAccessTokens, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> ListTokens()
{
var model = new TokensViewModel();
@@ -60,7 +59,7 @@ public async Task<IActionResult> ListTokens()
}
[HttpGet("{storeId}/tokens/{tokenId}/revoke")]
- [Authorize(Policy = Policies.CanManageStoreCredentials, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
+ [Authorize(Policy = BitpayPolicies.CanManageLegacyAccessTokens, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> RevokeToken(string tokenId)
{
var token = await tokenRepository.GetToken(tokenId);
@@ -70,7 +69,7 @@ public async Task<IActionResult> RevokeToken(string tokenId)
}
[HttpPost("{storeId}/tokens/{tokenId}/revoke")]
- [Authorize(Policy = Policies.CanManageStoreCredentials, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
+ [Authorize(Policy = BitpayPolicies.CanManageLegacyAccessTokens, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> RevokeTokenConfirm(string tokenId)
{
var token = await tokenRepository.GetToken(tokenId);
@@ -84,7 +83,7 @@ public async Task<IActionResult> RevokeTokenConfirm(string tokenId)
}
[HttpGet("{storeId}/tokens/{tokenId}")]
- [Authorize(Policy = Policies.CanManageStoreCredentials, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
+ [Authorize(Policy = BitpayPolicies.CanManageLegacyAccessTokens, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> ShowToken(string tokenId)
{
var token = await tokenRepository.GetToken(tokenId);
@@ -94,7 +93,7 @@ public async Task<IActionResult> ShowToken(string tokenId)
}
[HttpGet("{storeId}/tokens/create")]
- [Authorize(Policy = Policies.CanManageStoreCredentials, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
+ [Authorize(Policy = BitpayPolicies.CanManageLegacyAccessTokens, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public IActionResult CreateToken(string storeId)
{
var model = new CreateTokenViewModel();
@@ -105,7 +104,7 @@ public IActionResult CreateToken(string storeId)
}
[HttpPost("{storeId}/tokens/create")]
- [Authorize(Policy = Policies.CanManageStoreCredentials, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
+ [Authorize(Policy = BitpayPolicies.CanManageLegacyAccessTokens, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> CreateToken(string storeId, CreateTokenViewModel model)
{
if (!ModelState.IsValid)
@@ -124,7 +123,7 @@ public async Task<IActionResult> CreateToken(string storeId, CreateTokenViewMode
if (store == null)
return Challenge(AuthenticationSchemes.Cookie);
- if (!(await authorizationService.AuthorizeAsync(User, store.Id, Policies.CanManageStoreCredentials)).Succeeded)
+ if (!(await authorizationService.AuthorizeAsync(User, store.Id, BitpayPolicies.CanManageLegacyAccessTokens)).Succeeded)
return Challenge(AuthenticationSchemes.Cookie);
var tokenRequest = new TokenRequest()
@@ -168,7 +167,7 @@ public async Task<IActionResult> CreateToken()
var model = new CreateTokenViewModel();
ViewBag.HidePublicKey = true;
ViewBag.ShowStores = true;
- var stores = (await storeRepository.GetStoresByUserId(userId)).Where(data => data.HasPolicy(userId, Policies.CanManageStoreCredentials, permissionService)).ToArray();
+ var stores = (await storeRepository.GetStoresByUserId(userId)).Where(data => data.HasPolicy(userId, BitpayPolicies.CanManageLegacyAccessTokens, permissionService)).ToArray();
model.Stores = new SelectList(stores, nameof(CurrentStore.Id), nameof(CurrentStore.StoreName));
if (!model.Stores.Any())
@@ -209,7 +208,7 @@ public async Task<IActionResult> RequestPairing(string pairingCode, string? sele
return RedirectToAction(nameof(UIHomeController.Index), "UIHome");
}
- var stores = (await storeRepository.GetStoresByUserId(userId)).Where(data => data.HasPolicy(userId, Policies.CanManageStoreCredentials, permissionService)).ToArray();
+ var stores = (await storeRepository.GetStoresByUserId(userId)).Where(data => data.HasPolicy(userId, BitpayPolicies.CanManageLegacyAccessTokens, permissionService)).ToArray();
return View(new PairingModel
{
Id = pairing.Id,
@@ -225,7 +224,7 @@ public async Task<IActionResult> RequestPairing(string pairingCode, string? sele
}
[HttpPost("/api-access-request")]
- [Authorize(Policy = Policies.CanManageStoreCredentials, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
+ [Authorize(Policy = BitpayPolicies.CanManageLegacyAccessTokens, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> Pair(string pairingCode, string storeId)
{
var store = CurrentStore;
### BTCPayServer/Plugins/Bitpay/Views/ListTokens.cshtml
@@ -35,7 +35,7 @@
<div class="col-xxl-constrain col-xl-8">
<div class="settings-section__heading d-flex align-items-center justify-content-between">
<h3 class="mb-0">@ViewData["Title"]</h3>
- <a id="CreateNewToken" asp-action="CreateToken" class="btn btn-primary" role="button" asp-route-storeId="@Context.GetRouteValue("storeId")" permission="@Policies.CanManageStoreCredentials" text-translate="true">
+ <a id="CreateNewToken" asp-action="CreateToken" class="btn btn-primary" role="button" asp-route-storeId="@Context.GetRouteValue("storeId")" permission="@BitpayPolicies.CanManageLegacyAccessTokens" text-translate="true">
Create Token
</a>
</div>
@@ -61,15 +61,15 @@
<thead>
<tr>
<th text-translate="true">Label</th>
- <th class="text-end" permission="@Policies.CanManageStoreCredentials" text-translate="true">Actions</th>
+ <th class="text-end" permission="@BitpayPolicies.CanManageLegacyAccessTokens" text-translate="true">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var token in Model.Tokens)
{
<tr>
<td>@token.Label</td>
- <td class="text-end" permission="@Policies.CanManageStoreCredentials">
+ <td class="text-end" permission="@BitpayPolicies.CanManageLegacyAccessTokens">
<a asp-action="ShowToken" asp-route-storeId="@Context.GetRouteValue("storeId")" asp-route-tokenId="@token.Id" text-translate="true">See information</a> -
<a asp-action="RevokeToken" asp-route-storeId="@Context.GetRouteValue("storeId")" asp-route-tokenId="@token.Id" data-bs-toggle="modal" data-bs-target="#ConfirmModal" data-description="The access token with the label <strong>@Html.Encode(token.Label)</strong> will be revoked." data-confirm-input="REVOKE" text-translate="true">Revoke</a>
</td>
@@ -89,4 +89,4 @@
</div>
</div>
-<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Revoke access token"], StringLocalizer["The access token will be revoked. Do you wish to continue?"], StringLocalizer["Revoke"]))" permission="@Policies.CanManageStoreCredentials" />
+<partial name="_Confirm" model="@(new ConfirmModel(StringLocalizer["Revoke access token"], StringLocalizer["The access token will be revoked. Do you wish to continue?"], StringLocalizer["Revoke"]))" permission="@BitpayPolicies.CanManageLegacyAccessTokens" />
### BTCPayServer/Plugins/Bitpay/Views/NavExtension.cshtml
@@ -1,5 +1,4 @@
-@using BTCPayServer.Client
@using BTCPayServer.Plugins.Bitpay
-<li class="nav-item nav-item-sub" permission="@Policies.CanManageStoreCredentials">
+<li class="nav-item nav-item-sub" permission="@BitpayPolicies.CanManageLegacyAccessTokens">
<a layout-menu-item="@nameof(StoreNavPages.Tokens)" asp-area="@BitpayPlugin.Area" asp-controller="UIStoresToken" asp-action="ListTokens" asp-route-storeId="@Model.Store.Id" text-translate="true">Access Tokens</a>
</li>
### BTCPayServer/Plugins/Bitpay/Views/RequestPairing.cshtml
@@ -19,7 +19,7 @@
</button>
}
}
-<form asp-action="Pair" method="post" permissioned="@Policies.CanManageStoreCredentials">
+<form asp-action="Pair" method="post" permissioned="@BitpayPolicies.CanManageLegacyAccessTokens">
<div class="sticky-header">
<vc:title-header />
<button id="page-primary" type="submit" class="btn btn-primary mt-3" title="@StringLocalizer["Approve this pairing demand"]" text-translate="true">Approve</button>
### BTCPayServer/Plugins/Bitpay/Views/_ViewImports.cshtml
@@ -1,4 +1,5 @@
@using BTCPayServer.Abstractions.Extensions
@using BTCPayServer.Views.Stores
+@using BTCPayServer.Plugins.Bitpay
@using BTCPayServer.Plugins.Bitpay.Views
@using BTCPayServer.Models.StoreViewModels
### BTCPayServer/wwwroot/swagger/v1/swagger.template.json
@@ -216,7 +216,7 @@
"securitySchemes": {
"API_Key": {
"type": "apiKey",
- "description": "BTCPay Server supports authenticating and authorizing users through an API Key that is generated by them. Send the API Key as a header value to Authorization with the format: `token {token}`. For a smoother experience, you can generate a url that redirects users to an API key creation screen.\n\n The following permissions are available to the context of the user creating the API Key:\n\n* `btcpay.impersonation.canimpersonate`: Can impersonate users\n* `btcpay.user.candeleteuser`: Delete user\n* `btcpay.user.canmanagenotificationsforuser`: Manage your notifications\n* `btcpay.user.canmodifyprofile`: Manage your profile\n* `btcpay.user.canviewnotificationsforuser`: View your notifications\n* `btcpay.user.canviewprofile`: View your profile\n* `unrestricted`: Unrestricted access\n\nThe following permissions are available if the user is an administrator:\n\n* `btcpay.server.cancreatelightninginvoiceinternalnode`: Create invoices with internal lightning node\n* `btcpay.server.cancreateuser`: Create new users\n* `btcpay.server.canmanageusers`: Manage users\n* `btcpay.server.canmodifyserversettings`: Manage your server\n* `btcpay.server.canuseinternallightningnode`: Use the internal lightning node\n* `btcpay.server.canviewlightninginvoiceinternalnode`: View invoices from internal lightning node\n* `btcpay.server.canviewusers`: View users\n\nThe following permissions applies to all stores of the user, you can limit to a specific store with the following format: `btcpay.store.cancreateinvoice:6HSHAEU4iYWtjxtyRs9KyPjM9GAQp8kw2T9VWbGG1FnZ`:\n\n* `btcpay.store.canarchivepullpayments`: Archive your pull payments\n* `btcpay.store.canbroadcasttransactions`: Broadcast wallet transactions\n* `btcpay.store.cancanceltransactions`: Cancel wallet transactions\n* `btcpay.store.cancreateinvoice`: Create an invoice\n* `btcpay.store.cancreatelightninginvoice`: Create invoices from the lightning nodes associated with your stores\n* `btcpay.store.cancreatenonapprovedpullpayments`: Create non-approved pull payments\n* `btcpay.store.cancreatepullpayments`: Create pull payments\n* `btcpay.store.cancreatetransactions`: Create wallet transactions\n* `btcpay.store.cancreditsubscribers`: Credit your subscribers\n* `btcpay.store.canmanagepayouts`: Manage payouts\n* `btcpay.store.canmanagepullpayments`: Manage your pull payments\n* `btcpay.store.canmanagestorecredentials`: Manage access tokens\n* `btcpay.store.canmanagesubscribers`: Manage your subscribers\n* `btcpay.store.canmanagewallets`: Manage wallets\n* `btcpay.store.canmanagewalletsettings`: Manage wallet settings\n* `btcpay.store.canmanagewallettransactions`: Manage wallet transactions\n* `btcpay.store.canmodifyinvoices`: Modify invoices\n* `btcpay.store.canmodifyofferings`: Modify your offerings\n* `btcpay.store.canmodifypaymentrequests`: Modify your payment requests\n* `btcpay.store.canmodifystoresettings`: Modify your stores\n* `btcpay.store.cansendstoreemails`: Send store emails\n* `btcpay.store.cansigntransactions`: Sign wallet transactions\n* `btcpay.store.canuselightningnode`: Use the lightning nodes associated with your stores\n* `btcpay.store.canviewinvoices`: View invoices\n* `btcpay.store.canviewlightninginvoice`: View the lightning invoices associated with your stores\n* `btcpay.store.canviewofferings`: View your offerings\n* `btcpay.store.canviewpaymentrequests`: View your payment requests\n* `btcpay.store.canviewpayouts`: View payouts\n* `btcpay.store.canviewpullpayments`: View your pull payments\n* `btcpay.store.canviewreports`: View your reports\n* `btcpay.store.canviewstoresettings`: View your stores\n* `btcpay.store.canviewwallet`: View wallets\n* `btcpay.store.webhooks.canmodifywebhooks`: Modify stores webhooks\n\nNote that API Keys only limits permission of a user and can never expand it. If an API Key has the permission `btcpay.server.canmodifyserversettings` but that the user account creating this API Key is not administrator, the API Key will not be able to modify the server settings.\nSome permissions may include other permissions, see [this operation](#operation/permissionsMetadata).\n",
+ "description": "BTCPay Server supports authenticating and authorizing users through an API Key that is generated by them. Send the API Key as a header value to Authorization with the format: `token {token}`. For a smoother experience, you can generate a url that redirects users to an API key creation screen.\n\n The following permissions are available to the context of the user creating the API Key:\n\n* `btcpay.impersonation.canimpersonate`: Can impersonate users\n* `btcpay.user.candeleteuser`: Delete user\n* `btcpay.user.canmanagenotificationsforuser`: Manage your notifications\n* `btcpay.user.canmodifyprofile`: Manage your profile\n* `btcpay.user.canviewnotificationsforuser`: View your notifications\n* `btcpay.user.canviewprofile`: View your profile\n* `unrestricted`: Unrestricted access\n\nThe following permissions are available if the user is an administrator:\n\n* `btcpay.server.cancreatelightninginvoiceinternalnode`: Create invoices with internal lightning node\n* `btcpay.server.cancreateuser`: Create new users\n* `btcpay.server.canmanageusers`: Manage users\n* `btcpay.server.canmodifyserversettings`: Manage your server\n* `btcpay.server.canuseinternallightningnode`: Use the internal lightning node\n* `btcpay.server.canviewlightninginvoiceinternalnode`: View invoices from internal lightning node\n* `btcpay.server.canviewusers`: View users\n\nThe following permissions applies to all stores of the user, you can limit to a specific store with the following format: `btcpay.store.cancreateinvoice:6HSHAEU4iYWtjxtyRs9KyPjM9GAQp8kw2T9VWbGG1FnZ`:\n\n* `btcpay.store.canarchivepullpayments`: Archive your pull payments\n* `btcpay.store.canbroadcasttransactions`: Broadcast wallet transactions\n* `btcpay.store.cancanceltransactions`: Cancel wallet transactions\n* `btcpay.store.cancreateinvoice`: Create an invoice\n* `btcpay.store.cancreatelightninginvoice`: Create invoices from the lightning nodes associated with your stores\n* `btcpay.store.cancreatenonapprovedpullpayments`: Create non-approved pull payments\n* `btcpay.store.cancreatepullpayments`: Create pull payments\n* `btcpay.store.cancreatetransactions`: Create wallet transactions\n* `btcpay.store.cancreditsubscribers`: Credit your subscribers\n* `btcpay.store.canmanagelegacyaccesstokens`: Manage legacy access tokens\n* `btcpay.store.canmanagepayouts`: Manage payouts\n* `btcpay.store.canmanagepullpayments`: Manage your pull payments\n* `btcpay.store.canmanagesubscribers`: Manage your subscribers\n* `btcpay.store.canmanagewallets`: Manage wallets\n* `btcpay.store.canmanagewalletsettings`: Manage wallet settings\n* `btcpay.store.canmanagewallettransactions`: Manage wallet transactions\n* `btcpay.store.canmodifyinvoices`: Modify invoices\n* `btcpay.store.canmodifyofferings`: Modify your offerings\n* `btcpay.store.canmodifypaymentrequests`: Modify your payment requests\n* `btcpay.store.canmodifystoresettings`: Modify your stores\n* `btcpay.store.cansendstoreemails`: Send store emails\n* `btcpay.store.cansigntransactions`: Sign wallet transactions\n* `btcpay.store.canuselightningnode`: Use the lightning nodes associated with your stores\n* `btcpay.store.canviewinvoices`: View invoices\n* `btcpay.store.canviewlightninginvoice`: View the lightning invoices associated with your stores\n* `btcpay.store.canviewofferings`: View your offerings\n* `btcpay.store.canviewpaymentrequests`: View your payment requests\n* `btcpay.store.canviewpayouts`: View payouts\n* `btcpay.store.canviewpullpayments`: View your pull payments\n* `btcpay.store.canviewreports`: View your reports\n* `btcpay.store.canviewstoresettings`: View your stores\n* `btcpay.store.canviewwallet`: View wallets\n* `btcpay.store.webhooks.canmodifywebhooks`: Modify stores webhooks\n\nNote that API Keys only limits permission of a user and can never expand it. If an API Key has the permission `btcpay.server.canmodifyserversettings` but that the user account creating this API Key is not administrator, the API Key will not be able to modify the server settings.\nSome permissions may include other permissions, see [this operation](#operation/permissionsMetadata).\n",
"name": "Authorization",
"in": "header"
},Why this scored 28/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.