Applied AI Governance — Authorization by Resource Type
01 / 15

Navigation

→ / SpaceNext slide
←Previous slide
HomeFirst slide
EndLast slide
SwipeTouch navigation
Click anywhere or press Esc to close

Authorization by Resource Type

What access control looks like at each Databricks AI resource — the identity model, OAuth scopes, the gotcha for each, and the pattern that works.

Companion to token fundamentals. That covers how you get the token; this covers what each resource enforces once it arrives.

Agenda

Seven resources. Seven different authorization models.

1. OAuth scopes — what they control, the endpoint vs scope confusion, M2M vs OBO tokens

2. Serving endpoints, Genie Agents, Vector Search — identity model for each

3. UC Functions and HTTP Connections — safe boundaries for writes and external systems

4. Tables — row filters, column masks, current_user() vs is_member()

5. Lakebase — PostgreSQL-native grants and RLS, not Unity Catalog

6. Decision guide and production-readiness checklist

The problem

Authorization is enforced at the resource, not by the app.

The same token can be valid for Model Serving but rejected by Genie Agents. Vector Search sees one user, Lakebase sees another. Row filters in UC work one way in notebooks and a different way in Agent Bricks. Getting the token right is table stakes, but it's only the first check.
7
resources to understand
3
different OAuth endpoints

What this means for builders

Before you trust the result, know: which endpoint issued the token, which resource is enforcing it, and what identity it sees.

What — The resource lens

Seven resources. Six use Unity Catalog. One doesn't.

⚙
Serving Endpoints
OBO or M2M
💬
Genie Agents
OBO only
🔍
Vector Search
M2M + filter
𝑓
UC Functions
Inherits caller
🔗
HTTP Connections
M2M + auth method
🗃
Tables
Row/column filters
🐘
Lakebase
PostgreSQL, not UC
ResourcePathcurrent_user()#1 gotcha
Serving EndpointsOBO or M2MHuman (OBO) / SP (M2M)ModelServingUserCredentials() only in serving context
Genie AgentsOBOHuman emailBoth genie + dashboards.genie scopes required
Vector SearchM2MApp SP UUIDNo native OBO — apply pre/post-filter in app layer
UC FunctionsInherits callerCaller identityGrant EXECUTE, never INSERT/UPDATE on table directly
HTTP ConnectionsM2M + authDatabricks side onlyOnly U2M Per User / Managed OAuth pass identity to external service
TablesAnyCaller identityis_member() breaks in Genie Agents + Agent Bricks OBO
LakebaseM2MSP client ID (PG role)PG GRANT + RLS, not UC policy
What — Serving Endpoints & Agent Bricks

OBO extracts the user, but only inside the serving endpoint itself.

Identity model

  • OBO: Pass user's OAuth token in Authorization: Bearer {token} header
  • Inside endpoint: ModelServingUserCredentials() extracts user identity
  • Scope: model-serving
  • M2M: App SP credentials auto-injected by platform

The ModelServingUserCredentials trap

ModelServingUserCredentials() only works in Model Serving context. In Databricks Apps, it silently falls back to SP credentials — wrong identity, no error.

Fix: In apps, read X-Forwarded-Access-Token and pass explicitly to the endpoint.

What — Genie Agents

OBO only. Both scopes required. is_member() breaks silently.

Identity model

  • OBO only — user's token via Authorization: Bearer {user_token}
  • Both genie AND dashboards.genie scopes required (UI doesn't show both)
  • current_user() = caller human email
  • is_member() = Genie Agents execution service (not the caller)

The scope trap

App integration UI lists only dashboards.genie. Genie Agents API checks for both. Missing genie scope = 403 with cryptic error.

Fix: Add both scopes via account API or CLI, not the UI.

What — Vector Search

M2M only. Same results for all users. Filtering is application-layer.

Identity model

  • M2M only — App SP has CAN_SELECT on the index
  • WorkspaceClient() auto-discovers SP credentials
  • Scope: vector-search
  • current_user() = App SP UUID (not per-user)

No native per-user identity. Vector Search returns the same top-K to all users. Per-user access is your responsibility.

Filtering options

Pre-filterInclude user/group metadata in index, filter in query. Fast but requires data enrichment.
Post-filterApp retrieves results, checks each against user ACL. Flexible, uses retrieval budget.
Shared KBM2M as-is: everyone sees same docs, no filtering needed.
What — UC Functions

The authorization boundary for writes: EXECUTE on the function, not the table.

CREATE FUNCTION prod.auth.approve(
  deal_id STRING
)
RETURNS STRING LANGUAGE SQL
RETURN (
  UPDATE prod.sales.deals
  SET status = 'approved'
  WHERE id = deal_id
    AND current_user() IN (
      SELECT email FROM
      prod.sales.approvers
    )
);

Pattern

Agent SPHas EXECUTE on function only
Agent SPNO UPDATE/INSERT on table
FunctionChecks current_user() internally
Audit logFunction calls appear in system.access.audit

Function is the authorization boundary. Agent never has direct write access.

What — UC HTTP Connections

Five auth methods. Only two pass per-user identity to the external service.

MethodExternal seesUse case
Bearer TokenShared static tokenSimple integrations, static API keys
OAuth M2MShared app credentialsService-to-service at org level
OAuth U2M SharedOne admin's delegated tokenShared admin access
U2M Per UserUser's own identity ✓As the user (Jira, GitHub, etc.)
Managed OAuthUser's own identity ✓Google, Microsoft Graph — Databricks handles OAuth flow

Kill switch. REVOKE USE CONNECTION immediately blocks agent access — no redeploy needed.

No granular scopes. UC controls WHO can use connection. For different operations (read vs write), create separate connections with different credentials.

What — Tables

Row filters and column masks work everywhere, but is_member() has a gotcha in OBO.

Row filters & column masks

  • SQL function evaluated at query time, attached to the table
  • Fires in all access paths: notebooks, apps, Genie Agents, agents, API
  • Column masks transform values per user — same trigger rules as row filters

current_user() vs is_member()

Access pathcurrent_user()is_member()
NotebookHuman ✓Human groups ✓
App SQL (OBO)Human ✓Human groups ✓
Genie Agents (OBO)Human ✓Genie Agents service ✗
Agent Bricks (OBO)Human ✓Agent service ✗

Rule: Use current_user() everywhere. It works in all paths. is_member() breaks silently in Genie Agents and Agent Bricks OBO — no error, just wrong rows.

What — Lakebase

PostgreSQL-native authorization. Not governed by Unity Catalog.

Lakebase identity model

  • Scope: postgres (for management API only)
  • Auth: Databricks OAuth token as PG password OR native PG role
  • App's SP client ID = PG role name (auto-created on binding)
  • Access: GRANT on schema/table + PostgreSQL RLS policies
NOT Unity Catalog

Two access paths, different auth

Direct PG connection: PG roles + GRANT + RLS enforce access.

Via lakehouse API: Unity Catalog policies apply.

Same table. Different authorization model per access path.

Why it matters

Authorization failures return wrong data, not errors.

Security

A row filter using is_member() in Genie Agents leaks data silently — no error, just wrong rows to the wrong user.

Compliance

Lakebase data behind both UC and PG policies. Auditors need to know which layer enforced which control. You need to know too.

Scaling

UC Function as authorization boundary means every new agent gets the same safety boundary without re-derivation.

Authorization lives at the resource. The right token path is only the first check. Know which resource enforces which control.

How — Decision guide

Three questions that determine the authorization pattern.

Question 1

Which resource?

Serving Endpoints, Genie Agents, Vector Search, Functions, HTTP Connections, Tables — UC + scopes.

Lakebase — PG GRANT + RLS, not UC.

Question 2

Per-user identity needed externally?

Yes — U2M Per User or Managed OAuth connection.

No — Bearer token or M2M OAuth.

Question 3

Agent needs to write?

Yes — UC Function with EXECUTE grant (boundary for writes).

No — Row filters and column masks on the table.

How — Production-readiness checklist

Verify these before shipping.

ResourceChecklist item
Serving EndpointsUse ModelServingUserCredentials() inside Model Serving only. From apps, read X-Forwarded-Access-Token header explicitly.
Genie AgentsBoth genie + dashboards.genie scopes present (add via CLI, not UI). Row filters use current_user(), not is_member().
Vector SearchPre-filter or post-filter implemented in application — M2M SP retrieval returns same results to all users by default.
UC FunctionsAgent SP has EXECUTE only. No INSERT/UPDATE/DELETE direct on table. Grant is on the function.
HTTP ConnectionsConnection owner = app SP. GRANT USE CONNECTION re-run after each redeploy (new SP = new grants needed).
TablesRow filter audit: grep for is_member(), especially if table queried via Genie Agents. Use current_user() instead.
Databricks AppsApps declare least-privilege user API scopes (e.g. sql, files, genie, ai-gateway) for OBO user authorization calls. M2M app identity (service principal) handles background operations. Scope consent is managed by admins. Both identity models share UC governance rules.
LakebasePG GRANT and RLS policies configured per table. Do NOT assume UC row filters apply to direct PG connections.
AUTHORIZATION LIVES AT THE RESOURCE. Know which one applies.
Different resources, different models. Get the token right, then verify what each resource enforces.
Applied AI Governance · Authorization by Resource Type