cancel
Showing results forĀ 
Search instead forĀ 
Did you mean:Ā 
Data Engineering
Join discussions on data engineering best practices, architectures, and optimization strategies within the Databricks Community. Exchange insights and solutions with fellow data engineers.
cancel
Showing results forĀ 
Search instead forĀ 
Did you mean:Ā 

Long-lived authentication for Databricks Apps / FastAPI when using Service Principal (IoT use case)

Punit_Prajapati
Databricks Partner

Hi Community,

I’m working with Databricks Apps (FastAPI) and invoking the API from external IoT devices.

Currently, the recommended approach is to authenticate using a Bearer token generated via a Databricks Apps Service Principal (Client ID + Client Secret), as documented here:
https://apps-cookbook.dev/docs/fastapi/getting_started/connections/connect_from_external

This works, but the generated access token expires in 3600 seconds (1 hour).
For my use case (IoT devices deployed in the field), this is not practical, as I need a long-lived or non-expiring token, or at least a mechanism that does not require frequent re-authentication.

What I’ve tried

  1. Using Service Principal OAuth flow to generate the Bearer token

    • Token expires after 1 hour (expected behavior)

  2. Exploring on-behalf-of (OBO) token creation as discussed here:
    https://community.databricks.com/t5/data-engineering/on-behalf-of-token-creation-for-spn/td-p/32451

    • I have already granted CAN_MANAGE permissions on the Service Principal to my user

    • However, this approach does not work for my scenario because In my account console or Workspace I didnot get any option to enable or disable OBO Token

      Punit_Prajapati_1-1767935971292.png

       

3 REPLIES 3

MoJaMa
Databricks Employee
Databricks Employee

So from your IoT device you don't have a way to use any of the Unified Authentication mechanisms?

https://docs.databricks.com/aws/en/dev-tools/auth/unified-auth

Punit_Prajapati
Databricks Partner

Hi Databricks Team,

Thanks for the response.

I reviewed the Unified Authentication documentation. From what I understand, the supported authentication methods are PAT, M2M (Service Principal OAuth), and U2M.

For my use case, external IoT devices are calling a Databricks App (FastAPI endpoint).

Both M2M and U2M require OAuth access tokens that expire after 3600 seconds. This means the devices must frequently re-authenticate, which is not practical for IoT devices deployed in the field.

I also tried using a User PAT to call the Databricks App endpoint. This always returns 401 Unauthorized, even though the user has access to the Databricks App and the same PAT works for Databricks REST APIs. It only fails for Databricks Apps endpoints.

So currently, OAuth tokens are too short-lived for IoT use cases, and PATs do not seem to work for Databricks Apps.

Could you please clarify the following:

Is PAT-based authentication officially supported for Databricks Apps, or is it not supported by design?

Is there any supported way to use long-lived or non-interactive authentication for external systems such as IoT or edge devices?

If neither PAT nor long-lived tokens are supported, what is the recommended architecture for this scenario, such as using a proxy service or token broker?

SteveOstrowski
Databricks Employee
Databricks Employee
Hi @Punit_Prajapati,

This is a common architectural pattern for IoT scenarios, and there are a few approaches to consider depending on exactly how your IoT devices are calling the Databricks App.

UNDERSTANDING THE ARCHITECTURE

First, it helps to clarify the two distinct authentication layers in Databricks Apps:

1. Inbound authentication (IoT device to your App): How external clients reach your FastAPI endpoints.
2. Outbound authentication (your App to Databricks APIs): How your app calls Databricks services like SQL warehouses or Unity Catalog.

For layer 2, Databricks Apps automatically inject DATABRICKS_CLIENT_ID and DATABRICKS_CLIENT_SECRET environment variables for the app's own service principal. The Databricks SDK handles token refresh transparently when you use it inside the app, so that part should not require manual token management.

The challenge you are describing is layer 1: how your IoT devices authenticate when calling your FastAPI app.

OPTION 1: USE A PERSONAL ACCESS TOKEN (PAT) FOR THE SERVICE PRINCIPAL

PATs can have a much longer lifetime than OAuth access tokens. The default maximum is 730 days (two years), and workspace admins can configure the max lifetime.

To create a PAT for a service principal:

Step 1: A workspace admin creates an initial PAT on behalf of the service principal using the Databricks CLI:

databricks token-management create-obo-token APPLICATION_ID --lifetime-seconds 63072000 -p PROFILE_NAME

(63072000 seconds = 730 days)

Step 2: The service principal can then create additional tokens itself:

databricks tokens create --lifetime-seconds 63072000 -p PROFILE_NAME

Your IoT devices would then include this PAT in their HTTP requests to your FastAPI app, for example in an Authorization header. Your FastAPI app validates the token by calling the Databricks token introspection API or by maintaining its own validation logic.

Reference: https://docs.databricks.com/aws/en/dev-tools/auth/pat.html

Note on OBO token UI: The "create-obo-token" functionality is available through the CLI and REST API (Token Management API), not through a workspace UI toggle. There is no separate UI setting to "enable" OBO tokens. You run the CLI command or call the API directly as a workspace admin.

OPTION 2: IMPLEMENT CLIENT-SIDE OAUTH TOKEN REFRESH

If you prefer to stick with the standard OAuth M2M flow, the IoT devices can hold the service principal's client_id and client_secret and request a fresh access token before each API call (or when the current token is close to expiring). The token endpoint is:

POST https://YOUR_WORKSPACE.cloud.databricks.com/oidc/v1/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&scope=all-apis

Each token is valid for 1 hour. On the IoT device, you would implement a simple refresh loop or check token expiry before each request and re-fetch if needed. Many HTTP client libraries support this pattern natively (e.g., Python's requests-oauthlib or httpx with an auth handler).

This is the most secure approach because credentials are not stored as long-lived bearer tokens, but it does require the IoT devices to have outbound HTTPS connectivity to the workspace token endpoint.

OPTION 3: INTERMEDIARY TOKEN GATEWAY

If your IoT devices are too constrained to handle OAuth flows directly, consider placing a lightweight token gateway (for example, an AWS Lambda, Azure Function, or a small API service) between the devices and your Databricks App. The gateway:

1. Accepts requests from IoT devices authenticated with a long-lived API key or device certificate that you manage outside of Databricks.
2. Exchanges that credential for a short-lived Databricks OAuth token using the service principal's client credentials.
3. Forwards the request to your Databricks App with the fresh token.

This keeps the Databricks credential lifecycle separate from the device authentication lifecycle.

OPTION 4: APP-LEVEL CUSTOM AUTHENTICATION

Since your FastAPI app is the endpoint receiving IoT traffic, you can implement your own authentication layer within the app itself. For example:

- Generate your own long-lived API keys and store them in Databricks Secrets.
- Your FastAPI middleware validates incoming requests against those keys.
- Once validated, the app uses its own automatically managed service principal credentials (via the Databricks SDK) to interact with Databricks resources.

This decouples IoT device authentication from Databricks OAuth entirely. Your app handles device auth, and the Databricks SDK handles Databricks auth.

from databricks.sdk import WorkspaceClient
from fastapi import FastAPI, Depends, HTTPException, Header

app = FastAPI()
w = WorkspaceClient() # Automatically uses app service principal credentials

async def verify_device_key(x_api_key: str = Header(...)):
# Validate against keys stored in Databricks Secrets or a config
valid_keys = w.secrets.get_secret("iot-scope", "valid-api-keys")
if x_api_key not in valid_keys.value.split(","):
raise HTTPException(status_code=401, detail="Invalid API key")

@app.post("/ingest")
async def ingest_data(data: dict, _=Depends(verify_device_key)):
# Process IoT data using the app's service principal
# The SDK handles token refresh automatically
w.statement_execution.execute_statement(...)

RECOMMENDATION

For IoT use cases, Option 4 (custom app-level auth) or Option 1 (PATs) tend to be the most practical. Option 4 gives you full control over the device credential lifecycle without depending on Databricks token expiry at all. Option 1 gives you up to 2-year token validity with minimal code changes.

Key documentation references:
- Databricks Apps authorization: https://docs.databricks.com/aws/en/dev-tools/databricks-apps/auth
- OAuth M2M authentication: https://docs.databricks.com/aws/en/dev-tools/auth/oauth-m2m.html
- Personal access tokens: https://docs.databricks.com/aws/en/dev-tools/auth/pat.html
- Token management for service principals: https://docs.databricks.com/aws/en/admin/access-control/tokens.html

* This reply used an agent system I built to research and draft this response based on the wide set of documentation I have available and previous memory. I personally review the draft for any obvious issues and for monitoring system reliability and update it when I detect any drift, but there is still a small chance that something is inaccurate, especially if you are experimenting with brand new features.

If this answer resolves your question, could you mark it as "Accept as Solution"? That helps other users quickly find the correct fix.