Expose DAB set-session-context (native SQL RLS) and/or custom roles in Rayfin
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 610
- Forks
- 62
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 3
Description
Problem statement
We run a production Fabric App (AppBackend + SQL database, Rayfin 1.34) — an
operational-metrics data-entry system for a group of ~15 organizations.
Authorization requirement: an authenticated user must only read/write rows
belonging to organizations they were granted, where grants live in a mapping
table (UserOrgAccesses: user_email × organization_id).
Problem. DAB item policies cannot express joins — the policy syntax is
limited to @claims/@item comparisons, so "row is visible if a matching
(claims.email × item.organization_id) pair exists in the mapping table" is not
expressible. Our current workaround is item.user_email eq claims.email (own
rows only), which blocks legitimate same-organization reads: a collector cannot
see values entered by a colleague for the same org. We have since relaxed
read/update to all authenticated users so teams can work together, which
means the organization boundary is now enforced only in the UI. (Update
2026-09-15: we verified on the live Fabric backend that DAB does enforce
policy.database on create — an insert with a foreign user_email is
rejected with "Could not insert row with given values", and both text-literal
and quoted-GUID predicates filter read/update correctly. So authorship is
protected; what remains inexpressible is the organization membership check,
because it needs a join.)
Proposed solution
Expose DAB's data-source.options.set-session-context.
Data API Builder for MSSQL supports set-session-context: true — it calls
sp_set_session_context with the token claims before each query. That lets us
define a native SQL SECURITY POLICY whose predicate function joins our mapping
table (UserOrgAccesses), so the organization-membership check becomes
expressible in the database itself and is enforced for every query path,
including direct GraphQL. A BLOCK ... AFTER INSERT predicate would additionally
harden create.
Rayfin generates the DAB config internally and does not surface this option in
rayfin.yml (no mention in the 1.34 guide; rayfin/.temp is regenerated on
deploy). Two things would fully cover our requirement:
- A passthrough for
set-session-context: true(or an equivalent Rayfin knob). - A documented, supported way to ship SQL migrations (CREATE FUNCTION /
CREATE SECURITY POLICY) that survive redeploys.
Reference: https://learn.microsoft.com/azure/data-api-builder/concept/security/row-level-security
Alternatives considered
Custom roles (alternative or complement). DAB supports custom roles (roles
claim + X-MS-API-ROLE header with per-role permissions/policies), but Rayfin
restricts to the two built-ins (anonymous, authenticated). Custom roles would
let us model admin/collector without hardcoding admin emails as literals inside
policies (today an admin-list change requires a schema redeploy).
Reference: https://learn.microsoft.com/azure/data-api-builder/concept/security/authorization-overview
Workarounds we rely on today, and why each falls short:
item.user_email eq claims.email(own-rows-only): blocks legitimate
same-organization reads — a collector cannot see a colleague's values for the
same org.- Relax read/update to all authenticated users, enforce the org boundary in the
UI: leaves the boundary unenforced at the API layer — any authenticated caller
can read another org's rows via direct GraphQL. - Bake the full access map (user_email × organization_id) into policy predicates
as literals and regenerate on every access change: expressible today, but
couples every grant/revoke to a redeploy — it does not scale operationally.
None of these enforce "visible only if a matching grant exists in the mapping
table" at the database layer, because that check needs a join.
Additional context
Environment: tenant 2139481e-7233-4d97-b411-e65812d14856, workspace
12ea5e43-5aae-462c-aa40-8b6c6525a987, AppBackend
dfa02918-0e91-4c8c-baea-9eae837dcc01, Rayfin CLI/SDK 1.34.
Happy to share the schema and try preview bits.
Related but separable: staticHosting offers no way to set HTTP response
headers, so we ship CSP via a <meta http-equiv> tag. The meta form cannot
express frame-ancestors, leaving no way to restrict who may embed the app in
an iframe — while the app is designed to run inside the Fabric iframe. A way to
declare response headers (at minimum Content-Security-Policy with
frame-ancestors, ideally Strict-Transport-Security, X-Content-Type-Options)
for staticHosting would close this. Can file as a separate issue if preferred.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The payload identifies rayfin.yml and regenerated rayfin/.temp as the configuration boundary; start by tracing how Rayfin generates DAB configuration and compare it with DAB's set-session-context and custom-role documentation. Done means a supported configuration path and durable SQL migration mechanism are defined and documented, with the separate staticHosting headers concern split into its own issue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- sql
- Domain
- authorization, backend-api-design, databases, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100