M365Con 2027 – free online conference · 11–22 Jan 2027 · 120 sessions→ m365con.net

2025-08-06

Implement Power BI Row-Level Security in Microsoft Fabric

Implement Power BI Row-Level Security in Microsoft Fabric
This episode shows why Row-Level Security (RLS) in Power BI isn’t a checkbox—it’s a living system. We unpack the parts that actually decide who sees what: model relationships, role design, DAX filters (static vs dynamic), Azure AD group assignments, and the identity shifts that happen when you…

Don’t just lock data—design a security system that adapts as your org changes.

What you’ll learn

  • Why RLS is a system (roles + relationships + DAX + identities), not a one-time setup

  • Static vs dynamic RLS—and when each is the right tool

  • Safe DAX patterns for user-aware filters (and the traps to avoid)

  • Mapping users and groups without creating shadow access

  • Why RLS can change after publish (Desktop vs Fabric identity differences)

  • How to test, audit, and govern RLS at scale


Core concepts (the mental model)

  • Model-first security: Relationships and filter directions determine how RLS propagates.

  • Role design: Fewer, purpose-built roles beat sprawling, overlapping ones.

  • Dynamic context: Security must respond to who is viewing and what they’re related to.

  • Cloud reality: Identity resolution and tenant settings in Fabric can change behavior.


Designing filters that hold up (DAX patterns)

Static RLS (simple, fixed audiences)

  • Example (on DimRegion):
    DimRegion[Region] = "US"

Dynamic RLS via bridge table (recommended)

  • Tables: Users (UPN, UserKey), UserRegion (UserKey, RegionKey), DimRegion (RegionKey, Region)

  • Role filter on Users:
    Users[UPN] = USERPRINCIPALNAME()

  • Optionally restrict DimRegion using a relationship from Users → UserRegion → DimRegion.

Avoid

  • Calculated-column–based security (evaluated at refresh, not per user)

  • USERNAME() in Fabric (use USERPRINCIPALNAME(); test email formats)

  • Hardcoding emails/domains in filters

Helpful dynamic patterns

  • Multi-tenant: map TenantId from Users to fact/dimension tables

  • Hierarchies: store manager-subordinate links, materialize an access table, filter by all descendants for the viewer


Role & relationship design

  • Use single-direction filters where possible; avoid ambiguous many-to-many paths.

  • Create security dimensions (e.g., User→Access tables) rather than embedding logic in facts.

  • Prefer few reusable roles (e.g., Employee, Manager, Admin) + dynamic filters, over dozens of static roles.


Assignments without surprises (users & groups)

  • Map roles to Azure AD groups, not individuals (scales better).

  • Guard against stale membership: set quarterly access reviews with group owners.

  • Watch for overlap: users in multiple groups can unintentionally widen access—document intended precedence.

  • For external users, validate B2B guest scenarios and domain matching in your Users table.


Desktop vs Fabric: what changes after publish

  • Identity: USERPRINCIPALNAME() returns email in Fabric; Desktop previews can differ.

  • Ownership: dataset owner and refresh credentials can alter what’s visible.

  • Tenant & workspace settings (e.g., external sharing, discovery) can affect RLS outcomes.

  • Group sync latency: changes in Azure AD may lag—plan for it.


Testing that actually catches leaks

  • In Desktop: use “View as” for quick checks (sanity, not sign-off).

  • In Fabric:

    • Test with real groups and real users in a non-prod workspace.

    • Validate each role on core report pages and sensitive visuals.

    • Script spot checks: export small result sets for known users (via XMLA/Automation).

  • Drift detection: schedule a job to compare Users/groups vs HR/identity data and flag mismatches.


Governance & operations

  • Catalog: Document roles, their DAX filters, tables affected, and intended audiences.

  • Change control: PRs for model changes; require RLS test evidence before merge.

  • Data contracts: Define which dimensions/facts must participate in RLS and how.

  • Audits: Quarterly group membership recertification; semiannual RLS penetration tests in Fabric.

  • Monitoring: Track high-risk reports, owner changes, and role edits; alert on anomalies.


Common failure patterns (and fixes)

  • Works in Desktop, leaks in Fabric → Using USERNAME() / mismatched identity format

    • Fix: Standardize on USERPRINCIPALNAME() and align Users[UPN].

  • User sees too much → Many-to-many path bypassing security

    • Fix: Introduce a security dimension and tighten relationships/bi-directional filters.

  • Former team access persists → Stale AAD group memberships

    • Fix: Automate recertification and removal; log exceptions.

  • Calculated column used for identity → No per-user effect

    • Fix: Move logic to role filter DAX over model tables, not calculated columns.


Quick-start checklist (this week)

  • Add a Users table keyed by USERPRINCIPALNAME(); relate to access tables.

  • Convert hardcoded filters to dynamic, table-driven filters where appropriate.

  • Replace any USERNAME() logic with USERPRINCIPALNAME() and retest in Fabric.

  • Map roles to AAD groups; schedule an access review with group owners.

  • Publish to a test workspace; validate with real users; fix identity/relationship gaps.

  • Document roles, DAX, and tables; add to your model README.


Suggested SEO assets

  • URL slug: power-bi-row-level-security-architecture

  • Meta title: Power BI Row-Level Security: Architecture, DAX Patterns, and Cloud-Ready Governance

  • Meta description: Go beyond the RLS checkbox. Learn dynamic DAX patterns, role design, Azure AD mapping, and Fabric-specific testing to keep sensitive data truly secure.

  • Keywords: Power BI, Row-Level Security, RLS, USERPRINCIPALNAME, Azure AD groups, Fabric, dynamic RLS, data governance

Apple Podcasts · Spotify · YouTube

Host: Mirko Peters

Related articles

← Supply Chain Visibility with Fabric and Dynamics 365 SCMSet Up Power Platform ALM with GitHub Actions →