# How to Integrate Custom Authentication with Apache Superset: A Complete Guide

> Integrate custom authentication with Apache Superset easily. Extend better-auth to add OAuth providers, session data, and JWT claims for enhanced security. Get the complete guide.

- Repository: [Superset/superset](https://github.com/superset-sh/superset)
- Tags: how-to-guide
- Published: 2026-03-08

---

**You can integrate custom authentication with Apache Superset by extending the better-auth configuration in [`packages/auth/src/server.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/server.ts) to add OAuth providers, custom session data, and JWT claims.**

The superset-sh/superset repository ships with a production-ready authentication layer built on **better-auth**, providing a type-safe foundation for enterprise login flows. Whether you need to connect a corporate SSO, inject organization-specific metadata into user sessions, or secure API endpoints with custom JWT claims, the architecture exposes clear extension points without modifying core framework code.

## Understanding the Authentication Architecture

The authentication system centers on a single configuration object in [`packages/auth/src/server.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/server.ts) where the `betterAuth()` factory registers plugins for specific capabilities. This design keeps all auth logic centralized while remaining extensible through a plugin-based model.

Key files in the authentication stack include:

- **[`packages/auth/src/server.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/server.ts)** – Core configuration, plugin registration, and custom session logic.
- **[`packages/auth/src/env.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/env.ts)** – Environment variable validation for secrets and public client configuration.
- **[`packages/auth/src/client.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/client.ts)** – Typed client export for UI and API consumption.
- **[`packages/trpc/src/trpc.ts`](https://github.com/superset-sh/superset/blob/main/packages/trpc/src/trpc.ts)** – tRPC context injection where the `auth` instance is made available to API routers.

## How to Add a Custom OAuth Provider

Superset-sh supports multiple OAuth 2.0 providers simultaneously through the `socialProviders` object in the better-auth configuration. You can add corporate identity providers like Microsoft Entra ID, Okta, or Auth0 by extending this configuration block.

To register a new provider, locate the `socialProviders` definition (approximately lines 90–98 in [`server.ts`](https://github.com/superset-sh/superset/blob/main/server.ts)) and add your provider configuration:

```typescript
// packages/auth/src/server.ts – inside the `betterAuth({ … })` call
socialProviders: {
  github: { 
    clientId: env.GH_CLIENT_ID, 
    clientSecret: env.GH_CLIENT_SECRET 
  },
  google: { 
    clientId: env.GOOGLE_CLIENT_ID, 
    clientSecret: env.GOOGLE_CLIENT_SECRET 
  },
  // Add Microsoft OAuth provider
  microsoft: {
    clientId: env.MS_CLIENT_ID,
    clientSecret: env.MS_CLIENT_SECRET,
    scopes: ["email", "profile", "openid"],
    // Optional: override authorization or token endpoints for tenant-specific flows
  },
},

```

Ensure corresponding environment variables are defined in [`packages/auth/src/env.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/env.ts) and your deployment environment.

## Enriching Sessions with Custom Data

For scenarios requiring organization-specific context—such as feature flags, tenant isolation, or user roles—you can inject custom fields into the session object using the `customSession` plugin. This callback executes on every request after user identification, allowing dynamic enrichment based on database lookups or external services.

The `customSession` implementation resides approximately at lines 539–586 in [`server.ts`](https://github.com/superset-sh/superset/blob/main/server.ts). Modify the callback to append your custom logic:

```typescript
// packages/auth/src/server.ts – customSession hook
customSession(async ({ user, session: baseSession }) => {
  const session = baseSession as typeof sessions.$inferSelect;

  // Existing enrichment logic for active organization
  const activeOrganizationId = session.activeOrganizationId;
  
  // Custom: Add feature flag based on email domain
  const isEnterpriseUser = user.email.endsWith("@enterprise.com");
  
  // Custom: Fetch additional user metadata from your database
  const userPreferences = await db.query.userPreferences.findFirst({
    where: eq(userPreferences.userId, user.id),
  });

  return {
    user,
    session: {
      ...session,
      activeOrganizationId,
      isEnterpriseUser,      // Injected custom field
      preferredLocale: userPreferences?.locale ?? "en",
    },
  };
}),

```

These injected fields become available throughout your application via the session object.

## Customizing JWT Claims for API Security

When securing API endpoints or integrating with external services, you may need to embed specific claims—such as organization IDs, roles, or locale preferences—directly into JWT access tokens. The `customAccessTokenClaims` option in [`server.ts`](https://github.com/superset-sh/superset/blob/main/server.ts) (approximately lines 218–220) enables this customization.

Define additional claims by extending the configuration object:

```typescript
// packages/auth/src/server.ts – customAccessTokenClaims
customAccessTokenClaims: ({ referenceId, user }) => ({
  organizationId: referenceId ?? undefined,
  role: user.role ?? "viewer",
  locale: user.locale ?? "en",   // Custom claim for localization
  tenantTier: user.tier ?? "free", // Custom claim for billing tier
}),

```

These claims are cryptographically signed and verifiable by downstream services, enabling stateless authorization decisions without database lookups.

## Accessing Authentication State in Client Code

The client-side integration relies on the typed `auth` object exported from [`packages/auth/src/client.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/client.ts). This client provides methods to retrieve sessions, handle OAuth callbacks, and manage authentication state in React components or other UI code.

Import the client and access enriched session data:

```typescript
// packages/auth/src/client.ts – typed client usage
import { auth } from "./client";

async function fetchDashboardData() {
  const { session } = await auth.getSession();
  
  if (!session) {
    throw new Error("Unauthorized");
  }
  
  // Access custom fields injected by customSession
  console.log("Enterprise access:", session.isEnterpriseUser);
  console.log("User locale:", session.preferredLocale);
  
  // Use organization ID from session for tenant-scoped queries
  return await api.dashboards.list(session.activeOrganizationId);
}

```

The type definitions automatically reflect any custom fields added to the session configuration, ensuring end-to-end type safety.

## Summary

Integrating custom authentication with Apache Superset requires understanding the better-auth plugin architecture centralized in [`packages/auth/src/server.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/server.ts). The key extension points include:

- **OAuth Providers**: Extend the `socialProviders` object to add corporate SSO options like Microsoft or Okta.
- **Session Enrichment**: Use the `customSession` callback to inject organization-specific metadata and feature flags.
- **JWT Customization**: Define additional claims via `customAccessTokenClaims` for stateless API authorization.
- **Client Integration**: Consume the typed `auth` client from [`packages/auth/src/client.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/client.ts) to access session data in UI components.

All modifications remain type-safe and persist across the tRPC API layer defined in [`packages/trpc/src/trpc.ts`](https://github.com/superset-sh/superset/blob/main/packages/trpc/src/trpc.ts).

## Frequently Asked Questions

### Can I integrate multiple OAuth providers simultaneously?

Yes. The `socialProviders` configuration object in [`packages/auth/src/server.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/server.ts) accepts multiple provider definitions concurrently. You can enable GitHub, Google, Microsoft, and custom OIDC providers simultaneously, and better-auth will handle the routing and callback logic for each. Users can then choose their preferred login method from the authentication UI.

### How do I store additional user metadata in the session?

Use the `customSession` plugin callback in [`packages/auth/src/server.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/server.ts) to fetch and attach custom fields. This async function receives the `user` and `session` objects, allowing you to query external databases or APIs to retrieve roles, preferences, or tenant information. Return these values in the session object, and they become available in both server-side tRPC contexts and client-side code via the typed `auth` client.

### Is the authentication system compatible with existing Superset deployments?

The superset-sh/superset repository represents a modernized architecture built on better-auth, which differs from the legacy Flask-AppBuilder authentication in traditional Apache Superset deployments. While the concepts (OAuth, JWT, RBAC) remain similar, the implementation files and configuration methods described here are specific to the superset-sh codebase. Migration from legacy Superset would require adapting existing authentication logic to the better-auth plugin architecture described in [`packages/auth/src/server.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/server.ts).

### Where should I define environment variables for authentication?

Environment variables are validated and typed in [`packages/auth/src/env.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/env.ts) using a schema validation library (likely Zod or similar). Define all OAuth client secrets, JWT signing keys, and API key secrets in this file to ensure type safety across the application. The validated `env` object is then imported into [`packages/auth/src/server.ts`](https://github.com/superset-sh/superset/blob/main/packages/auth/src/server.ts) and passed to the better-auth configuration, ensuring that sensitive credentials are never hardcoded and are properly validated at startup.