How-to Guide

Stravis Group Limited
Getting permissions right in Business Central is one of the most important, and most frequently underestimated, parts of any implementation. Done well, it means the right people have access to exactly what they need, nothing more. Done poorly, it creates security gaps, audit findings, and operational friction that compounds over time. This guide covers the full permissions architecture: how BC permissions are structured internally, how they connect to Microsoft Entra ID (formerly Azure Active Directory), and how the underlying access levels work.
Business Central permission system has four layers that work together:
Understanding how these layers interact is key to building a permissions structure that is maintainable and auditable rather than a patchwork of individual user assignments.
A Permission Set in BC is a named collection of permissions across BC objects - tables, pages, reports, codeunits, and more. Each permission set defines exactly what a user assigned to it can see and do.
BC ships with a large library of system permission sets covering standard functional areas: posting journals, managing customers, running reports, and so on. You can also create custom permission sets for organisation-specific needs.
BC allows permission sets to include other permission sets, creating a parent/child structure that keeps things manageable at scale.
In a Permission Set, you can add other permission sets, effectively linking them as children. When a user is assigned the parent permission set (directly or via a security group), they automatically inherit all permissions from every child permission set nested within it. This means you do not have to build one huge permission set with everything listed table by table, or assign ten different permission sets to one user. You layer them.
This approach means you can reuse child permission sets across multiple parent roles that share some of the same requirements, and auditing is straightforward - one parent set per role, clearly named.

Security Groups in BC (available from BC 2023 onwards) are the mechanism for assigning permission sets to groups of users rather than individuals. Each security group has one or more permission sets assigned to it, and users added to the group inherit those permissions automatically.
The critical best practice: assign only the parent permission set to the security group. Everything flows down from there via the parent/child structure. This keeps the security group assignment clean and makes it immediately obvious what a group role is.
The most powerful aspect of BC modern permission architecture is the integration with Microsoft Entra ID (formerly Azure AD). Instead of managing group membership inside BC, you can assign a security group in Entra ID and the BC user will be reflected with those permissions automatically.
When a user has permissions assigned from multiple sources, BC combines them using an additive model with one important exception.
Permissions are generally additive. If Permission Set A gives Read access to the Customer table, and Permission Set B gives Modify access to the same table, the user effectively has both Read and Modify. The most permissive level from any source wins, for each object individually.
The built-in SUPER permission set grants unrestricted access to everything in BC. Any user with SUPER effectively bypasses all other permission logic. SUPER should be limited to a small number of system administrators and should never be assigned as a shortcut to resolve a permission issue.
BC now supports Permission Set Exclusions. You can explicitly exclude a permission set from a user or group, overriding additive permissions. This is useful for edge cases but should be used sparingly as it adds complexity to the audit trail. This is done by adding a specific line to a permission set with Type = Exclude. Note: at this point the exclude functionality does not work with Security Filters.
The most granular level of permissions in BC is TableData access. For any given table, you can set independent access levels for each operation:
These levels are set independently, so you can grant Read + Insert without Modify or Delete - useful for data entry roles that should not be able to change historical records.

Each tabledata permission also has a Direct/Indirect distinction:
Indirect access is important for transactional tables where users should not be browsing raw records but do need the underlying table data to be read or written as part of a workflow. Most posting routines write to ledger tables, and users need Indirect Insert on those tables to post, even though they should never be editing ledger entries directly.
The practical rule: give Direct access only to tables the user will interact with through a page or report. Give Indirect access to backend tables accessed only through processes and codeunits.
Security Filters are an advanced permission feature that adds row-level security, restricting which records within a table a user can see, not just whether they can access the table at all.
A security filter is a filter expression applied to a tabledata line in a permission set. For example:
Security filters are powerful but add significant complexity to troubleshooting. If a user cannot see a record they expect to, a security filter is often the culprit and can be hard to trace. Use them deliberately and document them carefully.