Filtri Menu 0 0.00

Delphi + Firebase Cloud Messaging nel 2026: cosa è cambiato davvero

Delphi + Firebase Cloud Messaging nel 2026: cosa è cambiato davvero

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:

👉 https://synaptica.info/2022/03/24/delphi-11-firebase-cloud-messaging-fcm-ios-app-push-notification-1/

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.


La vera novità: cambia tutto lato server

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


Obiettivo di questo articolo

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

FCM Legacy vs FCM HTTP v1: cosa cambia davvero (e perché è più sicuro)

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.

1) Endpoint e formato payload

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.

2) Autenticazione: da “chiave statica” a OAuth2 (JWT + Service Account)

Il punto più critico del confronto è l’autenticazione.

Legacy: Server Key (statica)

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.

HTTP v1: Bearer Token OAuth2 (generato e a scadenza)

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:

  • ha una scadenza breve (tipicamente ~1 ora)
  • è revocabile e ruotabile più facilmente
  • non è una chiave “eterna” che rimane valida fino a quando qualcuno non se ne accorge
  • è ottenuto tramite un flusso standard (OAuth2) controllato da Google

3) Sicurezza: perché HTTP v1 è un salto di qualità

Dal punto di vista sicurezza, HTTP v1 è semplicemente meglio per design:

  • Riduce l’impatto di un leak: se un token OAuth2 finisce in un log o in un dump, scade in breve tempo. Una server key legacy invece rimane valida fino a rotazione manuale (che spesso non avviene mai).
  • Allinea l’invio push a IAM e policy di progetto: usando service account e OAuth2, si entra nel paradigma Google Cloud, dove i permessi possono essere gestiti in modo più rigoroso.
  • Separazione netta tra client e server: la service account e la chiave privata devono stare solo sul backend; l’app non deve sapere nulla (e non deve mai includere segreti).
  • Best practice di auditing: è più naturale impostare log e controlli su token generation, rotazioni e permessi, invece di affidarsi a una singola chiave statica.

4) Impatto pratico su un backend Delphi

Per chi sviluppa backend in Delphi, la migrazione è soprattutto una questione di “mattoni”:

  • Generazione JWT (RS256)
  • Scambio JWT → access token (OAuth2 token endpoint)
  • POST verso /v1/projects/.../messages:send
  • Gestione cache del token (per evitare di rigenerarlo ad ogni invio)

Qui entrano in gioco due componenti molto comodi:

  • Kastri (Delphi Worlds) con DW.FCMSender: implementa il flusso completo per FCM HTTP v1 (JWT + OAuth2 + invio) e costruisce anche payload coerenti per Android e APNs.
  • DelphiOpenSsl (Grijjy): usato da Kastri per la parte di firma RSA/SHA256 (RS256) tramite OpenSSL, evitando di dover scrivere crittografia a mano.

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.

5) Best practice operative (consigli rapidi)

  • Non mettere mai la service account JSON nel repository o nell’app: deve vivere solo sul server (permessi file restrittivi).
  • Cache dell’access token: genera il token solo quando serve e riusalo fino a scadenza (Kastri lo gestisce tramite TBearerToken).
  • Rotazione chiavi: se hai policy aziendali, ruota periodicamente la key della service account e aggiorna il backend.
  • Topic vs token: usa i topic per broadcast (es. “low stock” per magazzino) e i token per notifiche transazionali (es. “merce spedita” per utente).

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).

Service Account Firebase: cos’è e perché è diventato fondamentale

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.

Cos’è una Service Account

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:

  • la service account identifica il backend autorizzato a inviare push
  • è legata al progetto Firebase (non alla singola app iOS/Android)
  • consente di ottenere access token OAuth2 temporanei
  • abilita l’uso delle API FCM HTTP v1

In pratica, la service account è il nuovo “passaporto” ufficiale per parlare con Google quando si inviano notifiche push.

Perché Google ha introdotto questo meccanismo

Il motivo principale è la sicurezza. Le vecchie server key erano:

  • statiche
  • spesso riutilizzate per anni
  • difficili da controllare in caso di leak

Con OAuth2 e service account invece:

  • i token hanno una scadenza breve
  • le chiavi private restano solo sul server
  • l’accesso è integrato con il modello IAM di Google Cloud
  • la superficie di attacco si riduce drasticamente

Questo approccio è oggi lo standard per tutte le API Google moderne, e FCM non fa eccezione.

Come ottenere il file firebase-service-account.json

Il file JSON della service account si genera direttamente dalla Firebase Console (o Google Cloud Console) e va creato una sola volta.

  1. Apri la Firebase Console e seleziona il progetto corretto
  2. Clicca sull’icona dell’ingranaggio (Impostazioni progetto)
  3. Apri la sezione Service accounts
  4. Vai alla scheda Firebase Admin SDK
  5. Clicca su Generate new private key
  6. Conferma e scarica il file JSON

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.

Cosa contiene il file JSON

Il contenuto del file include informazioni sensibili, tra cui:

  • project_id – l’identificativo del progetto Firebase
  • client_email – l’identità della service account
  • private_key – la chiave privata usata per firmare i JWT
  • token_uri – l’endpoint OAuth2 di Google

È importante sottolineare che:

  • questo file non deve mai essere incluso nell’app
  • non deve finire nel repository Git
  • deve vivere solo sul backend, con permessi file restrittivi


Come viene usata dal backend Delphi

Nel backend Delphi, la service account viene usata per:

  • generare un JWT firmato (RS256)
  • scambiarlo con un access token OAuth2
  • inviare richieste autenticate alle API FCM HTTP v1

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.





Esempio pratico: inviare una push a uno specifico device con Delphi

Concludiamo con un esempio concreto di invio di una push notification verso uno specifico dispositivo, utilizzando:

  • Delphi come backend
  • Kastri (TFCMSender / TFCMMessage)
  • Firebase Cloud Messaging HTTP v1
  • autenticazione tramite Service Account

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;
  

Cosa succede dietro le quinte

Dietro poche righe di codice, TFCMSender esegue automaticamente:

  • la generazione di un JWT firmato (RS256)
  • lo scambio JWT → access token OAuth2
  • la cache del token fino alla scadenza
  • la chiamata alle API FCM HTTP v1

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.

Considerazioni finali

Questo approccio rappresenta il modo moderno e consigliato per integrare Firebase Cloud Messaging in un backend Delphi:

  • niente chiavi statiche legacy
  • autenticazione OAuth2 standard Google
  • massima compatibilità con i client esistenti
  • codice pulito e manutenibile

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).

Condividi:

Iscriviti alla newsletter

Iscriviti alla nostra newsletter per ricevere offerte di sconto anticipate, aggiornamenti e informazioni sui nuovi prodotti.
Top