Thema

HMAC-Validierung

Die HMAC-Validierung ist die Methode, mit der FastOG überprüft, dass jede abonnementbasierte OG-Bildanfrage von Ihrem eigenen Server stammt – signierte URLs schützen Ihre Credits. Registrieren Sie sich, wählen Sie dann einen Dynamic-API-Plan und erstellen Sie Ihren API-Schlüssel sowie Ihr HMAC-Geheimnis im Dashboard; kostenpflichtige API-Renderings sind sauber. Diese Seite behandelt die serverseitigen Regeln hinter dynamischen Open-Graph-Bildern, von der kanonischen Query-Signierung bis zum Vergleich in konstanter Zeit.

Übersicht

Die Validierung der HMAC-SHA256-Signatur wurde zum /api/v1/og-Endpunkt hinzugefügt, um eine unbefugte Nutzung des API-Kontingents zu verhindern. Dadurch wird sichergestellt, dass nur Anfragen von der legitimen Website OG-Bilder generieren können.

Architektur

Zweistufige Authentifizierung:

  1. HMAC-Signatur (zuerst) – Bestätigt, dass die Anfrage von einer vertrauenswürdigen Quelle (der Website) stammt
  2. API-Schlüssel (danach) – Identifiziert das Benutzerkonto für die Abrechnung des Render-Kontingents

Ein einzelnes Middleware-Modul (ApiKeyAuth): überprüft die Signatur (Query-Parameter) und löst den API-Schlüssel für die Abrechnung des Render-Kontingents in einem Durchgang auf – bei ungültigen Signaturen erfolgt ein schneller Abbruch (Fail Fast).

Query-Parameter statt Header: Da OG-Bilder von Social-Media-Crawlern (LinkedIn, Twitter, Facebook) abgerufen werden, die keine benutzerdefinierten Header senden, wird die Signatur in den URL-Query-Parametern übergeben:

GET /api/v1/og?title=Hello&key=sk_quick_123abc&s=<hmac>

Implementierung

Erstellte/Geänderte Dateien

  • app/Http/Middleware/HmacSignature.php – Neue Middleware zur Validierung von HMAC-Signaturen (Query-Parameter)
  • routes/api.php – HMAC-Middleware zur OG-Route hinzugefügt
  • bootstrap/app.php – hmac-Middleware-Alias registriert
  • app/Models/ApiKey.php – hmac_secret-Feld hinzugefügt (Geheimnisse pro Benutzer)
  • app/Http/Controllers/DashboardController.php – Generiert HMAC-Geheimnis bei Erstellung des API-Schlüssels
  • database/migrations/2026_08_03_214931_add_hmac_secret_to_api_keys_table.php – Migration für die hmac_secret-Spalte
  • resources/js/Pages/Dashboard/ApiKeys.svelte – Zeigt HMAC-Geheimnis dem Benutzer an (einmalig)
  • docs/hmac-signature-guide.md – Leitfaden zur Client-Implementierung
  • tests/Feature/HmacSignatureTest.php – 8 erfolgreiche Tests

Signaturalgorithmus

method = HTTP method (e.g., "GET")
path  = request path (e.g., "/api/v1/og")
query = the request's DECODED query params

canonical = every param except `s`, keys sorted (array values sorted too),
            each `key=value` RFC-3986 encoded (unreserved-only), joined with "&"
message   = method + "/" + path + "\n" + canonical
signature = HMAC-SHA256(message, hmac_secret)

Query parameters:
  key=<apiKey>
  s=<signature>
  (no timestamp)

key ist Teil der kanonischen Query, sodass die Signatur an den API-Schlüssel gebunden ist. Das Ändern eines beliebigen Parameters (Titel, Vorlage, Bild usw.) oder des Schlüssels selbst ändert die kanonische Query → Signatur stimmt nicht überein → 401 → kein Rendering, keine Quota-Zählung. Identische Parameter → identische Signatur → identische URL → dauerhaft am Edge cachebar, ohne erneute Zählung bei Wiederholung.

Sicherheitsfunktionen

  • Inhaltsadressierte Signatur – Jede Parameteränderung → 401 → kein Rendering, keine Quota-Zählung (die URL selbst ist der Nachweis)
  • Kein Zeitstempel – URLs werden in öffentlichem HTML eingebettet und dauerhaft gecacht; sie müssen länger als 5 Minuten gültig bleiben
  • Konstantzeit-Vergleich (hash_equals()) – Verhindert Timing-Angriffe
  • API-Schlüssel in der Nachricht – Die Signatur ist an den Schlüssel gebunden; das Austauschen von Schlüsseln schlägt fehl
  • Pfadspezifisch – Die Signatur ist nur für den exakten Pfad gültig
  • Methodenspezifisch – Eine GET-Signatur funktioniert nicht für POST
  • Geheimnisse pro Benutzer – Jeder API-Schlüssel hat sein eigenes HMAC-Geheimnis und kann unabhängig widerrufen werden (Rotation = Kill-Switch für geleakte URLs)

Konfiguration

Geheimschlüssel generieren (automatisch)

Der HMAC-Geheimschlüssel wird automatisch generiert, wenn Sie einen API-Schlüssel im Dashboard erstellen. Er wird einmalig zusammen mit dem API-Schlüssel angezeigt und danach nie wieder.

Manuelle Generierung (falls erforderlich):

bash
openssl rand -hex 32

Datenbankschema

sql
ALTER TABLE api_keys ADD COLUMN hmac_secret VARCHAR(64)
  COMMENT 'HMAC-SHA256 secret for signing OG image URLs (hex, 64 chars)';

Umgebungsvariablen

Keine globale Umgebungsvariable erforderlich – Geheimschlüssel werden pro Benutzer in der api_keys-Tabelle gespeichert.

Verwendungsbeispiel (Website-Backend)

javascript
// Node.js example - generate signed OG image URL
const crypto = require("crypto");

// RFC-3986 encode (encodeURIComponent leaves !'()* unencoded).
const enc = (s) =>
    encodeURIComponent(s).replace(
        /[!'()*]/g,
        (c) => "%" + c.charCodeAt(0).toString(16).toUpperCase(),
    );

function generateOgImageUrl(baseUrl, params, apiKey, hmacSecret) {
    const all = { ...params, key: apiKey };

    // Canonical: every param (except s), sorted, RFC-3986 encoded, joined with "&".
    const pairs = [];
    for (const [k, v] of Object.entries(all)) {
        for (const vv of Array.isArray(v) ? [...v].sort() : [v])
            pairs.push(`${enc(k)}=${enc(vv)}`);
    }
    pairs.sort();
    const canonical = pairs.join("&");

    const message = `GET/api/v1/og\n${canonical}`;
    const signature = crypto
        .createHmac("sha256", hmacSecret)
        .update(message)
        .digest("hex");

    const url = new URL(baseUrl);
    for (const [k, v] of Object.entries(all)) {
        const isArray = Array.isArray(v);
        for (const vv of isArray ? v : [v])
            url.searchParams.append(isArray ? `${k}[]` : k, vv);
    }
    url.searchParams.set("s", signature);
    return url.toString();
}

// Usage in meta tag
const ogUrl = generateOgImageUrl(
    "https://fastog.com/api/v1/og",
    { title: "Como criar um SaaS", template: "blog" },
    "sk_quick_123abc",
    process.env.HMAC_SECRET,
);

// <meta property="og:image" content="{ogUrl}" />

Fehlerantworten

Status Code Beschreibung
401 missing_signature Fehlender key- oder s-Abfrageparameter
401 invalid_signature Signatur stimmt nicht mit der kanonischen Abfrage überein (manipuliert oder falsches Secret)

Testen

Tests ausführen:

bash
php artisan test --filter HmacSignatureTest

Alle 8 Tests bestehen:

  • ✅ Anfrage ohne Signatur wird abgelehnt
  • ✅ Anfrage mit fehlendem Schlüsselparameter wird abgelehnt
  • ✅ Manipulierter Inhaltsparameter (Titel geändert) wird abgelehnt
  • ✅ Hinzugefügter Parameter wird abgelehnt
  • ✅ Ungültige Signatur wird abgelehnt
  • ✅ Gültige Signatur besteht die HMAC-Prüfung
  • ✅ Signatur ist pfadspezifisch
  • ✅ Signatur ist methodspezifisch
  • ✅ Verschiedene API-Schlüssel haben unterschiedliche Geheimnisse

Auswirkungen auf die Leistung

  • Vernachlässigbar – Die HMAC-SHA256-Berechnung dauert etwa 0,1 ms pro Anfrage
  • Keine zusätzlichen Netzwerkaufrufe – Die Validierung erfolgt lokal
  • Schnelles Scheitern – Ungültige Signaturen werden abgelehnt, bevor die API-Schlüsselsuche erfolgt

Sicherheitshinweise

  1. Geben Sie das Geheimnis niemals im clientseitigen Code preis – Signieren Sie ausschließlich auf dem Server
  2. Verwenden Sie HTTPS – HMAC schützt vor unbefugten Anfragen, HTTPS schützt vor Man-in-the-Middle-Angriffen
  3. Rotieren Sie Geheimnisse regelmäßig – Insbesondere bei Kompromittierung (erfordert die Neugenerierung des API-Schlüssels)
  4. Überwachen Sie fehlgeschlagene Signaturen – Wiederholte Fehlschläge können auf Angriffe hindeuten
  5. Isolation pro Benutzer – Jeder API-Schlüssel besitzt sein eigenes HMAC-Geheimnis; die Kompromittierung eines Schlüssels hat keine Auswirkungen auf andere

Referenzen

Vollständige API-Referenz

Kostenlos testen – keine Anmeldung erforderlich

Vorschau und Test dynamischer OG-Bilder in Sekunden.

Kostenlosen OG-Bild-Tester öffnen

A BeCaSimulations site