Aihe

HMAC-validointi

HMAC-validointi on tapa, jolla FastOG varmistaa, että jokainen tilauspohjainen OG-kuvapyyntö on peräisin omalta palvelimeltasi — allekirjoitetut URL-osoitteet pitävät krediittisi turvassa. Rekisteröidy, valitse Dynamic API -suunnitelma ja luo API-avaimesi sekä HMAC-salaisuutesi hallintapaneelissa (dashboard); maksulliset API-renderöinnit ovat puhtaita. Tämä sivu kattaa palvelinpuolen säännöt dynaamisten Open Graph -kuvien takana, kanonisesta kyselymerkkien allekirjoituksesta vakioaikaiseen vertailuun.

Yleiskatsaus

HMAC-SHA256-allekirjoituksen vahvistus on lisätty /api/v1/og-päätepisteeseen estämään API-kiintiön luvaton käyttö. Tämä varmistaa, että vain oikean verkkosivuston pyynnöt voivat luoda OG-kuvia.

Arkkitehtuuri

Kaksitasoinen todennus:

  1. HMAC-allekirjoitus (ensimmäinen) – varmistaa, että pyyntö on peräisin luotetusta lähteestä (verkkosivusto)
  2. API-avain (toinen) – tunnistaa käyttäjätilin renderöintikiintiön laskentaa varten

Yksi middleware (ApiKeyAuth): varmistaa allekirjoituksen (kyselyparametrit) ja selvittää API-avaimen renderöintikiintiön laskentaa varten yhdellä kertaa – epäonnistu nopeasti virheellisillä allekirjoituksilla.

Kyselyparametrit, ei otsikot: Koska sosiaalisten verkostojen hakurobotit (LinkedIn, Twitter, Facebook) hakevat OG-kuvia eivätkä lähetä mukautettuja otsikoita, allekirjoitus välitetään URL-kyselyparametreissa:

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

Toteutus

Luodut/muokatut tiedostot

  • app/Http/Middleware/HmacSignature.php - Uusi middleware, joka validoi HMAC-allekirjoitukset (kyselyparametrit)
  • routes/api.php - Lisätty HMAC-middleware OG-reitille
  • bootstrap/app.php - Rekisteröity hmac-middleware-alias
  • app/Models/ApiKey.php - Lisätty hmac_secret-kenttä (käyttäjäkohtaiset salaisuudet)
  • app/Http/Controllers/DashboardController.php - Luo HMAC-salaisuuden API-avaimen luonnin yhteydessä
  • database/migrations/2026_08_03_214931_add_hmac_secret_to_api_keys_table.php - Migraatio hmac_secret-sarakkeelle
  • resources/js/Pages/Dashboard/ApiKeys.svelte - Näyttää HMAC-salaisuuden käyttäjälle (kerran)
  • docs/hmac-signature-guide.md - Asiakasohje toteutukseen
  • tests/Feature/HmacSignatureTest.php - 8 läpäisevää testiä

Allekirjoitusalgoritmi

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 on osa kanonista kyselyä, joten allekirjoitus on sidottu API-avaimeen. Minkä tahansa parametrin (otsikko, malli, kuva jne.) tai itse avaimen muuttaminen muuttaa kanonista merkkijonoa → allekirjoitus ei täsmää → 401 → ei renderöintiä, ei kiintiön kulutusta. Samat parametrit → sama allekirjoitus → sama URL → välimuistitettavissa reunalla pysyvästi, toistettavissa ilman laskutusta.

Tietoturvaominaisuudet

  • Sisältöosoitteinen allekirjoitus - Mikä tahansa parametrimuutos → 401 → ei renderöintiä, ei kiintiön kulutusta (URL itsessään on todiste)
  • Ei aikaleimaa - URLit upotetaan julkiseen HTML:ään ja välimuistitetaan pysyvästi; niiden on kestettävä yli 5 minuuttia
  • Vakioaikainen vertailu (hash_equals()) - Estää ajoituspohjaiset hyökkäykset
  • API-avain viestissä - Allekirjoitus on sidottu avaimeen; avaimen vaihto epäonnistuu
  • Polkukohtainen - Allekirjoitus on voimassa vain tarkalle polulle
  • Metodikohtainen - GET-allekirjoitus ei toimi POST-pyynnöissä
  • Käyttäjäkohtaiset salaisuudet - Jokaisella API-avaimella on oma HMAC-salaisuutensa, joka voidaan peruuttaa itsenäisesti (kierto = hätäkatkaisin vuotaneille URLeille)

Konfiguraatio

Salaisen avaimen luominen (automaattinen)

HMAC-salainen avain luodaan automaattisesti, kun luot API-avaimen hallintapaneelissa (dashboard). Se näytetään kerran API-avaimen yhteydessä, eikä sitä näytetä sen jälkeen uudelleen.

Manuaalinen luominen (tarvittaessa):

bash
openssl rand -hex 32

Tietokannan rakenne

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

Ympäristömuuttujat

Globaalia ympäristömuuttujaa ei tarvita – salaiset avaimet tallennetaan käyttäjäkohtaisesti api_keys-tauluun.

Käyttöesimerkki (verkkosivuston taustajärjestelmä)

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}" />

Virhevastaukset

Tila Koodi Kuvaus
401 missing_signature Puuttuva key- tai s-kyselyparametri
401 invalid_signature Allekirjoitus ei vastaa kanonista kyselyä (muokattu tai väärä salaisuus)

Testaaminen

Suorita testit:

bash
php artisan test --filter HmacSignatureTest

Kaikki 8 testiä menevät läpi:

  • ✅ Pyyntö ilman allekirjoitusta hylätään
  • ✅ Pyyntö, josta puuttuu avainparametri, hylätään
  • ✅ Muokattu sisältöparametri (otsikko muutettu) hylätään
  • ✅ Lisätty parametri hylätään
  • ✅ Virheellinen allekirjoitus hylätään
  • ✅ Kelvollinen allekirjoitus läpäisee HMAC-tarkistuksen
  • ✅ Allekirjoitus on polkukohtainen
  • ✅ Allekirjoitus on metodikohtainen
  • ✅ Eri API-avaimilla on eri salaisuudet

Suorituskykyvaikutus

  • Vähäinen – HMAC-SHA256-laskenta vie noin 0,1 ms pyyntöä kohden
  • Ei ylimääräisiä verkkokutsuja – vahvistus tapahtuu paikallisesti
  • Epäonnistuu nopeasti – virheelliset allekirjoitukset hylätään ennen API-avaimen hakua

Tietoturvanäkökohdat

  1. Älä koskaan paljasta salaista avainta asiakaspuolen koodissa – Allekirjoita vain palvelimella
  2. Käytä HTTPS:ää – HMAC suojaa luvattomilta pyynnöiltä, HTTPS suojaa MITM-hyökkäyksiltä
  3. Vaihda salaiset avaimet säännöllisesti – Erityisesti jos ne ovat vaarantuneet (edellyttää API-avaimen uudelleengenerointia)
  4. Seuraa epäonnistuneita allekirjoituksia – Toistuvat epäonnistumiset voivat viitata hyökkäyksiin
  5. Käyttäjäkohtainen eristys – Jokaisella API-avaimella on oma HMAC-salaisuutensa, yhden vaarantuminen ei vaikuta muihin

Viitteet

Täydellinen API-viite

Kokeile ilmaiseksi — ei vaadi rekisteröitymistä

Esikatsele ja testaa dynaamisia OG-kuvia sekunneissa.

Avaa ilmainen OG-kuvien testaaja

A BeCaSimulations site