Embedding Databricks Apps w/o SSO
A Go-based reverse proxy that enables embedding Databricks Lakehouse Apps (like VS Code and Marimo notebooks) without requiring users to authenticate directly with Databricks.
Overview
Normally, embedding a Databricks app (such as the hosted VS Code editor or Marimo notebooks) in an iframe requires users to authenticate directly with Databricks through an SSO login flow. This exposes the Databricks login interface to end users and breaks the seamless experience of a custom application.
This Go reverse proxy eliminates the need for Databricks SSO by handling authentication transparently. Users authenticate with your application, and the proxy securely manages OAuth tokens behind the scenes.
Key Features
- Encrypted OAuth token transmission in URLs (AES-256-GCM)
- Full HTTP/HTTPS reverse proxy with CORS support
- Bidirectional WebSocket proxying for real-time features
- Dynamic routing to any Databricks Lakehouse App
- Secure iframe embedding with sandbox controls
- No OAuth tokens exposed to browser JavaScript
Embedded Applications
This proxy architecture powers several embedded applications:
High-Level Architecture
The following diagram shows the interaction between your Next.js application, the Go proxy server, and Databricks Lakehouse Apps. OAuth tokens are encrypted by Next.js, passed through the browser in encrypted form, and decrypted by the Go proxy.
Why a Proxy is Needed
Databricks Lakehouse Apps require OAuth Bearer token authentication for every request. When embedding these apps in iframes, we face several security challenges:
Token Exposure
If we embed the Databricks app directly with the token in the URL, the OAuth token would be visible in the browser's address bar, network inspector, and history.
CORS Restrictions
Databricks apps have strict CORS policies that prevent direct cross-origin requests from custom web applications.
WebSocket Authentication
WebSocket connections (used for terminals and real-time features) cannot easily include custom authentication headers from browser-initiated connections.
How the Proxy Solves These
Encrypted Token URLs
Next.js encrypts OAuth tokens server-side before embedding them in URLs. The Go proxy decrypts them and injects them as Authorization headers.
CORS Proxy
The proxy adds appropriate CORS headers to responses, enabling cross-origin iframe embedding while maintaining security.
WebSocket Proxying
The proxy detects WebSocket upgrade requests, establishes authenticated connections to Databricks, and bidirectionally forwards messages.
Complete Proxy Flow
The following sequence diagram illustrates the complete flow from when a user requests an embedded app through the establishment of HTTP and WebSocket connections.
Token Encryption
The security of the proxy relies on strong encryption of OAuth tokens. Both Next.js and the Go proxy use AES-256-GCM encryption with a shared secret key.
Encryption Architecture
Encryption Details
Algorithm: AES-256-GCM
- Algorithm: AES (Advanced Encryption Standard)
- Key Size: 256 bits (32 bytes)
- Mode: GCM (Galois/Counter Mode)
- Nonce: 12-byte random value per encryption
- Auth Tag: 16-byte authentication tag
- Encoding: URL-safe base64
Key Management
- Storage: Environment variable (ENCRYPTION_KEY)
- Format: 64-character hexadecimal string
- Shared: Same key in Next.js and Go proxy
- Generation:
openssl rand -hex 32
Proxy URL Pattern
The proxy uses a structured URL pattern that encodes all necessary information for routing and authentication:
Pattern:
/app-proxy/{encrypted_token}/{provider}/{domain}/{app_name}/{path}
Example:
/app-proxy/abc123xyz.../aws/databricksapps/code-editor-3771219485779100/terminal
Components:
- encrypted_token: AES-256-GCM encrypted OAuth token (URL-safe base64)
- provider: Cloud provider (aws, azure, gcp)
- domain: App domain (databricksapps)
- app_name: Specific app identifier
- path: Target path within the app (/, /terminal, /api/files, etc.)
Target URL Reconstruction:
https://{app_name}.{provider}.{domain}.com/{path}Iframe Embedding
The proxy enables secure embedding of Databricks Lakehouse Apps in iframes with proper sandbox controls.
Iframe Architecture
Sandbox Attributes
Allows JavaScript execution (required for editor functionality)
Allows access to localStorage and cookies within iframe context
Enables form submission for file uploads and settings
Allows opening new windows for help docs and external links
Permits file downloads for notebooks and data exports
WebSocket Support
Real-time features like terminal sessions and language server protocol require WebSocket connections. The Go proxy provides full bidirectional WebSocket proxying.
WebSocket Proxy Flow
WebSocket Detection
func isWebSocketRequest(r *http.Request) bool {
return strings.ToLower(r.Header.Get("Connection")) == "upgrade" &&
strings.ToLower(r.Header.Get("Upgrade")) == "websocket"
}
// In the main handler:
if isWebSocketRequest(r) {
wsURL := strings.Replace(targetURL, "https://", "wss://", 1) + remainingPath
handleWebSocketProxy(w, r, wsURL, token)
} else {
handleHTTPProxy(w, r, targetURL, token, remainingPath)
}Deployment
The Go proxy can be deployed in several ways:
Docker Container
Build a Docker image and deploy to any container platform (ECS, Kubernetes, Cloud Run)
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o proxy main.go crypto.go
FROM alpine:latest
COPY --from=builder /app/proxy /proxy
ENV ENCRYPTION_KEY=""
ENV PORT=8090
EXPOSE 8090
CMD ["/proxy"]Serverless Function
Deploy as AWS Lambda or Google Cloud Functions for auto-scaling
VM or Bare Metal
Run directly on VMs for maximum performance and control
Configuration Reference
| Variable | Description | Required |
|---|---|---|
ENCRYPTION_KEY | AES-256 key (64 hex chars) | Yes |
APP_DOMAIN_SUFFIX | Domain suffix (default: com) | No |
PORT | Server port (default: 8090) | No |