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:
- HMAC-signatur (først) – Validerer at forespørselen kommer fra en pålitelig kilde (nettstedet)
- 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-rutenbootstrap/app.php- Registrertehmac-alias for mellomvarenapp/Models/ApiKey.php- La tilhmac_secret-felt (hemmeligheter per bruker)app/Http/Controllers/DashboardController.php- Genererer HMAC-hemmelighet ved opprettelse av API-nøkkeldatabase/migrations/2026_08_03_214931_add_hmac_secret_to_api_keys_table.php- Migrering for hmac_secret-kolonnenresources/js/Pages/Dashboard/ApiKeys.svelte- Viser HMAC-hemmeligheten til brukeren (én gang)docs/hmac-signature-guide.md- Veiledning for klientimplementasjontests/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):
openssl rand -hex 32
Databaseskjema
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)
// 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:
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
- Aldri eksponer hemmeligheten i klientsidekode – signer kun på serveren
- Bruk HTTPS – HMAC beskytter mot uautoriserte forespørsler, HTTPS beskytter mot MITM
- Roter hemmeligheter jevnlig – spesielt ved kompromittering (krever regenerering av API-nøkkel)
- Overvåk mislykkede signaturer – gjentatte feil kan indikere angrep
- Per-bruker-isolering – hver API-nøkkel har sin egen HMAC-hemmelighet, kompromittering av én påvirker ikke de andre
Referanser
- HMAC-signaturveiledning for klienter
- Hurtigstartguide
- OWASP: Jukselapp for kryptografisk lagring
- PHP: hash_hmac()