| name | abp-authorization |
| description | ABP Framework v10.x (10.4/10.5) authorization: defining permissions (PermissionDefinitionProvider), [Authorize], CheckPolicyAsync/IsGrantedAsync, CurrentUser, IPermissionManager, resource-based auth, multi-tenancy permissions. Use when you need permission, role or access checks in ABP. |
ABP Authorization Skill
Trigger
User asks about permissions, authorization, roles, policies, permission groups, resource-based authorization, or access control in ABP Framework.
Core Concepts
ABP extends ASP.NET Core Authorization with a Permission System that auto-registers permissions as policies. Two permission types exist:
- Standard (Global) Permissions — Apply globally (e.g., "can create documents")
- Resource-Based Permissions — Target specific instances (e.g., "can edit Document #123")
Permission System
Defining Permissions
Create a class inheriting PermissionDefinitionProvider:
using Volo.Abp.Authorization.Permissions;
namespace Acme.BookStore.Permissions
{
public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var myGroup = context.AddGroup(
"BookStore",
LocalizableString.Create<BookStoreResource>("BookStore")
);
myGroup.AddPermission(
"BookStore_Author_Create",
LocalizableString.Create<BookStoreResource>("Permission:BookStore_Author_Create")
);
}
}
}
- ABP auto-discovers this class — no registration needed
- Typically placed in
Application.Contracts project
- Permission name becomes usable as an ASP.NET Core policy name
Permission Groups
context.AddGroup("GroupName") creates a new group
- Groups appear as tabs in the UI permission dialog
- Use
LocalizableString.Create<TResource>("Key") for localized display names
Permission Options
myGroup.AddPermission(
"BookStore_Books_Manage",
LocalizableString.Create<BookStoreResource>("Permission:ManageBooks"),
multiTenancySide: MultiTenancySides.Tenant
);
Multi-tenancy side options:
MultiTenancySides.Host — Available only on host side
MultiTenancySides.Tenant — Available only on tenant side
MultiTenancySides.Both (default) — Available on both
Child Permissions
Permissions can have parent-child relationships for hierarchical UI display:
var booksPermission = myGroup.AddPermission("BookStore_Books_Manage");
booksPermission.AddChild("BookStore_Books_Create");
booksPermission.AddChild("BookStore_Books_Edit");
booksPermission.AddChild("BookStore_Books_Delete");
Enable/Disable Permissions
myGroup.AddPermission("BookStore_Feature", isEnabled: false);
Permission Depending on a Condition
myGroup.AddPermission("BookStore_Advanced")
.WithFeatureDependency("AdvancedFeature");
myGroup.AddPermission("BookStore_Preview")
.WithGlobalFeatureDependency("PreviewModule");
myGroup.AddPermission("BookStore_Special")
.WithStateChecker(() => MyStaticChecker.IsSpecialEnabled);
Overriding Permissions with Custom Policies
myGroup.AddPermission("BookStore_Special")
.WithPolicyDependency(new MyCustomPolicyRequirement());
Changing Permission Definitions of Dependent Modules
[DependsOn(typeof(AbpIdentityModule))]
public class MyModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<PermissionDefinitionContext>(options =>
{
});
}
}
Using Permissions
In Controllers / Page Models
[Authorize("BookStore_Author_Create")]
public async Task<IActionResult> CreateAsync(CreateAuthorDto input)
{
}
In Application Services
public class AuthorAppService : ApplicationService, IAuthorAppService
{
public async Task<AuthorDto> CreateAsync(CreateAuthorDto input)
{
await AuthorizationService.CheckAsync("BookStore_Author_Create");
if (!await AuthorizationService.IsGrantedAsync("BookStore_Author_Create"))
{
throw new AbpAuthorizationException("...");
}
}
}
Using IAuthorizationService
public class MyService : ITransientDependency
{
private readonly IAuthorizationService _authorizationService;
public MyService(IAuthorizationService authorizationService)
{
_authorizationService = authorizationService;
}
public async Task DoWorkAsync()
{
await _authorizationService.CheckAsync("BookStore_Author_Create");
}
}
Shortcut methods in base classes: await CheckPolicyAsync("...") (throws an exception if not granted) and await IsGrantedAsync("...") (returns a bool, does not throw).
Current User
Authenticated user information is accessed via the CurrentUser property — it is available out of the box in base classes (ApplicationService, DomainService, AbpController) and requires no injection:
public class BookAppService : ApplicationService
{
public async Task DoSomethingAsync()
{
var userId = CurrentUser.Id;
var userName = CurrentUser.UserName;
var email = CurrentUser.Email;
var isAuth = CurrentUser.IsAuthenticated;
var roles = CurrentUser.Roles;
var tenantId = CurrentUser.TenantId;
}
}
public class MyService : ITransientDependency
{
private readonly ICurrentUser _currentUser;
public MyService(ICurrentUser currentUser) => _currentUser = currentUser;
}
Ownership Verification
public async Task UpdateMyBookAsync(Guid bookId, UpdateBookDto input)
{
var book = await _bookRepository.GetAsync(bookId);
if (book.CreatorId != CurrentUser.Id)
{
throw new AbpAuthorizationException();
}
}
Security: never trust client input for the user identity — always use CurrentUser and verify ownership inside the application service.
Resource-Based Authorization
For fine-grained, per-instance permissions:
var booksGroup = context.AddGroup("BookStore_Books");
var bookPermission = booksGroup.AddResourcePermission(
"BookStore_Books_Edit",
typeof(Book),
LocalizableString.Create<BookStoreResource>("Permission:EditBook")
);
Resource-based permissions are managed through the Resource Permission Management Dialog on individual resource instances (not the global permissions dialog).
See: Resource-Based Authorization
Multi-Tenancy Integration
- Permissions can be scoped to Host, Tenant, or Both
- When setting permissions for users/roles, use
ISettingManager or the Identity module UI
- Tenant-specific permissions are stored per-tenant in the database
UI Integration
- Permissions dialog available with Identity module pre-installed
- Permission groups shown as tabs
- Standard permissions shown in global dialog
- Resource-based permissions managed per-resource instance
Best Practices
- Naming convention:
ModuleName_Entity_Action (e.g., BookStore_Books_Create)
- Always localize permission display names using
LocalizableString.Create<TResource>()
- Group logically — one group per module or feature area
- Use child permissions for hierarchical UI (Manage > Create/Edit/Delete)
- Set multi-tenancy side explicitly if your app is multi-tenant
- Use resource-based permissions for instance-level access control
- Check permissions early in application service methods to fail fast
Common Patterns
CRUD Permissions
var books = myGroup.AddPermission("BookStore_Books_Manage");
books.AddChild("BookStore_Books_Create");
books.AddChild("BookStore_Books_Edit");
books.AddChild("BookStore_Books_Delete");
books.AddChild("BookStore_Books_ViewList");
Permission Check in App Service Base Class
public abstract class BookStoreAppService : ApplicationService
{
protected BookStoreAppService()
{
LocalizationResource = typeof(BookStoreResource);
}
protected virtual async Task CheckPolicyAsync(string policyName)
{
await AuthorizationService.CheckAsync(policyName);
}
}
What's New in v10.5
Single-Active Identity Token Providers (v10.5+)
ABP replaces ASP.NET Core Identity's default DataProtectorTokenProvider with AbpDefaultTokenProvider, and LinkUserTokenProvider uses the same single-active infrastructure. Tokens are now single-active per user/purpose: generating a new token invalidates the previous one. Default lifetime is 10 minutes:
Configure<AbpDefaultTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromMinutes(10);
});
Configure<AbpLinkUserTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromMinutes(10);
});
After upgrading to 10.5, re-test login, two-factor, forced/periodic password change, and link-user flows. If a flow sends multiple tokens for the same purpose and expects older ones to stay valid, switch it to use only the latest token.
OpenIddict Default Scope Fallback (v10.5+, opt-in)
For client_credentials, password, and token-exchange grants, ABP can fall back to the client application's registered scopes when the request omits the scope parameter. Disabled by default:
Configure<AbpOpenIddictAspNetCoreOptions>(options =>
{
options.UseDefaultScopesForClientCredentials = true;
options.UseDefaultScopesForPassword = true;
options.UseDefaultScopesForTokenExchange = true;
});
After enabling, re-test token issuance for the affected grant types and confirm the resulting scopes/resources match authorization expectations.
Related Modules
- Identity Module — User and role management, permission UI
- Permission Management Module — Resource permission management dialog
- Setting Management Module — Feature-based permission toggling
Related