Skip to main content

On-behalf-of-user authentication

This recipe demonstrates how to use Databricks Apps on-behalf-of-user authentication to run a SQL query using the user's credentials instead of the app's service principal.

Code snippet​

app.py
import reflex as rx
import pandas as pd
from databricks import sql
from databricks.sdk.core import Config

cfg = Config()

_connection = None

def get_user_token(headers):
return getattr(headers, "x_forwarded_access_token", "")

def connect_with_obo(http_path: str, user_token: str):
global _connection
if _connection:
return _connection
_connection = sql.connect(
server_hostname=cfg.host,
http_path=http_path,
access_token=user_token
)
return _connection

def execute_query(table_name: str, conn):
with conn.cursor() as cursor:
query = f"SELECT * FROM {table_name} LIMIT 10"
cursor.execute(query)
return cursor.fetchall_arrow().to_pandas()

class OboState(rx.State):
warehouse_paths: dict[str, str] = {}
selected_warehouse: str = ""
table_name: str = "samples.nyctaxi.trips"
data: list[list] = []
columns: list[dict] = []
is_loading: bool = False
error_message: str = ""

@rx.event(background=True)
async def run_query(self):
async with self:
self.is_loading = True
self.error_message = ""
headers = self.router.headers
user_token = get_user_token(headers)

if not user_token:
async with self:
self.error_message = "No OBO token found."
self.is_loading = False
return

try:
http_path = self.warehouse_paths.get(self.selected_warehouse)
conn = connect_with_obo(http_path, user_token)
df = execute_query(self.table_name, conn)

# Process dataframe for display
d = df.values.tolist()
c = [{"title": col, "id": col, "type": "str"} for col in df.columns]

async with self:
self.data = d
self.columns = c
except Exception as e:
async with self:
self.error_message = str(e)
finally:
async with self:
self.is_loading = False
info

This sample caches the SQL connection in a module-level _connection variable so it can be reused within the same app process. The app will only work when deployed to Databricks Apps with on-behalf-of-user authentication enabled.

warning

You need to enable on-behalf-of-user authentication for your application for this sample to work. When running this code locally, the X-Forwarded-Access-Token will not be present and the sample will not work as intended.

Resources​

Permissions​

For the on-behalf-of-user authentication model, permissions work as follows:

  • User's permissions: When using OBO authentication, the query runs with the end user's permissions

    • User needs SELECT permissions on the tables being queried
    • User needs CAN USE on the SQL warehouse
  • App service principal: When falling back to service principal authentication

    • Needs CAN USE on the SQL warehouse
    • Needs SELECT on the Unity Catalog tables for fallback access

See Databricks Apps authorization model for more information.

Dependencies​

requirements.txt
databricks-sdk
databricks-sql-connector
pandas
reflex