BETTER-AUTH. UI
Advanced

API Keys

API Keys provide a secure way for applications and services to authenticate with your API programmatically. Better Auth UI includes a complete API key management system with creation, expiration, and revocation capabilities.

Overview

The API key system provides:

  • Secure Generation: Cryptographically secure key generation
  • Expiration Management: Set expiration dates for keys
  • Custom Prefixes: Add custom prefixes to identify key types
  • Metadata Support: Attach metadata to keys for tracking
  • One-Time Display: Keys are shown only once after creation
  • Secure Storage: Keys are hashed before storage

Enabling API Keys

To enable API keys, configure the apiKey prop in your AuthUIProvider:

providers.tsx
<AuthUIProvider
  authClient={authClient}
  apiKey={true} // Simple enable
>
  {children}
</AuthUIProvider>

Advanced Configuration

providers.tsx
<AuthUIProvider
  authClient={authClient}
  apiKey={{
    prefix: "app_", // Custom prefix for all keys
    metadata: {
      // Default metadata for new keys
      environment: "production",
      version: "v1",
    },
  }}
>
  {children}
</AuthUIProvider>

Key Components

ApiKeysCard

The main component for managing API keys:

import { ApiKeysCard } from "@/components/settings/api-key/api-keys-card";

<ApiKeysCard />;

In AccountView

API keys automatically appear in settings when enabled:

import { AccountView } from "better-auth-ui";

// Shows API keys management when view="API_KEYS"
<AccountView view="API_KEYS" />;

API Key Structure

Generated API keys follow this structure:

[prefix][random_string]

Example: app_sk_live_a1b2c3d4e5f6g7h8i9j0

Using API Keys

Client-Side Generation

const { authClient } = useContext(AuthUIContext);

// Create a new API key
const { key } = await authClient.apiKey.create({
  name: "Production API Key",
  expiresIn: 30 * 24 * 60 * 60, // 30 days in seconds
  prefix: "prod_",
  metadata: {
    service: "payment-processor",
  },
});

console.log(key); // This is the only time you'll see the full key

Server-Side Validation

// In your API endpoint
import { auth } from "@/lib/auth";

export async function POST(request: Request) {
  const apiKey = request.headers.get("x-api-key");

  if (!apiKey) {
    return new Response("API key required", { status: 401 });
  }

  const session = await auth.api.validateApiKey({
    apiKey,
  });

  if (!session) {
    return new Response("Invalid API key", { status: 401 });
  }

  // Access user and metadata
  console.log(session.user);
  console.log(session.apiKey.metadata);

  // Process request...
}

Security Features

One-Time Display

  • Keys are shown in full only once after creation
  • Users must copy the key immediately
  • Lost keys cannot be recovered

Secure Storage

  • Keys are hashed using bcrypt before storage
  • Original keys are never stored in the database
  • Only the first few characters are stored for identification

Expiration

  • Keys can have expiration dates
  • Expired keys are automatically rejected
  • No expiration option available for long-lived keys

Best Practices

  1. Naming Convention

    "Production - Payment Service"
    "Development - Local Testing"
    "CI/CD - GitHub Actions"
  2. Expiration Policy

    • Development keys: 7-30 days
    • Production keys: 90-365 days
    • CI/CD keys: No expiration with rotation
  3. Key Rotation

    • Rotate production keys every 90 days
    • Implement overlap period for smooth transition
    • Log key usage for audit trails
  4. Access Control

    • Limit who can create API keys
    • Log all key operations
    • Monitor key usage patterns
  5. Environment Separation

    apiKey={{
      prefix: process.env.NODE_ENV === 'production' ? 'pk_' : 'sk_test_'
    }}

Metadata Usage

Attach metadata to track key usage:

await authClient.apiKey.create({
  name: "Analytics Service",
  metadata: {
    service: "analytics",
    environment: "production",
    permissions: ["read:analytics", "write:reports"],
    rateLimit: 1000,
  },
});

Rate Limiting

Implement rate limiting based on metadata:

// Server-side
const session = await auth.api.validateApiKey({ apiKey });
const rateLimit = session.apiKey.metadata.rateLimit || 100;

// Apply rate limiting logic

Monitoring

Track API key usage:

  1. Usage Metrics: Track requests per key
  2. Error Rates: Monitor failed authentications
  3. Expiration Alerts: Notify before keys expire
  4. Anomaly Detection: Detect unusual usage patterns

Error Handling

Common API key errors:

  • API_KEY_INVALID: Key doesn't exist or is malformed
  • API_KEY_EXPIRED: Key has passed expiration date
  • API_KEY_REVOKED: Key has been manually revoked
  • API_KEY_RATE_LIMITED: Key has exceeded rate limits

Next Steps