Shopify · Webhook · GDPR
Webhook di conformità GDPR per le app Shopify (HMAC e mandatory webho…
Ogni app pubblicata sullo Shopify App Store deve gestire i webhook di conformità GDPR. Non è facoltativo: il revisore automatico di Shopify invia proprio questi webhook e, se l'app non li gestisce o sbaglia la verifica della firma, la pubblicazione viene rifiutata. È lo stesso tipo di problema "piccolo ma bloccante" del webhook di cancellazione account di eBay: un endpoint obbligatorio che va implementato bene una volta sola.
I tre webhook obbligatori
| Topic | Quando arriva | Cosa devi fare |
|---|---|---|
| customers/data_request | Un cliente richiede i propri dati | Raccogliere e fornire i dati personali che l'app conserva |
| customers/redact | Va cancellato un cliente | Eliminare/anonimizzare i dati personali di quel cliente |
| shop/redact | 48 ore dopo la disinstallazione | Eliminare tutti i dati del negozio |
Tutte le app distribuite tramite lo store devono rispondere a queste richieste, anche se non raccolgono dati personali.
Verificare la firma HMAC sul body grezzo
Ogni webhook include l'header X-Shopify-Hmac-Sha256: un HMAC-SHA256 in base64 calcolato da Shopify con il client secret dell'app sul corpo della richiesta. Devi ricalcolarlo e confrontarlo. Il punto critico: l'HMAC va calcolato sul body grezzo (Buffer), non sull'oggetto JSON già parsato. Un middleware come express.json() rompe la verifica perché altera i byte.
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
const received = req.get('X-Shopify-Hmac-Sha256');
const digest = crypto
.createHmac('sha256', process.env.SHOPIFY_API_SECRET)
.update(req.body) // Buffer: il body grezzo, non l'oggetto parsato
.digest('base64');
// confronto a tempo costante per evitare timing attack
const ok = crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(received));
if (!ok) return res.status(401).send('Unauthorized');
// gestisci customers/data_request, customers/redact, shop/redact
return res.status(200).send('OK');
});
Cosa rispondere e in quanto tempo
- firma valida: rispondi
200rapidamente, poi processa in modo asincrono; - firma non valida o shop sconosciuto: rispondi
401e non fare nulla; customers/data_request: hai l'obbligo di fornire i dati (in genere entro 30 giorni), non necessariamente in tempo reale nella risposta;shop/redact: arriva circa 48 ore dopo la disinstallazione, quindi prevedi un percorso di cancellazione differita.
Registrare i webhook
Per le app pubbliche il modo raccomandato è dichiarare i topic di conformità nel file shopify.app.toml (gestiti via Shopify CLI), puntandoli a un unico endpoint che li distingue dal campo topic. Evita registrazioni manuali divergenti tra ambienti.
Conservare il client secret in sicurezza
L'intera verifica dipende dal client secret: se finisce in chiaro nel codice o nei log, la firma non protegge più nulla. Conservalo in un secret manager e iniettalo a runtime, come descritto nella guida su come proteggere segreti e credenziali con Azure Key Vault. Se l'app fa anche sincronizzazione di catalogo e ordini, vale la pena leggere come strutturare l'integrazione tra Shopify e l'ERP.
Errori comuni
- calcolare l'HMAC sul JSON parsato invece che sul body grezzo;
- gestire solo i webhook di business e ignorare i topic GDPR (il check di Shopify fallisce);
- confronto non a tempo costante (vulnerabile a timing attack);
- processare in modo sincrono e andare in timeout invece di rispondere subito 200 e accodare.
Conclusione
I webhook di conformità sono un requisito a basso volume ma ad alto impatto: o sono corretti, o l'app non passa la review. La ricetta è semplice: verifica l'HMAC sul body grezzo, rispondi 200/401, accoda l'elaborazione e proteggi il client secret. Riferimenti: Privacy law compliance (Shopify) e consegna dei webhook via HTTPS.