How to Embed Secure, Personalized Power BI Reports in Microsoft Teams Tabs—Maintaining Row-Level Security for Each User

Embedding Power BI reports in Microsoft Teams tabs only preserves RLS if you use the native Power BI tab and configure dataset-level security correctly.

MP

A Power BI report embedded in a Microsoft Teams tab will not automatically enforce Row-Level Security (RLS) for each user unless you configure the integration with an understanding of both Teams’ authentication flow and the Power BI Service’s identity propagation. If you rely on quick-share or publish-to-web links, you risk bypassing RLS entirely. This article walks through the friction points, the mechanics of secure embedding, and the edge cases that break RLS—so you can embed truly personalized, secure analytics, not just a static report.

RLS Enforcement Relies on Viewer Identity—And Teams Doesn’t Always Pass It

Most Power BI developers assume that adding a report to a Teams tab means RLS “just works” as it does in the Power BI Service. This is only true if the Teams integration uses AAD-backed identity and the user is licensed appropriately. The moment you shortcut via a static embed code, or rely on a link pasted into a Teams website tab, you sever the identity chain. Here’s how the flows differ:

  • Teams Power BI tab (native): Uses the user’s AAD identity (via Teams SSO) to access the report, enforcing RLS as in the Power BI Service.
  • Website tab with report URL: Lacks authentication context; user may be prompted to sign in, or the report may not load at all. RLS may not apply, or the report may show as the credentials of whoever generated the link.
  • Publish to web / public embed: Disables RLS entirely, as the report is rendered anonymously. Never use this for confidential data.

The non-obvious trap: Teams tabs can host native Power BI content or just a web page. Only the Power BI app for Teams or the “Add a Power BI tab” flow propagates user identity correctly. If you see a prompt for credentials, RLS is likely broken. If the report loads without sign-in, check if it’s public—RLS is not enforced for anonymous access.

Licensing, Workspace, and Dataset Configuration: Where RLS Actually Applies

Even with the right Teams integration, RLS can silently fail if your workspace, dataset, or user licenses aren’t aligned. Here’s where most developers get stung:

  • The workspace must be in a Power BI Service workspace, not “My Workspace”. RLS roles are ignored in personal workspaces.
  • Users need a Power BI Pro license (or the workspace needs to be in a Premium/Fabric capacity). Without this, even if the Teams tab renders, RLS evaluation may not happen—or users may be blocked from access entirely.
  • RLS must be configured on the dataset, not just at the report level. Adding roles in the report UI does nothing for embedded/Teams scenarios. Roles must be defined and assigned in the dataset security settings.

The real cost of getting this wrong: you may think your report is secure, but users see all data, or none. This is silent until a user points it out—or data leaks. When debugging, always check: which dataset is the report using? Is the user listed in the correct RLS role? Is the workspace Premium-backed if using Free users?

Worked Example: Where Naive Embedding Fails—And the Fix

Take a model with a Fact_Sales table (~5M rows), Dim_Region, and RLS configured so users only see sales for their assigned region. The RLS role filters Dim_Region based on USERPRINCIPALNAME():

// In the dataset's RLS configuration
[Email] = USERPRINCIPALNAME()

You share the report in Teams using a Website tab and paste the report URL. Two users, Alice (should see only Region A) and Bob (Region B), both open the Teams tab. Both see all regions. Why?

  1. The Website tab loads the report as you (or as anonymous, depending on session state), not as the current Teams user. RLS evaluates based on whoever is authenticated at load time.
  2. If you were signed in and have access to all regions, that’s what everyone sees. If the session is stale, users may get a sign-in prompt or error.

The fix: Use the native Power BI Teams tab:

  1. In Teams, click “+” to add a tab.
  2. Select Power BI (not Website).
  3. Navigate to the report in the workspace (must not be “My Workspace”).
  4. Add the report. The Teams Power BI app uses AAD SSO, so USERPRINCIPALNAME() resolves per viewer, and RLS works as expected.

To confirm: have Alice and Bob open the tab in their own Teams clients. Each should see only their region. If either can see all data, check that:

  • The report is in a shared workspace.
  • The dataset RLS role is assigned to their account or group.
  • They access via the Power BI tab, not a pasted link or Website tab.

Edge Cases That Break RLS in Teams Embedding

  • Publish to web disables RLS by design. Any report embedded this way is public; do not use this for anything requiring security.
  • Exported data ignores RLS if exported by a user with higher privileges. If a Teams tab is added by an admin with broader access, and users export underlying data, exported content is filtered to the viewer’s RLS, but beware of cached or shared data extracts.
  • Service principal and embed tokens: If you use the Power BI JavaScript SDK to embed reports in a Teams app (not the native tab), you must implement token acquisition and user impersonation. If you embed using a master user or service principal without passing the viewer’s identity, RLS is not enforced per-user.
  • DirectQuery with RLS: RLS predicates are pushed to the source in DirectQuery mode, and the user identity in Teams is still AAD-backed—as long as the integration is correct. However, row-level filters on large DirectQuery sources can incur substantial query overhead; monitor for predicate pushdown failures or excessive source scans.

Modeling and DAX Patterns for RLS in Embedded Scenarios

Not all RLS patterns are equally robust in embedded/Teams scenarios. Here’s what trips up even experienced developers:

  • USERPRINCIPALNAME() is safe in Teams, USERNAME() is not. USERNAME() returns different formats on different clients; always use USERPRINCIPALNAME() for dynamic RLS in the Service and Teams.
  • Group-based RLS works if you assign AAD groups, not individual emails. Assigning roles to groups (not just individual users) scales better and reduces maintenance friction.
  • Beware filter context leaks via DAX measures. If you use USERELATIONSHIP or certain ALL* functions inside measures, test that the filter context set by RLS is not overwritten. Naive use of ALL(Dim_Region) can defeat RLS by removing the filter imposed by the role.

Consider this DAX measure:

[Total Sales All Regions] =
CALCULATE(
    [Total Sales],
    ALL(Dim_Region) // This removes region filter, including RLS filter
)

This measure will defeat RLS by removing the region filter, even for users in a restricted RLS role. To maintain RLS, use REMOVEFILTERS or KEEPFILTERS carefully, or avoid ALL on RLS-filtered tables. For example:

[Total Sales RLS-Respecting] =
SUM(Fact_Sales[SalesAmount])
// No ALL or REMOVEFILTERS -- respects current filters, including RLS

Checklist: Embedding Power BI Reports in Teams While Maintaining RLS

  • Place reports in a shared workspace (not “My Workspace”).
  • Define and assign RLS roles at the dataset level, using USERPRINCIPALNAME() or group-based assignments.
  • Embed reports using the native Power BI Teams tab, not a Website tab or publish-to-web link.
  • Verify users have appropriate licenses (Pro or Premium/Fabric-backed workspace for Free users).
  • Test with real user accounts; do not assume your view matches theirs.
  • Review DAX measures for ALL/REMOVEFILTERS usage that may bypass RLS filters.
  • For custom Teams apps using Power BI embedding, ensure token acquisition and identity propagation match the viewing user.

Securing Power BI reports in Teams is less about ticking a box and more about understanding the integration points where identity and context can leak or break. The safest path is to use the native Power BI Teams tab, model RLS at the dataset, and avoid ALL functions that could override role filters. Anything else requires explicit, tested configuration—assume default behavior is insecure until proven otherwise.

MP
Max Power
Published June 1, 2026  ·  Updated June 1, 2026