33800 Docs

← Retour

Proposition : Système de Clés API pour Connectors Hub

Status : IMPLEMENTEE

Objectif

Permettre aux utilisateurs de créer des clés API permanentes pour s'authentifier sans passer par le login JWT classique.

Use case : Appeler /api/fetch depuis un script, cron, ou autre service sans avoir à gérer les cookies/sessions.

Design proposé

1. Nouvelle table api_keys

CREATE TABLE connectors.api_keys (
    id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
    user_id uuid NOT NULL,
    name text NOT NULL,                    -- ex: "Script backup", "CI/CD"
    key_hash text NOT NULL,                -- SHA256 du préfixe + clé
    key_prefix text NOT NULL,              -- 8 premiers chars pour identification (ex: "ck_abc123")
    scopes text[] DEFAULT '{}',            -- permissions: ['fetch', 'connectors:read', 'audit:read']
    expires_at timestamptz,                -- null = jamais
    last_used_at timestamptz,
    created_at timestamptz DEFAULT now(),
    revoked_at timestamptz,

    CONSTRAINT api_keys_user_name_unique UNIQUE (user_id, name)
);

CREATE INDEX idx_api_keys_user ON connectors.api_keys (user_id) WHERE revoked_at IS NULL;
CREATE INDEX idx_api_keys_prefix ON connectors.api_keys (key_prefix) WHERE revoked_at IS NULL;

2. Format de la clé

ck_live_abc12345xyz67890...  (64 chars après préfixe)

La clé complète n'est affichée qu'une fois à la création. On stocke uniquement le hash.

3. Nouveaux endpoints

Méthode Endpoint Description
POST /api/auth/api-keys Créer une clé API
GET /api/auth/api-keys Lister mes clés (sans les valeurs)
DELETE /api/auth/api-keys/:id Révoquer une clé

4. Modification du middleware d'auth

Actuellement getUserFromRequest lit le JWT. On ajoute la détection de clé API :

// Header: X-API-Key: ck_live_abc123...
// ou
// Header: Authorization: Bearer ck_live_abc123...

async function getUserFromRequest(headers: Headers): Promise<string | null> {
  // 1. Essayer clé API
  const apiKey = headers.get('X-API-Key') || extractApiKeyFromBearer(headers);
  if (apiKey?.startsWith('ck_')) {
    const user = await validateApiKey(apiKey);
    if (user) return user.id;
  }

  // 2. Fallback JWT existant
  return getUserFromJwt(headers);
}

5. Scopes (permissions)

Scope Accès
* Tout (admin)
fetch /api/fetch uniquement
fetch:read Fetch GET uniquement
connectors:read Lister/voir connecteurs
connectors:write Créer/modifier connecteurs
instances:* Gérer ses instances
audit:read Voir les logs

Par défaut : ['fetch', 'connectors:read', 'instances:*', 'audit:read']

6. Utilisation

# Avec header X-API-Key
curl -X POST https://connectors.33800.nowhere84.com/api/fetch \
  -H "X-API-Key: ck_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"connector": "github", "method": "GET", "path": "/user"}'

# Ou avec Authorization Bearer
curl -X POST https://connectors.33800.nowhere84.com/api/fetch \
  -H "Authorization: Bearer ck_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"connector": "github", "method": "GET", "path": "/user"}'

7. Interface Front (optionnel)

Page /settings avec section "Clés API" :

Fichiers à modifier/créer

API (connectors-api)

  1. Migration SQL : Créer table api_keys
  2. src/services/apiKeys.ts : CRUD clés API
  3. src/middleware/jwt.ts : Ajouter détection clé API
  4. src/index.ts : Ajouter endpoints /api/auth/api-keys

Front (connectors-front) - Phase 2

  1. src/routes/settings/index.tsx : Section gestion clés

Avantages

Questions

  1. Expiration par défaut ? → Je propose : null (jamais) mais configurable à la création
  2. Limite de clés par user ? → Je propose : 10 max
  3. Rate limiting différent pour clés API ? → Pour l'instant non, même limites

Prêt à implémenter sur validation.