OAuth 2.0 with Proof Key for Code Exchange (PKCE) provides a secure authentication framework for integrating Sigma with cloud data platforms. When embedding Sigma analytics in your applications or implementing secure data access patterns, OAuth 2.0 with PKCE ensures that users authenticate with their own credentials and access only the data they're authorized to see.
This QuickStart explains the key concepts, security benefits, and implementation considerations for using OAuth 2.0 with PKCE in Sigma deployments. You'll understand why OAuth matters for both native and embedded analytics, how PKCE enhances security, and what patterns work best for different Sigma use cases.
This is a conceptual QuickStart designed to build foundational understanding and is not "hands-on".
Developers implementing embedded Sigma analytics in custom applications
Prerequisites
Understanding of authentication and authorization concepts
Familiarity with web application security principles
Basic knowledge of OAuth 2.0 flows (recommended but not required)
What is OAuth 2.0?
OAuth 2.0 is an industry-standard authorization framework that enables applications to obtain limited access to user accounts on an HTTP service. Rather than sharing passwords, OAuth 2.0 allows users to grant applications access to their resources through secure token-based authentication.
Key Components
Resource Owner (User): The person who owns the data and grants access to it. In Sigma deployments, this is typically an employee or customer accessing data through Sigma workbooks or dashboards embedded in your application.
Client (Application): The application requesting access to protected resources on behalf of the user. When using Sigma Embedding, this is your custom application hosting embedded Sigma content (dashboards, workbooks, or visualizations).
Authorization Server: The server that authenticates the user and issues access tokens after successful authorization. For Sigma integrations, this is typically your cloud data warehouse's OAuth service (Snowflake, BigQuery, Redshift, etc.) or your corporate identity provider (Okta, Azure AD, etc.).
Resource Server: The server hosting the protected resources (data). For Sigma users, this is your cloud data warehouse (Snowflake, BigQuery, Redshift, Azure Synapse, etc.) that Sigma queries on the user's behalf.
The Authorization Flow
Here's how OAuth 2.0 works when a user accesses embedded Sigma content:
User initiates action: User clicks on embedded Sigma dashboard in your application
Authorization request: Your application redirects user to the authorization server (this could be your corporate SSO provider like Okta/Azure AD for federated identity, or directly to the data warehouse OAuth endpoint)
User authentication: User logs in with their credentials
Authorization grant: User approves Sigma's access request to query data on their behalf
Token exchange: Your application receives an access token from the authorization server (if using federated identity, your application exchanges the SSO token for a data warehouse token)
Sigma queries data: Sigma uses the data warehouse token to query with the user's permissions
Connection-Level vs Organization-Level OAuth
When implementing OAuth with Sigma, you have two primary approaches for managing authentication:
Connection-Level OAuth:
Each user authenticates individually with the data platform (Snowflake, BigQuery, Redshift, etc.)
Tokens are scoped to specific connections
Supports PKCE for enhanced security (this is the key advantage)
Ideal for embedded scenarios where user identity and individual permissions matter
Each query runs with the authenticated user's credentials
Provides the strongest audit trail and access control
Organization-Level OAuth:
Uses a single service account or shared credentials for all users
All users query through the same organizational identity
Does not support PKCE
Simpler initial setup but less granular access control
Better for scenarios where all users have identical data permissions
Requires implementing Row-Level Security (RLS) separately if user-specific data access is needed
Why OAuth 2.0 for Sigma Deployments?
Security: No database credentials stored in Sigma or your application - users authenticate directly with the data platform
Granular Control: Each Sigma user queries data with their own permissions - see only what they're authorized to access
Audit Trail: Detailed logging shows which user ran which Sigma queries and when, meeting governance requirements
User Experience: Single sign-on enables seamless access to embedded Sigma content without additional logins
Compliance: Meets regulatory requirements (SOC 2, HIPAA, GDPR) for data access controls and auditability
What is PKCE?
Proof Key for Code Exchange (PKCE, pronounced "pixie") is an extension to OAuth 2.0 that provides additional security for public clients, particularly browser-based and mobile applications. When using Sigma, PKCE prevents authorization code interception attacks that could compromise user data access.
The Security Problem PKCE Solves
Traditional OAuth 2.0 authorization code flow assumes the client can securely store a client secret. However, public clients like browser-based and mobile applications cannot securely store secrets because:
JavaScript code can be inspected in the browser
Mobile applications can be decompiled
OAuth secrets in client-side code can be extracted by attackers
This creates a vulnerability where an attacker could intercept the authorization code and exchange it for an access token, gaining unauthorized access to your data warehouse.
How PKCE Works
PKCE adds two cryptographic elements to the authorization flow:
Code Verifier: A cryptographically random string (43-128 characters) generated by the client at the start of the flow. This remains secret on the client.
Code Challenge: A transformed version of the code verifier, created using SHA-256 hashing. This is sent to the authorization server.
PKCE Flow Step-by-Step
Client generates code verifier: Random string created at flow start
Client creates code challenge: SHA-256 hash of code verifier
Authorization request with challenge: Client sends code challenge to auth server
User authenticates: Standard OAuth login flow occurs
Authorization code returned: Server sends code back to client
Token request with verifier: Client sends authorization code AND original code verifier
Server validates: Server hashes verifier, compares to stored challenge
Token issued: If match confirmed, access token provided
PKCE Benefits
No Client Secret Required: Eliminates the need to store secrets in public clients
Prevents Code Interception: Even if authorization code is stolen, it's useless without the verifier
Backward Compatible: Works with existing OAuth 2.0 infrastructure
Industry Best Practice: Recommended by OAuth 2.0 Security Best Practices RFC
Real-World Use Case: Embedded Sigma Analytics
Consider an enterprise scenario where you want to embed Sigma dashboards into your customer portal:
Without OAuth/PKCE:
Requires storing data warehouse credentials in your application or Sigma connection
All Sigma users share the same database connection and permissions
No per-user access control - everyone sees all data
Difficult to audit which individual user ran which Sigma query
Security risk if application is compromised - credentials exposed
Cannot leverage warehouse-native row-level security features
With OAuth/PKCE:
No credentials stored in your application or Sigma
Each Sigma user authenticates with their own data warehouse identity
Sigma queries respect each user's warehouse permissions automatically
Complete audit trail showing which user accessed what data through Sigma
Sigma Storage: Access tokens are stored in buffer and encrypted using envelope encryption with AES256
Refresh Tokens
Longer-lived (up to 90 days)
Used to obtain new access tokens
Must be stored securely
Can be revoked by authorization server
Sigma Storage: Refresh tokens are encrypted using unique keys per customer. Encryption keys are housed in a separate key store for enhanced security
Token Expiration Flow in Sigma
User views embedded Sigma dashboard, Sigma queries data with access token
Data warehouse returns "token expired" error
Your application uses refresh token to request new access token from authorization server
New access token issued without user re-authentication
Sigma retries the query with new token - user experience uninterrupted
Scopes and Permissions
OAuth 2.0 uses "scopes" to define what access a token grants. When Sigma integrates with data platforms, scopes determine what Sigma can do on the user's behalf:
Common Scope Examples for Sigma Integration:
OAuth scopes vary by data warehouse platform. Here are examples from commonly used platforms:
Snowflake:
session:role-any - Allows Sigma to use any role the user has access to
refresh_token - Enables refresh token generation for long-running sessions
session:scope:warehouse - Permission to use warehouse resources for query execution
Databricks:
sql - Permission for Sigma to execute SQL queries against the data warehouse
offline_access - Allows Sigma to request refresh tokens for long-running sessions
all-apis - Full API access (use with caution, grant only necessary permissions)
BigQuery:
https://www.googleapis.com/auth/bigquery - Access to BigQuery API for running queries
https://www.googleapis.com/auth/bigquery.readonly - Read-only access to BigQuery data
offline_access - Allows Sigma to request refresh tokens
General Concepts Across Platforms:
SQL execution permissions - Core access to run queries
Refresh token capabilities - For long-running Sigma sessions
Resource access controls - Permission to use compute/warehouse resources
Metadata access - Ability to read schema and table information
Note: Consult your data platform's OAuth documentation for specific scope names and definitions. Most cloud data warehouses support similar security concepts with platform-specific naming conventions.
Scope Request Flow:
Your application requests specific scopes when initiating OAuth flow
Authorization server shows user what Sigma will be able to do
User approves or denies the requested scopes
Token is issued with only approved scopes
Data warehouse enforces scope restrictions on all Sigma queries
Requires all users to have individual data platform accounts (licensing cost)
Additional login step interrupts embedded Sigma user experience
More complex token management logic in your application
Pattern 2: Service Account with Row-Level Security
Scenario: Sigma connects using shared service account, data filtered by user attributes
Flow:
Your application authenticates with shared warehouse service account
User identity passed via Sigma embed parameters (user attributes)
Sigma includes user attributes in SQL queries (e.g., WHERE user_id = ?)
Data warehouse row-level security or custom SQL enforces RLS based on user context
Query results automatically filtered per user permissions
Pros:
Simplified authentication flow - no OAuth redirect for Sigma users
Users don't need individual data warehouse accounts (cost savings)
Centralized permission management in Sigma user attributes
Smoother embedded Sigma user experience
Cons:
Less granular audit trail - queries run as service account
Requires implementing RLS logic in warehouse or Sigma SQL
Service account credentials must be secured in Sigma connection
Cannot leverage some warehouse user-level features
Pattern 3: Federated Identity
Scenario: Corporate SSO integrated with both Sigma and data platform
Flow:
User logs into your application via corporate SSO (Okta, Azure AD, etc.)
Your application exchanges SSO token for data warehouse OAuth token
Data warehouse OAuth token passed to Sigma for embedded content
Sigma uses token to query data - single identity across all systems
User never sees additional login prompts
Pros:
Seamless Sigma user experience - single corporate login covers everything
Centralized identity management across application, Sigma, and data platform
Consistent access policies enforced by corporate identity provider
Easy onboarding/offboarding - one place to manage all access
Best for enterprise deployments with existing SSO infrastructure
Cons:
Most complex initial setup - requires SSO integration with data warehouse and Sigma
Dependency on identity provider availability
Choosing the Right Pattern for Sigma
Use Connection-Level OAuth with PKCE (Pattern 1) when:
You need the strongest security posture with PKCE protection
Regulatory compliance requires tracking which user ran which Sigma query
Users already have individual data platform accounts
Data sensitivity is very high (healthcare, financial)
You want to leverage platform-native permissions in Sigma dashboards
Enhanced security against authorization code interception is required
Use Service Account with RLS when:
Embedding Sigma for external customers who don't have data warehouse accounts
You control user permissions at the application layer
Cost of per-user data warehouse licenses is prohibitive
You already have RLS implemented in your data warehouse
Sigma user experience is more important than granular audit trail
Use Federated Identity when:
Enterprise SSO already deployed across your organization
Embedding Sigma for internal employees only
Multiple data platforms need consistent authentication
User convenience is top priority
You have resources for complex initial integration
Before implementing OAuth 2.0 with PKCE for your Sigma deployment, ensure your environment meets the necessary requirements and understand common challenges you'll encounter.
Platform Requirements
Your OAuth implementation requires support from both the authorization server (your data platform) and your application.
Authorization Server Must Support:
OAuth 2.0 authorization code flow
PKCE extension (code challenge/verifier)
Token refresh capability
Configurable token expiration times
Scope-based permission management
Token revocation endpoints
Your Application Must Support:
HTTPS/TLS for all OAuth communications
Secure token storage (never in localStorage)
Automatic token refresh before expiration
Error handling for expired/invalid tokens
OAuth redirect URI handling
State parameter for CSRF protection
Let's walk through the four most common challenges teams face when implementing OAuth with Sigma, with practical solutions you can apply.
Challenge 1: Token Refresh Timing
The Problem:
Your embedded Sigma dashboard is working perfectly. A user is exploring data, building visualizations, when suddenly: "Authentication Error - Token Expired." The access token expired mid-session, breaking their workflow.
Why This Happens:
Access tokens typically expire after 60 minutes. If you wait for the token to expire before refreshing, users will see errors when Sigma tries to query data.
The Solution:
Implement proactive token refresh that runs before expiration.
Practical Example:
// Check token expiration every 5 minutes
setInterval(async () => {
const tokenExpiry = getTokenExpiration();
const now = Date.now();
const timeUntilExpiry = tokenExpiry - now;
// Refresh if less than 10 minutes remaining
if (timeUntilExpiry < 10 * 60 * 1000) {
await refreshAccessToken();
}
}, 5 * 60 * 1000);
Best Practices:
Refresh tokens when 5-10 minutes remain on the access token
Queue Sigma API requests during the refresh process
Implement retry logic with exponential backoff for failed refreshes
Monitor refresh token success rates to catch issues early
Challenge 2: Redirect URI Management
The Problem:
OAuth requires exact redirect URI matching. You register https://app.example.com/callback with your data warehouse, but your staging environment uses https://staging.example.com/callback. Result? OAuth fails in staging with "redirect_uri_mismatch" error.
Why This Happens:
For security, authorization servers require exact matches between registered redirect URIs and the URI in your OAuth request. Different environments (dev/staging/prod) need different URIs.
The Solution:
Register separate OAuth applications for each environment and use environment variables.
Create separate OAuth apps in your data warehouse for each environment
Store client IDs and redirect URIs in environment variables
Document all registered redirect URIs in your team wiki
Use wildcard subdomains if your authorization server supports them
Test OAuth flow in each environment before deploying
Challenge 3: Secure Token Storage
The Problem:
A developer stores OAuth tokens in browser localStorage for convenience. Later, a security audit flags this as a critical XSS vulnerability - any malicious script can steal tokens and access your data warehouse.
Why This Happens:
localStorage is accessible to any JavaScript running on your page. If an attacker injects malicious code (XSS attack), they can steal tokens and impersonate users in Sigma.
The Solution:
Use httpOnly, secure cookies that JavaScript cannot access.
Practical Example:
// Backend: Set token as httpOnly cookie (Node.js/Express)
app.post('/oauth/callback', async (req, res) => {
const tokens = await exchangeCodeForTokens(req.query.code);
// Store access token in httpOnly cookie
res.cookie('sigma_access_token', tokens.access_token, {
httpOnly: true, // JavaScript cannot access
secure: true, // HTTPS only
sameSite: 'strict', // CSRF protection
maxAge: 3600000 // 1 hour
});
// Store refresh token separately with longer expiry
res.cookie('sigma_refresh_token', tokens.refresh_token, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 90 * 24 * 3600000 // 90 days
});
res.redirect('/dashboard');
});
Best Practices:
Always use httpOnly, secure cookies for tokens
Implement Content Security Policy headers
Use SameSite cookie attribute to prevent CSRF attacks
For mobile apps, use platform-native secure storage (Keychain/KeyStore)
Consider backend-for-frontend pattern for maximum security
Never store tokens in localStorage, sessionStorage, or URL parameters
Challenge 4: Mobile Deep Linking
The Problem:
A user clicks your embedded Sigma dashboard in your mobile app. OAuth redirects them to Safari/Chrome for data warehouse login. After authenticating, they're stuck in the browser - the app doesn't resume, and the user is confused.
Why This Happens:
OAuth redirects users to the authorization server's web login. Mobile apps need special URL schemes to redirect users back from the browser to the app.
The Solution:
Implement universal links (iOS) or app links (Android) to seamlessly return users to your app.
Practical Example:
// iOS Universal Link Configuration (apple-app-site-association)
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.example.app",
"paths": ["/oauth/callback"]
}
]
}
}
// Handle OAuth callback in your app
func application(_ app: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL,
url.path == "/oauth/callback" else {
return false
}
// Extract authorization code from URL
let code = extractAuthCode(from: url)
// Exchange for tokens and load Sigma embed
exchangeCodeForTokens(code) { tokens in
loadSigmaEmbed(with: tokens.accessToken)
}
return true
}
Best Practices:
Configure universal links (iOS) or app links (Android)
Test deep linking across different iOS/Android versions
Preserve user's place in the app during OAuth redirect
Implement custom URL schemes as fallback
Handle cases where universal links aren't configured
Provide clear visual feedback during OAuth redirect flow
Testing Your OAuth Implementation
Local Development:
Start by testing OAuth flows on your development machine:
// Use localhost for development
const devRedirectUri = 'http://localhost:3000/oauth/callback';
// Mock authorization server for unit tests
const mockAuthServer = {
generateTokens: () => ({
access_token: 'mock_access_token',
refresh_token: 'mock_refresh_token',
expires_in: 3600
})
};
Key Tests to Run:
Successful OAuth authorization flow end-to-end
Token expiration and automatic refresh
Error handling when tokens are invalid
PKCE code challenge/verifier validation
Redirect URI mismatch scenarios
Staging Environment:
Register a separate OAuth application for staging and test with production-like data:
Verify all redirect flows work correctly
Test token refresh before expiration
Simulate token expiration mid-session
Test error conditions (network failures, invalid tokens)
Verify Sigma embeds load with staging OAuth tokens
Production Monitoring:
Once deployed, monitor your OAuth implementation continuously:
// Log OAuth events (but never log tokens!)
logger.info('OAuth authorization started', {
userId: user.id,
timestamp: Date.now()
});
logger.info('Token refresh succeeded', {
userId: user.id,
expiresIn: 3600,
scopes: ['sql', 'offline_access']
});
logger.error('Token refresh failed', {
userId: user.id,
errorType: 'invalid_grant',
// DO NOT log the actual token or refresh token
});
Metrics to Monitor:
Token refresh success rate (target: >99%)
Authorization flow success rate
Average time for OAuth redirect flow
Token expiration errors
Unusual token usage patterns
OAuth implementations must meet audit, privacy, and security requirements.
Audit Requirements
What to Log:
Token issuance events (who, when, which scopes)
Data access through Sigma (which user queried what data)