Skip to content

OAuth2 per i connettori ​

Non è un connettore: è l'identità che IMAP e SMTP usano per autenticarsi dove la password non basta più — Gmail, Google Workspace, Microsoft 365. Lo usa anche il connettore Zoho CRM, che autentica ogni richiesta alla Records API con il token che questa identità rinnova. Procedura passo passo nel runbook oauth-google-posta.md.

Perché esiste ​

I connettori sapevano già parlare XOAUTH2, ma un access token vive un'ora: incollarne uno in IMAP_ACCESS_TOKEN è una configurazione che funziona per un'ora e poi torna rossa. Questo modulo tiene il refresh token e scambia un access token nuovo quando serve.

Un'identità, due connettori ​

La stessa casella Google si legge e si scrive con lo stesso consenso, quindi l'identità sta in un registry suo e IMAP e SMTP la referenziano per id. Duplicare CLIENT_SECRET e REFRESH_TOKEN nei due blocchi significherebbe, prima o poi, ruotarne uno solo.

Variabili ​

VariabileDefaultNote
OAUTH_CLIENT_ID—obbligatoria se il registry è usato
OAUTH_CLIENT_SECRET—obbligatoria
OAUTH_REFRESH_TOKEN—obbligatoria; ottenuto una volta sola, vedi runbook
OAUTH_TOKEN_ENDPOINThttps://oauth2.googleapis.com/tokendeve essere https://; Microsoft 365 si configura qui
OAUTH_SCOPE—solo se il provider lo vuole al refresh; Google no
OAUTH_INSTANCES—più caselle: ordini,notifiche → OAUTH_<ID>_*

Chi le usa:

VariabileDefaultNote
IMAP_AUTH=oauth2dedottoe IMAP_PASSWORD va tolta
IMAP_OAUTH_INSTANCEdefaultquale identità rinnova il token di quella casella
SMTP_AUTH=oauth2dedottoe SMTP_PASSWORD va tolta
SMTP_OAUTH_INSTANCEdefaultdi norma la stessa di IMAP
ZOHO_<ID>_OAUTH_INSTANCEdefaultl'identità di un'organizzazione Zoho CRM, con il token endpoint di Zoho

Zoho risponde 200 anche a un refresh rifiutato, con { "error": … } nel corpo: il fornitore lo tratta come un rifiuto, un ConfigError con il codice di Zoho (per esempio invalid_code).

Le variabili sono dichiarate in MANIFEST_OAUTH: un'identità incompleta dà un ConfigError che elenca tutte le variabili mancanti.

Nel piano ​

Un'identità OAuth2 non è un nodo. Nel piano compare nella riga credenziale delle caselle IMAP e dei server SMTP che la usano: OAuth · identità default · impostata, oppure … · mancano OAUTH_CLIENT_SECRET, OAUTH_REFRESH_TOKEN con origine mancante e la variabile che punta alla prima da impostare. Un'identità che non è in OAUTH_INSTANCES la run non la trova, anche se le sue variabili ci sono: il piano lo dice con · manca OAUTH_INSTANCES. Il piano la risolve con risolviIdentitaOauth(id, env), che non lancia e dei segreti restituisce solo lo stato.

Per etl env check, identitaOauthDichiarate(caselle, env) dà le sole identità che le caselle date usano davvero, cioè quelle su <PREFIX>AUTH=oauth2 senza <PREFIX>ACCESS_TOKEN, da aggiungere alle istanze di ambienteDellaPipeline: una pipeline con caselle su password non chiede variabili OAUTH_*.

Il registry può essere vuoto ​

È l'unico, ed è deliberato. Un PG_HOST mancante è una configurazione rotta; OAuth2 invece è una scelta, e la maggioranza delle installazioni continuerà con una password. Senza OAUTH_INSTANCES né OAUTH_CLIENT_ID il registry esce vuoto e i connettori non cambiano comportamento.

La tolleranza finisce lì. Un'istanza dichiarata in OAUTH_INSTANCES e incompleta è un errore, e un IMAP_OAUTH_INSTANCE che nomina un id inesistente pure: ricadere in silenzio sul token statico significherebbe autenticarsi con una credenziale diversa da quella che si crede.

Come si usa dal codice ​

ts
const oauth = fornitoriOauth(loadOauthRegistry(env));
const tokenImap = oauth(imap.auth, imap.oauthInstance);

imapSource(imap, {
  // …
  ...(tokenImap !== undefined ? { client: { accessToken: tokenImap } } : {}),
});

Un risolutore per run, non per nodo. fornitoriOauth memoizza per id d'istanza: i nodi che condividono l'identità condividono la cache del token. Una pipeline di posta può toccare la stessa casella in tre punti — sorgente, sessione delle action IMAP, notifiche SMTP — e senza la memoizzazione la stessa run chiederebbe tre token invece di uno. Il guaio non è lo spreco: è che funzionerebbe, quindi nessuno se ne accorgerebbe fino al primo rate limit.

Il fornitore serializza anche le richieste: due nodi che chiedono il token insieme sulla cache fredda fanno una chiamata sola.

Come tratta le credenziali ​

  • Niente redirect. La fetch verso il token endpoint usa redirect: "error". Il default di fetch è seguirli, e su un 307 il body — client secret e refresh token — viene ripetuto verso l'host nuovo, anche in http://. Il vincolo https:// guarda solo il primo URL: da solo non basterebbe.
  • Niente credenziali nei messaggi d'errore. Il testo che arriva dal provider viene redatto (client secret e refresh token sostituiti) e troncato a 160 caratteri: più d'un IdP rieccheggia il valore rifiutato, e la CLI stampa gli errori su stderr.
  • Nessuna cause, come in IMAP e SMTP: console.error segue la catena delle cause per intero.
  • Timeout di 30 secondi, come gli altri connettori: un endpoint muto non blocca la run.
  • La cache del token vive in memoria, per la durata della run. Mai su disco.

Errori ​

MessaggioChe cosa vuol dire
OAuth2: refresh token rifiutato (invalid_grant)Non più valido. Su un progetto Internal la causa prima è il cambio password della casella: lo scope è un ambito Gmail. Le altre cause sono nel runbook
OAuth2: il provider ha rifiutato la richiesta (invalid_client…)Client ID o secret sbagliati
OAuth2: il token endpoint non rispondeRete, DNS, timeout, o un redirect rifiutato
OAuth2: risposta del provider senza access_token utilizzabileIl provider ha risposto 200 con un corpo che non contiene un token
Identità OAuth2 "…" non configurataIMAP_OAUTH_INSTANCE o SMTP_OAUTH_INSTANCE nomina un id che non esiste

Noeva è un marchio registrato di 4D S.R.L.