Emne

HMAC-validering

HMAC-validering er hvordan FastOG bekrefter at hver abonnementsbasert OG-bildforespørsel kom fra din egen server — signerte URL-er holder kredittene dine trygge. Registrer deg, velg deretter en Dynamic API-plan og opprett API-nøkkelen og HMAC-hemmeligheten din i dashbordet; betalte API-renderinger er rene. Denne siden dekker server-sidereglene bak dynamiske Open Graph-bilder, fra kanonisk spørringsunderskriving til konstant-tid-sammenligning.

Oversikt

HMAC-SHA256-signaturvalidering er lagt til på /api/v1/og-endepunktet for å forhindre uautorisert bruk av API-kvoten. Dette sikrer at kun forespørsler fra den legitime nettsiden kan generere OG-bilder.

Arkitektur

Tolags autentisering:

  1. HMAC-signatur (først) – Validerer at forespørselen kommer fra en pålitelig kilde (nettstedet)
  2. API-nøkkel (andre) – Identifiserer brukerkontoen for kvoteregnskap for rendering

Én mellomvare (ApiKeyAuth): verifiserer signaturen (spørreparametere) og løser API-nøkkelen for kvoteregnskap for rendering i én omgang – feil raskt ved ugyldige signaturer.

Spørreparametere, ikke overskrifter: Siden OG-bilder hentes av crawlerne til sosiale nettverk (LinkedIn, Twitter, Facebook) som ikke sender egendefinerte overskrifter, sendes signaturen i URL-spørreparametere:

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

Implementasjon

Filer opprettet/endret

  • app/Http/Middleware/HmacSignature.php - Ny mellomvare (middleware) som validerer HMAC-signaturer (spørreparametere)
  • routes/api.php - La til HMAC-mellomvare på OG-ruten
  • bootstrap/app.php - Registrerte hmac-alias for mellomvaren
  • app/Models/ApiKey.php - La til hmac_secret-felt (hemmeligheter per bruker)
  • app/Http/Controllers/DashboardController.php - Genererer HMAC-hemmelighet ved opprettelse av API-nøkkel
  • database/migrations/2026_08_03_214931_add_hmac_secret_to_api_keys_table.php - Migrering for hmac_secret-kolonnen
  • resources/js/Pages/Dashboard/ApiKeys.svelte - Viser HMAC-hemmeligheten til brukeren (én gang)
  • docs/hmac-signature-guide.md - Veiledning for klientimplementasjon
  • tests/Feature/HmacSignatureTest.php - 8 beståtte tester

Signaturalgoritme

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 er en del av den kanoniske spørringen, så signaturen er bundet til API-nøkkelen. Endring av en hvilken som helst parameter (tittel, mal, bilde, …) eller selve nøkkelen fører til at den kanoniske strengen endres → signaturmismatch → 401 → ingen rendering, ingen kvotetelling. Identiske parametere → identisk signatur → identisk URL → kan bufres i kanten for alltid, og spilles av uten å telles.

Sikkerhetsfunksjoner

  • Innholdsadressert signatur - Enhver parameterendring → 401 → ingen rendering, ingen kvotetelling (URL-en er i seg selv beviset)
  • Ingen tidsstempel - URL-er er innebygd i offentlig HTML og bufret for alltid; de må overleve 5 minutter
  • Konstant-tid-sammenligning (hash_equals()) - Forhindrer tidsangrep (timing attacks)
  • API-nøkkel i meldingen - Signaturen er bundet til nøkkelen; bytting av nøkler feiler
  • Sti-spesifikk - Signaturen er kun gyldig for nøyaktig sti
  • Metode-spesifikk - GET-signatur fungerer ikke for POST
  • Hemmeligheter per bruker - Hver API-nøkkel har sin egen HMAC-hemmelighet, som kan tilbakekalles uavhengig (rotasjon = nødstopp for lekkede URL-er)

Konfigurasjon

Generer hemmelighet (automatisk)

HMAC-hemmeligheten genereres automatisk når du oppretter en API-nøkkel i dashbordet. Den vises én gang sammen med API-nøkkelen, og vises deretter aldri igjen.

Manuell generering (om nødvendig):

bash
openssl rand -hex 32

Databaseskjema

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

Miljøvariabler

Ingen global miljøvariabel er nødvendig – hemmeligheter lagres per bruker i api_keys-tabellen.

Brukseksempel (nettstedets 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}" />

Feilresponser

Status Kode Beskrivelse
401 missing_signature Mangler key- eller s-spørringsparameter
401 invalid_signature Signaturen samsvarer ikke med den kanoniske spørringen (manipulert eller feil hemmelighet)

Testing

Kjør testene:

bash
php artisan test --filter HmacSignatureTest

Alle 8 testene består:

  • ✅ Forespørsel uten signatur avvises
  • ✅ Forespørsel med manglende nøkkelparameter avvises
  • ✅ Endret innholdsparameter (tittel endret) avvises
  • ✅ Lagt til parameter avvises
  • ✅ Ugyldig signatur avvises
  • ✅ Gyldig signatur består HMAC-sjekken
  • ✅ Signatur er sti-spesifikk
  • ✅ Signatur er metode-spesifikk
  • ✅ Ulike API-nøkler har ulike hemmeligheter

Ytelsespåvirkning

  • Ubetydelig – HMAC-SHA256-beregning tar ~0,1 ms per forespørsel
  • Ingen ekstra nettverkskall – Validering skjer lokalt
  • Feiler raskt – Ugyldige signaturer avvises før API-nøkkeloppslag

Sikkerhetshensyn

  1. Aldri eksponer hemmeligheten i klientsidekode – signer kun på serveren
  2. Bruk HTTPS – HMAC beskytter mot uautoriserte forespørsler, HTTPS beskytter mot MITM
  3. Roter hemmeligheter jevnlig – spesielt ved kompromittering (krever regenerering av API-nøkkel)
  4. Overvåk mislykkede signaturer – gjentatte feil kan indikere angrep
  5. Per-bruker-isolering – hver API-nøkkel har sin egen HMAC-hemmelighet, kompromittering av én påvirker ikke de andre

Referanser

Full API-referanse

Prøv gratis – ingen registrering nødvendig

Forhåndsvis og test dynamiske OG-bilder på sekunder.

Åpne den gratis OG-bildetesteren

A BeCaSimulations site