[{"data":1,"prerenderedAt":372},["ShallowReactive",2],{"navigation":3,"\u002Fblog\u002Fpower-bi-row-level-security":50,"\u002Fblog\u002Fpower-bi-row-level-security-surround":368},[4],{"title":5,"path":6,"stem":7,"children":8,"page":49},"Blog","\u002Fblog","blog",[9,13,17,21,25,29,33,37,41,45],{"title":10,"path":11,"stem":12},"Data Catalog 3.0: Rise of the Active Metadata Platform","\u002Fblog\u002Fdata-catalog-3","blog\u002Fdata-catalog-3",{"title":14,"path":15,"stem":16},"dbt on Databricks: Data Transformation Pipelines","\u002Fblog\u002Fdbt-on-databricks","blog\u002Fdbt-on-databricks",{"title":18,"path":19,"stem":20},"Deploying Azure Resources with VS Code","\u002Fblog\u002Fdeploying-azure-resource-with-vs-code","blog\u002Fdeploying-azure-resource-with-vs-code",{"title":22,"path":23,"stem":24},"Dynamic Management Views (DMVs)","\u002Fblog\u002Fdynamic-management-views","blog\u002Fdynamic-management-views",{"title":26,"path":27,"stem":28},"General Delta Table Processing","\u002Fblog\u002Fgeneral-delta-table","blog\u002Fgeneral-delta-table",{"title":30,"path":31,"stem":32},"Microsoft Fabric as an All-in-One Analytics Solution","\u002Fblog\u002Fmicrosoft-fabric","blog\u002Fmicrosoft-fabric",{"title":34,"path":35,"stem":36},"Orchard Core Shapes: Demystifying the View Data Model","\u002Fblog\u002Forchard-core-shapes","blog\u002Forchard-core-shapes",{"title":38,"path":39,"stem":40},"Power BI DAX Masterclass","\u002Fblog\u002Fpower-bi-dax-masterclass","blog\u002Fpower-bi-dax-masterclass",{"title":42,"path":43,"stem":44},"Power BI Incremental Refresh","\u002Fblog\u002Fpower-bi-incremental-refresh","blog\u002Fpower-bi-incremental-refresh",{"title":46,"path":47,"stem":48},"Set Power BI Row-Level Security to SAP Cost Center","\u002Fblog\u002Fpower-bi-row-level-security","blog\u002Fpower-bi-row-level-security",false,{"id":51,"title":46,"author":52,"body":56,"date":361,"description":362,"extension":363,"image":364,"meta":365,"minRead":262,"navigation":234,"path":47,"seo":366,"stem":48,"__hash__":367},"blog\u002Fblog\u002Fpower-bi-row-level-security.md",{"name":53,"avatar":54},"Radek Řezáč",{"src":55,"alt":53},"\u002Faboutme.png",{"type":57,"value":58,"toc":349},"minimark",[59,72,77,80,83,87,113,117,122,125,130,147,150,154,165,170,187,191,202,209,213,219,308,311,317,321,345],[60,61,62,63,67,68,71],"p",{},"In organisations where data is shared across departments, restricting access to only relevant information is critical. Power BI provides two complementary security mechanisms: ",[64,65,66],"strong",{},"Row-Level Security (RLS)"," and ",[64,69,70],{},"Object-Level Security (OLS)",". This article focuses on dynamic RLS driven by SAP authorization data.",[73,74,76],"h2",{"id":75},"row-level-security","Row-Level Security",[60,78,79],{},"RLS restricts access to rows in a table based on the identity of the user viewing the report. Rather than maintaining separate reports for different user groups, RLS applies filters at the data model level — each user sees only what they are permitted to see.",[60,81,82],{},"RLS operates within the Power BI data model and ensures that restricted data cannot be accessed even indirectly through slicers or drill-downs.",[73,84,86],{"id":85},"setting-up-role-level-security","Setting Up Role-Level Security",[88,89,90,97,107],"ol",{},[91,92,93,96],"li",{},[64,94,95],{},"Create Roles"," — use DAX to define roles with filters. For example, a \"Territory Manager\" role that filters to only their region.",[91,98,99,102,103,106],{},[64,100,101],{},"Test"," — use the ",[64,104,105],{},"View As"," feature in Power BI Desktop to verify that filters work correctly for each role.",[91,108,109,112],{},[64,110,111],{},"Deploy"," — publish the report to Power BI Service and assign users to roles.",[73,114,116],{"id":115},"static-vs-dynamic-rls","Static vs. Dynamic RLS",[118,119,121],"h3",{"id":120},"static-rls","Static RLS",[60,123,124],{},"Roles with hardcoded DAX filters. Each role corresponds to a fixed group or segment.",[60,126,127],{},[64,128,129],{},"Example:",[131,132,137],"pre",{"className":133,"code":134,"language":135,"meta":136,"style":136},"language-dax shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","[Region] = \"East\"\n","dax","",[138,139,140],"code",{"__ignoreMap":136},[141,142,145],"span",{"class":143,"line":144},"line",1,[141,146,134],{},[60,148,149],{},"Assign specific users to the \"Region_East\" role in Power BI Service.",[118,151,153],{"id":152},"dynamic-rls","Dynamic RLS",[60,155,156,157,160,161,164],{},"Uses ",[138,158,159],{},"USERNAME()"," or ",[138,162,163],{},"USERPRINCIPALNAME()"," combined with a mapping table to dynamically filter data based on the logged-in user identity.",[60,166,167],{},[64,168,169],{},"Steps:",[88,171,172,175,181],{},[91,173,174],{},"Create a mapping table with columns: user email, access regions, display name",[91,176,177,178],{},"Write a DAX filter: ",[138,179,180],{},"[Region] = RELATED(UserRegion[Region])",[91,182,183,184],{},"Filter by logged-in user: ",[138,185,186],{},"UserRegion[Email] = USERPRINCIPALNAME()",[73,188,190],{"id":189},"example-rls-based-on-sap-cost-center-assignments","Example: RLS Based on SAP Cost Center Assignments",[60,192,193,194,197,198,201],{},"In organisations using SAP, business roles contain cost center assignments per user. The authorization table derived from SAP contains the ",[64,195,196],{},"user's email address"," paired with each ",[64,199,200],{},"assigned cost center"," (one row per cost center per user).",[60,203,204],{},[205,206],"img",{"alt":207,"src":208},"Authorization table structure","https:\u002F\u002Fradekrezac.dotnest.net\u002Fmedia\u002FDM\u002Frls-authorization.jpg",[118,210,212],{"id":211},"dax-filter-for-dynamic-cost-center-rls","DAX Filter for Dynamic Cost Center RLS",[60,214,215,216,218],{},"The following measure uses ",[138,217,163],{}," as the logged-in user and checks whether the current cost center is in the set of cost centers assigned to that user:",[131,220,222],{"className":133,"code":221,"language":135,"meta":136,"style":136},"VAR Logged_User = LOWER(USERPRINCIPALNAME())\n\nRETURN\n    CALCULATE(\n        COUNTROWS('Cost Center'),\n        'Cost Center'[Cost Center Key]\n            IN CALCULATETABLE(\n                VALUES(Authorization[Cost Center]),\n                FILTER(\n                    ALL(Authorization),\n                    [User Email] = Logged_User\n                )\n            )\n    ) > 0\n",[138,223,224,229,236,242,248,254,260,266,272,278,284,290,296,302],{"__ignoreMap":136},[141,225,226],{"class":143,"line":144},[141,227,228],{},"VAR Logged_User = LOWER(USERPRINCIPALNAME())\n",[141,230,232],{"class":143,"line":231},2,[141,233,235],{"emptyLinePlaceholder":234},true,"\n",[141,237,239],{"class":143,"line":238},3,[141,240,241],{},"RETURN\n",[141,243,245],{"class":143,"line":244},4,[141,246,247],{},"    CALCULATE(\n",[141,249,251],{"class":143,"line":250},5,[141,252,253],{},"        COUNTROWS('Cost Center'),\n",[141,255,257],{"class":143,"line":256},6,[141,258,259],{},"        'Cost Center'[Cost Center Key]\n",[141,261,263],{"class":143,"line":262},7,[141,264,265],{},"            IN CALCULATETABLE(\n",[141,267,269],{"class":143,"line":268},8,[141,270,271],{},"                VALUES(Authorization[Cost Center]),\n",[141,273,275],{"class":143,"line":274},9,[141,276,277],{},"                FILTER(\n",[141,279,281],{"class":143,"line":280},10,[141,282,283],{},"                    ALL(Authorization),\n",[141,285,287],{"class":143,"line":286},11,[141,288,289],{},"                    [User Email] = Logged_User\n",[141,291,293],{"class":143,"line":292},12,[141,294,295],{},"                )\n",[141,297,299],{"class":143,"line":298},13,[141,300,301],{},"            )\n",[141,303,305],{"class":143,"line":304},14,[141,306,307],{},"    ) > 0\n",[60,309,310],{},"Apply this as the table filter expression for the Cost Center role. The logged-in user then sees only data linked to their assigned cost centers.",[60,312,313],{},[205,314],{"alt":315,"src":316},"Cost Center filtered view","https:\u002F\u002Fradekrezac.dotnest.net\u002Fmedia\u002FDM\u002Frls-costcenter.jpg",[73,318,320],{"id":319},"key-points","Key Points",[322,323,324,331,339,342],"ul",{},[91,325,326,330],{},[64,327,328],{},[138,329,163],{}," returns the email\u002FUPN of the currently authenticated user in Power BI Service",[91,332,333,338],{},[64,334,335],{},[138,336,337],{},"LOWER()"," normalises casing to avoid mismatches between SAP and Azure AD email formats",[91,340,341],{},"The authorization table acts as the single source of truth — updating SAP role assignments automatically propagates to Power BI access without touching the report",[91,343,344],{},"Users cannot see data outside their cost center assignments, even by manipulating slicers or visual filters",[346,347,348],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":136,"searchDepth":231,"depth":231,"links":350},[351,352,353,357,360],{"id":75,"depth":231,"text":76},{"id":85,"depth":231,"text":86},{"id":115,"depth":231,"text":116,"children":354},[355,356],{"id":120,"depth":238,"text":121},{"id":152,"depth":238,"text":153},{"id":189,"depth":231,"text":190,"children":358},[359],{"id":211,"depth":238,"text":212},{"id":319,"depth":231,"text":320},"2025-10-07","How to implement dynamic Row-Level Security (RLS) in Power BI using SAP authorization tables — restricting data access by cost center based on the logged-in user.","md","\u002Fblog\u002Fpbi-rls.png",{},{"title":46,"description":362},"eBEjjfyBMPK8J22l2Xnuzpc6lIcObW131hIN-VT_6-8",[369,371],{"title":42,"path":43,"stem":44,"description":370,"children":-1},"How incremental refresh works in Power BI — partitioning, change detection, step-by-step setup, and the license and data source limitations you need to know.",null,1782253168115]