Nel 2022 avevo pubblicato un articolo su come integrare Firebase Cloud Messaging (FCM) in un’app Delphi 11 per iOS, concentrandomi soprattutto sulla parte client-side e sulla configurazione iniziale delle push notification:
Da allora sono successe diverse cose, ma vale la pena chiarirlo subito:
lato app, tutto ciò che avevamo implementato continua a funzionare ed è rimasto sostanzialmente compatibile.
Embarcadero ha rilasciato nel tempo nuove versioni delle librerie Firebase per iOS e Android, migliorando l’integrazione e aggiornando gli SDK sottostanti, ma il modello concettuale lato client non è cambiato:
registrazione al servizio FCM
ottenimento del device token
ricezione delle notifiche (foreground/background)
gestione dei payload notification / data
Se hai un’app Delphi già in produzione che riceve correttamente le push, non sei obbligato a riscrivere nulla lato app.
Il cambiamento importante – e in molti casi obbligatorio – riguarda invece le API Google usate per inviare i messaggi.
Negli ultimi anni Google ha:
deprecato e poi dismesso le vecchie FCM Legacy HTTP API
introdotto le FCM HTTP v1 API, basate su:
OAuth2
Service Account
JWT firmati (RS256)
endpoint REST versionati
Questo significa che:
non è più possibile (o non lo sarà a breve) inviare push usando la classica Server Key
l’invio dei messaggi passa da un semplice header statico a un flusso di autenticazione strutturato
l’integrazione server-side va aggiornata, soprattutto se il backend è scritto in Delphi
In questo articolo vedremo quindi:
cosa cambia realmente passando da FCM Legacy a FCM HTTP v1
perché le app Delphi esistenti continuano a funzionare
come implementare correttamente l’invio delle push dal backend Delphi
come usare una service account Firebase in modo sicuro
e come sfruttare librerie esistenti (come Kastri) per evitare di reinventare OAuth2 e JW
Se lato app l’integrazione FCM è rimasta sostanzialmente compatibile con il pregresso, lato backend la storia è diversa: il cambio importante è l’evoluzione delle API di invio. Storicamente molti progetti Delphi (compreso il mio) hanno usato le Legacy HTTP API di FCM, basate su una semplice server key. Oggi invece la strada corretta è la FCM HTTP v1 API, che introduce un modello di autenticazione e autorizzazione molto più robusto.
Con le API legacy si inviavano notifiche verso l’endpoint:
POST https://fcm.googleapis.com/fcm/send
La v1 utilizza invece un endpoint versionato e legato esplicitamente al Project ID:
POST https://fcm.googleapis.com/v1/projects/<PROJECT_ID>/messages:send
Anche la struttura del payload cambia: in legacy era comune usare un campo come to (token o topic),
mentre in v1 si lavora con un oggetto message e campi più espliciti come token o topic.
In pratica il messaggio diventa più “strutturato” e meno ambiguo.
Il punto più critico del confronto è l’autenticazione.
Con legacy bastava aggiungere un header con una chiave statica (la server key):
Authorization: key=AAAA....
È comodo, ma ha un problema: la chiave è un “segreto unico” che spesso finisce in posti sbagliati (config non protetti, log, backup, repository privati ma condivisi, ecc.). Inoltre la chiave non è “contestuale”: chi la possiede può potenzialmente inviare notifiche a tutto ciò che è legato al progetto.
Con HTTP v1 il backend non usa più una chiave statica, ma ottiene un access token OAuth2 a partire da una Service Account (chiave privata) e un JWT firmato. L’invio poi avviene con:
Authorization: Bearer ya29....
Questo token:
Dal punto di vista sicurezza, HTTP v1 è semplicemente meglio per design:
Per chi sviluppa backend in Delphi, la migrazione è soprattutto una questione di “mattoni”:
/v1/projects/.../messages:sendQui entrano in gioco due componenti molto comodi:
DW.FCMSender:
implementa il flusso completo per FCM HTTP v1 (JWT + OAuth2 + invio) e costruisce anche payload coerenti per Android e APNs.
In altre parole: è possibile fare tutto “a mano” con Indy/OpenSSL, ma usare Kastri + DelphiOpenSsl fa risparmiare molto tempo, riduce la superficie di bug e ti porta più vicino a un’implementazione già testata in contesti reali.
TBearerToken).
Nel resto dell’articolo vedremo un esempio pratico con Delphi che invia una push a un singolo device tramite token, utilizzando Kastri (DW.FCMSender) e DelphiOpenSsl (Grijjy).
Con l’introduzione delle FCM HTTP v1 API, Google ha cambiato in modo sostanziale il modello di autenticazione per l’invio delle push notification. Il vecchio meccanismo basato su una server key statica è stato progressivamente dismesso in favore di un approccio più moderno e sicuro, basato su OAuth2 e Service Account.
In questo nuovo modello, il backend (nel nostro caso scritto in Delphi) non utilizza più una chiave “fissa” per autenticarsi verso Firebase, ma si identifica tramite una service account, ovvero un account tecnico associato direttamente al progetto Google/Firebase.
Una service account è un’identità server-to-server utilizzata dai servizi backend per autenticarsi verso le API Google. Non rappresenta un utente umano, ma un servizio o un’applicazione.
Nel contesto di Firebase Cloud Messaging:
In pratica, la service account è il nuovo “passaporto” ufficiale per parlare con Google quando si inviano notifiche push.
Il motivo principale è la sicurezza. Le vecchie server key erano:
Con OAuth2 e service account invece:
Questo approccio è oggi lo standard per tutte le API Google moderne, e FCM non fa eccezione.
firebase-service-account.jsonIl file JSON della service account si genera direttamente dalla Firebase Console (o Google Cloud Console) e va creato una sola volta.
A questo punto Firebase scaricherà un file con un nome simile a:
my-project-firebase-adminsdk-xxxx.json
Questo file è ciò che nel backend useremo come
firebase-service-account.json.
Il contenuto del file include informazioni sensibili, tra cui:
project_id – l’identificativo del progetto Firebaseclient_email – l’identità della service accountprivate_key – la chiave privata usata per firmare i JWTtoken_uri – l’endpoint OAuth2 di GoogleÈ importante sottolineare che:

Nel backend Delphi, la service account viene usata per:
Librerie come Kastri (tramite DW.FCMSender) e
DelphiOpenSsl (Grijjy) semplificano enormemente questo processo,
incapsulando tutta la complessità di JWT, OAuth2 e firma crittografica.
In questo modo il codice Delphi rimane pulito e leggibile, mentre l’autenticazione segue le best practice ufficiali di Google.
Concludiamo con un esempio concreto di invio di una push notification verso uno specifico dispositivo, utilizzando:
TFCMSender / TFCMMessage)In questo esempio la service account viene caricata direttamente da una stringa JSON (ad esempio letta da file, variabile d’ambiente o vault), e la notifica viene inviata a due device distinti tramite il loro FCM registration token.
uses DW.FCMSender;
.
.
.
.
.
procedure TForm6.Button1Click(Sender: TObject);
var
LSender: TFCMSender;
Msg: TFCMMessage;
Payload: string;
begin
// Istanza del sender FCM (gestisce OAuth2, JWT e invio HTTP v1)
LSender := TFCMSender.Create;
try
// Caricamento della service account da JSON (stringa)
// Alternativa: LoadServiceAccount('path/file.json')
if not LSender.ServiceAccount.Parse(c_service_account_xtumble) then
raise Exception.Create('Service account JSON non valido');
// Creazione del messaggio FCM
Msg := TFCMMessage.Create;
try
// Titolo e corpo della notifica
Msg.Title := edTitle.Text;
Msg.Body := edBody.Text;
// Dati aggiuntivi (DEVONO essere JSON con sole stringhe)
// Verranno recapitati nel payload "data" dell’app
Msg.Data := Format(
'{"message_id":"%s","type":"shipment"}',
['xtumble']
);
// Costruzione del payload per il primo device (token specifico)
Payload := Msg.GetTokenPayload(device_token_simo);
// Invio della notifica
if LSender.Post(Payload) then
begin
// Push inviata correttamente al primo device
end;
// Invio della stessa notifica a un secondo device
Payload := Msg.GetTokenPayload(device_token_ivan);
if LSender.Post(Payload) then
begin
// Push inviata correttamente al secondo device
end;
finally
Msg.Free;
end;
finally
LSender.Free;
end;
end;
Dietro poche righe di codice, TFCMSender esegue automaticamente:
Il token FCM passato a GetTokenPayload determina in modo univoco
il destinatario della notifica: anche se il progetto Firebase contiene più
app (iOS / Android), il messaggio verrà recapitato solo a quel dispositivo.
Questo approccio rappresenta il modo moderno e consigliato per integrare Firebase Cloud Messaging in un backend Delphi:
Una volta impostata correttamente la service account, l’invio delle push diventa un dettaglio implementativo, permettendo di concentrarsi sulla logica applicativa (eventi, workflow, notifiche mirate).