Row-Level Security (RLS)
Definition
Row-Level Security restricts which ROWS of data a user can see, based on their identity - the same report and visuals are shared by everyone, but each viewer only sees data relevant to them (e.g. a regional manager sees only their region’s sales).
Creating a Role
Modeling > Manage Roles > Create
-- Role name: "RegionManager"
-- DAX Filter expression applied to the Sales table:
[Region] = "West"The DAX filter expression acts like an automatic, invisible
CALCULATEfilterWhatever expression you write is applied as a row filter on that table for any user assigned to the role - functionally equivalent to every query implicitly wrapped in
CALCULATE(..., [Region] = "West").
Static vs Dynamic RLS
graph TD A[RLS Approach] --> B["Static one role per fixed value, manually assign users to each role"] A --> C["Dynamic ONE role, filter driven by the logged-in user's identity"]
Static RLS (Simple, More Maintenance)
-- Role: "WestRegion"
Sales[Region] = "West"
-- Role: "EastRegion"
Sales[Region] = "East"Then manually assign specific users to each role in the Power BI Service.
Dynamic RLS (Scales Better)
-- A single role, e.g. "UserSecurity," using a mapping table
-- UserRegionMapping table: columns [Email], [Region]
Sales[Region] IN
CALCULATETABLE(
VALUES(UserRegionMapping[Region]),
UserRegionMapping[Email] = USERPRINCIPALNAME()
)USERPRINCIPALNAME() -- returns the currently logged-in user's email/UPN (in the Power BI Service)
USERNAME() -- returns domain\username format (mainly relevant on-prem)Dynamic RLS scales to hundreds of users without manual role assignment
With a mapping table (
Email -> Region) driving the filter, adding a new user’s access is just adding a row to that table - no need to create new roles or manually reassign users in the Service every time the team changes.
Testing Roles in Desktop
Modeling > View As > select a role (or "Other user" to test USERPRINCIPALNAME() with a specific email)
Always test every role before publishing
View Assimulates exactly what a user assigned to that role would see, directly in Desktop - critical for catching mistakes (like an overly broad or overly narrow filter expression) before real users are affected.
Assigning Users to Roles (Power BI Service)
Workspace > dataset > "..." > Security > select a role > add user emails or security groups
Assign security GROUPS, not individual users, wherever possible
Managing access via an Azure AD security group (rather than adding/removing individual emails inside Power BI) means IT/access changes happen in one central place and automatically flow through to report access - far less maintenance than manual per-user assignment.
RLS and Relationships - Filter Propagation
graph LR A["RLS filter applied to Region table"] -->|flows through single-direction relationship| B["Sales table automatically filtered too"]
RLS only propagates along relationships in the FILTERING direction
If a role filters the
Regiondimension table but the relationship toSalesis single-direction (Region -> Sales), the filter correctly flows through. If relationships are misconfigured or filtering the wrong table, RLS can silently fail to restrict data as intended - always verify withView As, not just by inspecting the DAX expression.
RLS Limitations
Things RLS does NOT protect against
- Users with Build permission on the underlying dataset can create their OWN new reports against it, and RLS still applies correctly there - but users with direct access to the underlying data source (bypassing Power BI entirely) aren’t restricted by RLS at all, since it’s enforced at the Power BI query layer, not the source database.
- RLS restricts ROWS, not columns - use Object-Level Security (OLS), configured via external tools like Tabular Editor, if specific columns/measures also need hiding per role.
- RLS doesn’t apply to Power BI Desktop’s Data View for someone with edit access to the .pbix file itself - it’s enforced for VIEWERS of a published report, not for report authors/editors.
Object-Level Security (OLS) - Brief Note
Hiding entire tables/columns/measures per role
Not configurable directly in Power BI Desktop’s standard UI - requires an external tool like Tabular Editor (free, widely used) to set OLS permissions on top of an existing RLS role, for cases where certain roles shouldn’t even see that a sensitive column/measure exists.