Authentication

Authentication

Authentication methods for SelfHostedDB API

SelfHostedDB supports two authentication methods: HTTP Basic Authentication and API Keys.


HTTP Basic Authentication

Overview

HTTP Basic Authentication uses a username and password combination. The credentials are set via environment variables AUTH_USER and AUTH_PASS.

Usage

cURL:

curl -u username:password http://localhost:3001/api/tables

JavaScript (fetch):

const username = 'admin';
const password = 'secret';
const credentials = btoa(`${username}:${password}`);
 
fetch('http://localhost:3001/api/tables', {
  headers: {
    'Authorization': `Basic ${credentials}`
  }
});

JavaScript (axios):

const axios = require('axios');
 
axios.get('http://localhost:3001/api/tables', {
  auth: {
    username: 'admin',
    password: 'secret'
  }
});

Python (requests):

import requests
 
response = requests.get(
    'http://localhost:3001/api/tables',
    auth=('admin', 'secret')
)

Header Format

Authorization: Basic base64(username:password)

When to Use

  • Development and testing - Quick setup
  • Single-user deployments - Simple authentication
  • Internal tools - When API keys aren't needed

Security Notes

  • Credentials are sent with every request
  • Use HTTPS in production to protect credentials
  • Change default credentials immediately
  • Use strong passwords (16+ characters)

API Key Authentication

Overview

API Keys provide a more secure, token-based authentication method. Each API key is associated with a specific schema (project) and can be scoped with different permissions.

Creating API Keys

Endpoint: POST /api/project/:schema/keys

Request:

curl -X POST http://localhost:3001/api/project/my_schema/keys \
  -u admin:secret \
  -H "Content-Type: application/json" \
  -d '{
    "keyName": "My API Key",
    "keyType": "anon"
  }'

Response:

{
  "id": 1,
  "key": "a1b2c3d4e5f6...64-character-hex-string",
  "keyPrefix": "a1b2c3d4",
  "keyName": "My API Key",
  "keyType": "anon",
  "schemaName": "my_schema",
  "createdAt": "2025-01-27T10:00:00.000Z"
}

Important: The full API key is only returned once on creation. Store it securely!

Key Types

  • anon - Anonymous key (read-only access, typically)
  • service_role - Service role key (full access)

Usage

cURL:

curl -H "Authorization: Bearer your-api-key-here" \
  http://localhost:3001/api/tables?schema=my_schema

JavaScript (fetch):

fetch('http://localhost:3001/api/tables?schema=my_schema', {
  headers: {
    'Authorization': `Bearer ${apiKey}`
  }
});

JavaScript (axios):

axios.get('http://localhost:3001/api/tables', {
  params: { schema: 'my_schema' },
  headers: {
    'Authorization': `Bearer ${apiKey}`
  }
});

Python (requests):

import requests
 
headers = {
    'Authorization': f'Bearer {api_key}'
}
 
response = requests.get(
    'http://localhost:3001/api/tables',
    params={'schema': 'my_schema'},
    headers=headers
)

Header Format

Authorization: Bearer your-api-key-here

Schema Association

API keys are automatically associated with a schema. When using an API key:

  • The schema is automatically set from the key
  • You don't need to specify schema parameter (but can override)
  • All operations are scoped to that schema

Managing API Keys

List API Keys:

GET /api/project/:schema/keys

Delete API Key:

DELETE /api/project/:schema/keys/:keyId

When to Use

  • Production applications - More secure than Basic Auth
  • Multiple users/services - Each can have their own key
  • Programmatic access - Better for automation
  • Key rotation - Easy to revoke and recreate

Security Best Practices

  • Store API keys in environment variables or secrets manager
  • Never commit API keys to version control
  • Rotate keys regularly (every 90 days)
  • Use different keys for different environments
  • Revoke keys immediately if compromised

Authentication Flow

Basic Auth Flow

  1. Client sends request with Authorization: Basic <credentials> header
  2. Server validates credentials against AUTH_USER and AUTH_PASS
  3. If valid, request proceeds; if invalid, returns 401

API Key Flow

  1. Client sends request with Authorization: Bearer <api-key> header
  2. Server hashes the API key and looks it up in database
  3. If found and active, request proceeds with schema from key
  4. If not found or inactive, returns 401

Combined Authentication

The API supports both methods. The server checks for Bearer token first, then falls back to Basic Auth:

// Try API key first
if (authHeader.startsWith('Bearer ')) {
  return apiKeyAuth(req, res, next);
}
// Fall back to Basic Auth
return basicAuth(req, res, next);

Error Responses

401 Unauthorized

Basic Auth:

{
  "error": "Unauthorized",
  "message": "Invalid credentials"
}

API Key:

{
  "error": "Unauthorized",
  "message": "Invalid API key"
}

Missing Authentication

{
  "error": "Unauthorized",
  "message": "Authentication required"
}

Examples

Complete Example: Using API Key

// 1. Create API key (one-time setup)
const createKey = async () => {
  const response = await fetch('http://localhost:3001/api/project/my_schema/keys', {
    method: 'POST',
    headers: {
      'Authorization': 'Basic ' + btoa('admin:secret'),
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      keyName: 'My App Key',
      keyType: 'anon'
    })
  });
  
  const data = await response.json();
  console.log('API Key:', data.key); // Store this securely!
  return data.key;
};
 
// 2. Use API key for requests
const fetchTables = async (apiKey) => {
  const response = await fetch('http://localhost:3001/api/tables?schema=my_schema', {
    headers: {
      'Authorization': `Bearer ${apiKey}`
    }
  });
  
  return response.json();
};

Related Documentation


Last Updated: 2025-01-27