HMAC ověření
HMAC ověření je způsob, jakým FastOG zajišťuje, že každý požadavek na OG obrázek na základě předplatného přišel z vašeho vlastního serveru — podepsané URL chrání vaše kredity. Zaregistrujte se, poté zvolte tarif Dynamic API a vytvořte si svůj API klíč a HMAC tajemství v dashboardu; placené API rendery jsou čisté. Tato stránka pokrývá pravidla na straně serveru pro dynamické Open Graph obrázky, od kanonického podepisování dotazu až po porovnání v konstantním čase.
Přehled
Ověřování podpisu HMAC-SHA256 bylo přidáno ke koncovému bodu /api/v1/og, aby se zabránilo neoprávněnému využití API kvóty. Tím je zajištěno, že OG obrázky mohou generovat pouze požadavky z legitimního webu.
Architektura
Dvouvrstvá autentizace:
- HMAC podpis (první) – ověřuje, že požadavek pochází z důvěryhodného zdroje (webové stránky)
- API klíč (druhý) – identifikuje uživatelský účet pro účtování vykreslovací kvóty
Jediný middleware (ApiKeyAuth): ověřuje podpis (parametry dotazu) a v jednom průchodu vyřeší API klíč pro účtování vykreslovací kvóty – při chybném podpisu okamžitě selže.
Parametry dotazu, ne hlavičky: Protože OG obrázky načítají crawleři sociálních sítí (LinkedIn, Twitter, Facebook), kteří neposílají vlastní hlavičky, podpis se předává v parametrech URL dotazu:
GET /api/v1/og?title=Hello&key=sk_quick_123abc&s=<hmac>
Implementace
Vytvořené/změněné soubory
app/Http/Middleware/HmacSignature.php– Nový middleware pro ověřování HMAC podpisů (query parametry)routes/api.php– Přidán HMAC middleware do OG routybootstrap/app.php– Registrován alias middlewarehmacapp/Models/ApiKey.php– Přidáno polehmac_secret(tajemství pro jednotlivé uživatele)app/Http/Controllers/DashboardController.php– Generuje HMAC tajemství při vytvoření API klíčedatabase/migrations/2026_08_03_214931_add_hmac_secret_to_api_keys_table.php– Migrace pro sloupec hmac_secretresources/js/Pages/Dashboard/ApiKeys.svelte– Zobrazí HMAC tajemství uživateli (jednorázově)docs/hmac-signature-guide.md– Průvodce implementací pro klientatests/Feature/HmacSignatureTest.php– 8 procházejících testů
Algoritmus podpisu
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 je součástí kanonického dotazu, takže podpis je vázán na API klíč. Změna jakéhokoli parametru (title, template, image, …) nebo samotného klíče změní kanonický dotaz → neshoda podpisu → 401 → žádné vykreslení, žádné započítání kvóty. Identické parametry → identický podpis → identická URL → kešovatelná na hraně sítě navždy, přehrávaná bez započítávání.
Bezpečnostní funkce
- Podpis vázaný na obsah – Jakákoli změna parametru → 401 → žádné vykreslení, žádné započítání kvóty (samotná URL je důkazem)
- Žádné časové razítko – URL jsou vloženy do veřejného HTML a kešovány navždy; musí přežít déle než 5 minut
- Porovnání v konstantním čase (
hash_equals()) – Zabraňuje útokům založeným na měření času - API klíč ve zprávě – Podpis je vázán na klíč; výměna klíčů selže
- Specifické pro cestu – Podpis je platný pouze pro přesnou cestu
- Specifické pro metodu – Podpis pro GET nebude fungovat pro POST
- Tajemství pro jednotlivé uživatele – Každý API klíč má vlastní HMAC tajemství, které lze nezávisle zneplatnit (rotace = vypínač pro uniklé URL)
Konfigurace
Generování tajemství (automatické)
HMAC tajemství se automaticky vygeneruje při vytvoření API klíče v dashboardu. Zobrazí se jednou společně s API klíčem a poté už nikdy znovu.
Ruční generování (pokud je potřeba):
openssl rand -hex 32
Schéma databáze
ALTER TABLE api_keys ADD COLUMN hmac_secret VARCHAR(64)
COMMENT 'HMAC-SHA256 secret for signing OG image URLs (hex, 64 chars)';
Proměnné prostředí
Není potřeba žádná globální proměnná prostředí – tajemství se ukládají pro každého uživatele zvlášť do tabulky api_keys.
Příklad použití (backend webu)
// 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}" />
Chybové odpovědi
| Stav | Kód | Popis |
|---|---|---|
| 401 | missing_signature |
Chybí dotazovací parametr key nebo s |
| 401 | invalid_signature |
Podpis neodpovídá kanonickému dotazu (pozměněný nebo chybný tajný klíč) |
Testování
Spusťte testy:
php artisan test --filter HmacSignatureTest
Všech 8 testů projde:
- ✅ Požadavek bez podpisu je odmítnut
- ✅ Požadavek s chybějícím parametrem klíče je odmítnut
- ✅ Pozměněný parametr obsahu (změněný titulek) je odmítnut
- ✅ Přidaný parametr je odmítnut
- ✅ Neplatný podpis je odmítnut
- ✅ Platný podpis projde kontrolou HMAC
- ✅ Podpis je specifický pro cestu
- ✅ Podpis je specifický pro metodu
- ✅ Různé API klíče mají různá tajemství
Dopad na výkon
- Zanedbatelný – výpočet HMAC-SHA256 trvá přibližně 0,1 ms na požadavek
- Žádná další síťová volání – ověření probíhá lokálně
- Rychlé selhání – neplatné podpisy jsou odmítnuty před vyhledáním API klíče
Bezpečnostní aspekty
- Nikdy nevystavujte tajný klíč v kódu na straně klienta – podepisujte pouze na serveru
- Používejte HTTPS – HMAC chrání před neoprávněnými požadavky, HTTPS chrání před útoky typu MITM
- Pravidelně obměňujte tajné klíče – zejména pokud dojde k jejich kompromitaci (vyžaduje regeneraci API klíče)
- Sledujte neúspěšné podpisy – opakované selhání může naznačovat útok
- Izolace podle uživatelů – každý API klíč má vlastní HMAC tajemství, kompromitace jednoho neovlivní ostatní
Reference
- Průvodce podpisem HMAC pro klienty
- Průvodce rychlým startem
- OWASP: Cryptographic Storage Cheat Sheet
- PHP: hash_hmac()