Novità È disponibile GajaCms 2026.9 — MCP e pannello di approvazione delle proposte AI. Leggi il changelog
Guida di GajaCms Guida di GajaCms
FONDAMENTI

Autenticazione delle richieste

Ogni richiesta all'API è firmata. La firma dimostra il possesso del segreto del sito senza trasmetterlo e vincola la richiesta all'istante in cui è stata prodotta.

Gli header richiesti

Header

Contenuto

WebsiteId

Identificativo del sito, in formato GUID

WebSecretId

Identificativo pubblico della chiave associata al sito

X-Timestamp

Istante della richiesta, in secondi Unix UTC

X-Website-Auth

Firma della richiesta, in Base64

WebsiteId e WebSecretId si leggono nel pannello, nelle impostazioni del sito. Il segreto usato per firmare non compare in nessun header e non lascia il server chiamante.

Come si calcola la firma

Il messaggio da firmare è la concatenazione dell'identificativo della chiave e del timestamp, separati da una barra verticale: {webSecretId}|{timestamp}.

Il messaggio viene sottoposto a HMAC-SHA256 usando il segreto del sito come chiave, entrambi codificati in UTF-8. Il risultato binario si trasmette in Base64 nell'header X-Website-Auth.

Lo stesso timestamp usato nel calcolo va inviato in X-Timestamp: un timestamp diverso da quello firmato produce una firma non valida.

import crypto from "node:crypto";

const websiteId = "00000000-0000-0000-0000-000000000000";
const webSecretId = "IDENTIFICATIVO_CHIAVE";
const secretKey = process.env.GAJACMS_SECRET;

const timestamp = Math.floor(Date.now() / 1000);
const signature = crypto
  .createHmac("sha256", secretKey)
  .update(`${webSecretId}|${timestamp}`, "utf8")
  .digest("base64");

const response = await fetch("https://esempio.it/api/v1/content/pages/resolve", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "WebsiteId": websiteId,
    "WebSecretId": webSecretId,
    "X-Timestamp": String(timestamp),
    "X-Website-Auth": signature
  },
  body: JSON.stringify({ requestedUrl: "/chi-siamo" })
});

Finestra di validità

La differenza fra il timestamp inviato e l'ora del server non può superare i 120 secondi, in anticipo o in ritardo. Oltre quella soglia la richiesta viene rifiutata anche con una firma corretta.

La firma va quindi calcolata a ogni richiesta e non può essere memorizzata e riutilizzata. L'orologio del sistema chiamante deve essere sincronizzato.

Esito del controllo

Il controllo avviene prima di qualunque logica applicativa. Quando fallisce, la risposta è 403 con corpo di testo Forbidden: non è un JSON e non adotta il wrapper descritto nella pagina Formato delle risposte.

Le cause del rifiuto sono:

  • uno degli header richiesti è assente;

  • WebsiteId non è un GUID valido;

  • X-Timestamp non è un numero intero;

  • la differenza dall'ora del server supera i 120 secondi;

  • WebSecretId non corrisponde a nessuna chiave registrata;

  • la firma non coincide con quella calcolata dal server.