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 '@daveyplate/better-auth-ui'

<APIKeysCard />

In SettingsCards

API keys automatically appear in settings when enabled:

import { SettingsCards } from '@daveyplate/better-auth-ui'

// Shows API keys management when view="API_KEYS"
<SettingsCards 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