Yorrick Zijlstra · Maart 2026 · 7 min leestijd
Row-Level Security (RLS) is de oplossing voor een veelvoorkomend probleem: je hebt meerdere gebruikers die elk een ander deel van je data mogen zien. Denk aan regio-managers die alleen hun regio's zien, klantportalen waar elke klant slechts zijn eigen data kan inzien, of multi-tenant dashboards. In dit artikel laten we zien hoe je RLS stap voor stap implementeert, wat de beperkingen zijn, en hoe je fouten voorkomt.
Row-Level Security is een beveiligingsmechanisme in Power BI dat bepaalt welke rijen een gebruiker in een tabel kan zien. Je definieert rollen met DAX-filterformules, en die rollen koppel je aan gebruikers. Wanneer iemand een rapport opent, ziet hij alleen de rijen die door zijn rol(len) zijn toegestaan.
Voorbeeld: als je een verkooptabel hebt met een kolom "Regio", kun je een rol "Regio Noord" maken met het filter [Regio] = "Noord". Elke gebruiker in die rol ziet dan alleen verkopen uit Noord.
RLS is essentieel voor:
Zonder RLS zou je meerdere modellen nodig hebben, of je zou alle data openbaar moeten maken. RLS maakt centralisatie mogelijk.
Open Power BI Desktop en ga naar het tabblad Modeling (of Model). Daar vind je de knop Manage roles.
Laten we een praktische rol maken:
[Regio] = "Noord"
Dit is een DAX-filterexpressie. Deze rol zorgt dat alleen rijen zichtbaar zijn waar de kolom Regio gelijk is aan "Noord". Je kunt meerdere condities combineren met AND/OR:
[Regio] = "Noord" AND [Jaar] >= 2025
Statische rollen werken, maar voor grotere organisaties is dynamische RLS veel beter. Daarvoor gebruik je de functie USERPRINCIPALNAME(), die automatisch het e-mailadres of de gebruiker-ID van de ingelogde gebruiker ophaalt.
Je hebt een beveiligingstabel nodig met gebruikers en hun toegestane data:
tbl_RLS = {
("john@bedrijf.nl", "Noord"),
("anna@bedrijf.nl", "Zuid"),
("marc@bedrijf.nl", "Oost")
}
Nu maak je één rol met een dynamische filter:
[Regio] IN
CALCULATE(
VALUES(tbl_RLS[Regio]),
tbl_RLS[Email] = USERPRINCIPALNAME()
)
Deze formule zegt: "Filter de verkooptabel zodat alleen de regios zichtbaar zijn die in de tbl_RLS tabel voor deze gebruiker zijn gedefinieerd." Veel schaalbaarder dan statische rollen!
In Power BI Desktop kun je je RLS testen voordat je het publiceert. Ga naar het tabblad Modeling en klik op View as Role. Selecteer de rol en open een rapport. Je ziet nu alleen de gefilterde data voor die rol.
Dit is cruciaal: test altijd beide zijden. Test statische rollen met verschillende data, test dynamische RLS door verschillende gebruikers na te bootsen.
Na publicatie gaat het echt gebeuren in Power BI Service. Ga naar je dataset en open Security.
Hier voeg je gebruikers toe aan rollen:
Power BI zal de gebruiker dan op basis van USERPRINCIPALNAME() automatisch aan de juiste dataset koppelen.
| Statische RLS | Dynamische RLS | |
|---|---|---|
| DAX-filter | [Regio] = "Noord" | USERPRINCIPALNAME() + lookup tabel |
| Aantal rollen | Veel (per unieke waarde) | Weinig (meestal één) |
| Toevoegen gebruiker | Handmatig aan rol in Service | Update RLS-tabel, gebruiker automatisch gefilterd |
| Schaalbaar voor 100+ gebruikers | Nee (veel onderhoud) | Ja (tabel-driven) |
| Performance | Snel, simpel | Snel, maar wat meer DAX-evaluatie |
In de praktijk is de beveiligingslogica zelden zo simpel als "deze gebruiker mag regio Noord zien". Denk aan een organisatie waar een teamleider zijn eigen team ziet, een afdelingsmanager alle teams binnen zijn afdeling, en een directeur de hele organisatie. Dit los je op met een parent-child hierarchie en de DAX PATH()-functies.
Stel je hebt een tabel dim_Organisatie met een klassieke parent-child structuur:
| MedewerkerID | Naam | ManagerID | Rol | |
|---|---|---|---|---|
| 1 | Lisa de Vries | lisa@bedrijf.nl | Directeur | |
| 2 | Mark Jansen | mark@bedrijf.nl | 1 | Manager Sales |
| 3 | Sophie Bakker | sophie@bedrijf.nl | 1 | Manager Operations |
| 4 | Tom van Dijk | tom@bedrijf.nl | 2 | Teamlead Noord |
| 5 | Eva Smit | eva@bedrijf.nl | 2 | Teamlead Zuid |
| 6 | Jan Peters | jan@bedrijf.nl | 4 | Verkoper |
| 7 | Fleur de Groot | fleur@bedrijf.nl | 5 | Verkoper |
Lisa is directeur en moet alles kunnen zien. Mark is manager Sales en ziet Tom, Eva en hun teams. Tom ziet alleen zijn eigen verkopen en die van Jan. Elke laag in de hierarchie erft de data van de lagen eronder.
Voeg twee berekende kolommen toe aan dim_Organisatie:
// Berekende kolom: HierarchiePad
HierarchiePad =
PATH(dim_Organisatie[MedewerkerID], dim_Organisatie[ManagerID])
Dit geeft per rij het volledige pad van de top naar de medewerker. Bijvoorbeeld:
| Naam | HierarchiePad |
|---|---|
| Lisa de Vries | 1 |
| Mark Jansen | 1|2 |
| Tom van Dijk | 1|2|4 |
| Jan Peters | 1|2|4|6 |
| Fleur de Groot | 1|2|5|7 |
Het pad van Jan (6) is 1|2|4|6 - hij valt onder Tom (4), die onder Mark (2) valt, die onder Lisa (1) valt.
Nu komt het slimme deel. In de RLS-rol maak je een filter op dim_Organisatie:
// RLS-filter op dim_Organisatie
VAR HuidigeMedewerkerID =
LOOKUPVALUE(
dim_Organisatie[MedewerkerID],
dim_Organisatie[Email], USERPRINCIPALNAME()
)
RETURN
PATHCONTAINS(dim_Organisatie[HierarchiePad], HuidigeMedewerkerID)
Wat doet dit precies?
Als Mark (ID 2) inlogt, geeft PATHCONTAINS TRUE voor alle rijen waar 2 in het pad voorkomt: Mark zelf, Tom, Eva, Jan en Fleur. Maar niet Sophie (Operations), want haar pad is 1|3.
Belangrijk: Zorg dat je verkooptabel (of andere feitentabel) een relatie heeft naar dim_Organisatie, bijvoorbeeld via een MedewerkerID-kolom. Het RLS-filter op dim_Organisatie propageert dan automatisch naar de feitentabel via die relatie.
Wat als een gebruiker meerdere rollen heeft? Bijvoorbeeld een regiomanager die ook tijdelijk een ander team beheert? Breid de beveiligingstabel dan uit met meerdere rijen per gebruiker:
// RLS-filter met meerdere posities per gebruiker
VAR MedewerkerIDs =
CALCULATETABLE(
VALUES(tbl_RLS_Mapping[MedewerkerID]),
tbl_RLS_Mapping[Email] = USERPRINCIPALNAME()
)
RETURN
COUNTROWS(
FILTER(
MedewerkerIDs,
PATHCONTAINS(
dim_Organisatie[HierarchiePad],
[MedewerkerID]
)
)
) > 0
Met deze opzet kun je iemand in meerdere takken van de hierarchie plaatsen zonder de organisatietabel aan te passen.
Bij organisaties met duizenden medewerkers kan PATHCONTAINS per rij kostbaar worden. Een alternatief: maak een bridge-tabel aan in Power Query die voor elke manager alle onderliggende MedewerkerIDs uitklapt naar aparte rijen. Je RLS-filter wordt dan een simpele lookup in plaats van een pad-berekening per rij.
// Bridge-tabel aanpak (eenvoudiger RLS-filter)
[Email] = USERPRINCIPALNAME()
De bridge-tabel bevat dan een rij voor elke combinatie van manager en medewerker die onder hem valt. Dit is performanter maar vereist meer voorbereiding in Power Query.
Als je directQuery gebruikt (live verbinding met SQL Server, Azure SQL, etc.), werkt RLS anders:
Zorg dat je dit goed plant voordat je DirectQuery en RLS combineert.
1. RLS-rollen toewijzen vergeten
Je publiceert je model met RLS, maar vergeet gebruikers toe te wijzen in Power BI Service. Iemand kan dan het hele model zien. Test dit!
2. Bidirectionele relaties
Als je bidirectionele relaties hebt in je model en je gebruikt CALCULATE() in je RLS-formule, kan dit onverwachte resultaten geven. RLS werkt beter met unidirectionele relaties.
3. CALCULATE() en ALL()
ALL() op een dimensietabel die een RLS-filter heeft, kan dat filter verwijderen en onverwachte resultaten geven. Gebruik je ALL() op de feitentabel zelf, dan verwijdert het de filtercontext maar het RLS-filter op tabelniveau blijft intact. Het risico zit vooral bij dimensietabellen:
// Risico: ALL() op een dimensie met RLS-filter
CALCULATE(
SUM(Verkopen[Bedrag]),
ALL(dim_Organisatie) // Verwijdert het RLS-filter op deze dimensie
)
Vermijd ALL() op tabellen die direct een RLS-filter hebben. Gebruik in plaats daarvan ALLSELECTED() of filter op specifieke kolommen met REMOVEFILTERS().
4. Onvoldoende testen
Test RLS goed in Desktop (View as Role) en in Service. Zorg dat je test met echte gebruikers en verschillende rollen.
YorrData helpt bij het ontwerpen en implementeren van veilige RLS-architecturen op maat voor je organisatie.
Neem contact op →Formatteer je DAX met de DAX Formatter, zoek functies in de Cheat Sheet, of kopieer patronen uit de Measure Patronen bibliotheek.