L’app Expo non carica HTTP su Android 9: è il cleartext, non la VPN
Una build Expo che chiama una semplice API HTTP fallisce da Android 9 in poi. Il tunnel è innocente: il flag cleartext va nella configurazione della build.
Avete rilasciato una nuova build, siete passati alla VPN e la stessa schermata ha smesso di caricarsi. Da Android 9 in poi la spiegazione più comune è più noiosa: la piattaforma rifiuta HTTP semplice per le app che puntano all’API 28 o superiore, e la VPN ha cambiato solo abbastanza contesto da renderlo evidente. L’errore che vedete dipende dal client HTTP, per questo dice così raramente cleartext.
Che cos’è davvero questo errore
Da Android 9 la piattaforma blocca il cleartext per impostazione predefinita appena un’app punta al livello API 28 o superiore. La piattaforma rifiuta la richiesta a un indirizzo HTTP semplice prima che un solo pacchetto lasci il dispositivo. Quale errore vedete dipende dalla libreria HTTP: a volte un guasto di rete generico, a volte un timeout, a volte un messaggio che nomina cleartext senza giri di parole. Quello che non fa mai è raggiungere il vostro server. Android documenta il comportamento predefinito e l’alternativa limitata al dominio nella sua guida alla configurazione di sicurezza.
Un browser sullo stesso dispositivo riesce ancora a caricare la pagina, ed è l’indizio che quasi tutti trascurano. I browser non sono soggetti alla politica di sicurezza di rete della vostra app.
Perché si dà la colpa alla VPN
Di solito cambiano tre cose insieme. L’app può risolvere un altro nome host dopo la connessione della VPN, il dispositivo può essere nuovo con una build più recente, oppure la build stessa può essere passata a un livello API di destinazione che attiva il comportamento predefinito. La VPN si vede e l’SDK di destinazione no, quindi il ticket se lo prende la VPN.
Confrontate i livelli di destinazione della build vecchia e di quella nuova prima di toccare la configurazione di rete. Un’app che punta a 27 o meno ne è esente, e questo spiega tutti i rapporti del tipo «a me funziona sul telefono vecchio».
Dove finisce davvero il flag di Expo
In un progetto Expo gestito, aggiungere un’impostazione a app.json non modifica un manifest Android, perché è il prebuild e sono le build di sviluppo a produrre il manifest. È un plugin di configurazione a scrivere l’impostazione in quella fase. La via supportata è expo-build-properties, configurato nella configurazione dell’app con l’opzione cleartext sotto android.
{
"plugins": [
["expo-build-properties", {
"android": { "usesCleartextTraffic": true }
}]
]
}Lo snippet imposta solo l’opzione del plugin; il manifest viene prodotto dopo. Eseguite un prebuild o una build nuova del client di sviluppo, poi, prima di ritestare, ispezionate l’AndroidManifest.xml generato per android:usesCleartextTraffic, perché un ricaricamento solo JS conserva il vecchio manifest. Allineate la versione del plugin all’SDK Expo su cui gira il progetto. Le opzioni del plugin si spostano tra le versioni, e uno snippet copiato da un altro SDK è una fonte affidabile di no-op silenziosi.
Il flusso bare e l’opzione più stretta
Per React Native bare l’equivalente è android:usesCleartextTraffic sull’elemento application, oppure una configurazione di sicurezza di rete che consenta il cleartext solo per domini specifici. La forma limitata al dominio è quella da preferire, perché consente l’API interna e lascia tutto il resto su HTTPS. Documenta anche la propria lista di eccezioni, ed è proprio la parte su cui un revisore farà domande.
Nessuno dei due approcci cambia il comportamento predefinito della piattaforma per ciò che non avete nominato.
Prima dimostratelo con il log del dispositivo
Prima di modificare la configurazione, ottenete l’errore esatto. adb logcat su un dispositivo collegato mostra il rifiuto cleartext della piattaforma e nomina il componente che l’ha sollevato. Un socket rifiutato, un nome che non si risolve o una stretta di mano TLS fallita indicano un posto del tutto diverso, e abilitare il cleartext non farebbe che indebolire l’app senza motivo.
Poi mantenete onesta la produzione. Il cleartext è accettabile per un endpoint di laboratorio che non può offrire TLS, e solo per il periodo più breve che riuscite a pianificare. Se l’API può terminare TLS dentro la rete privata, mettete il certificato nel trust store del dispositivo e lasciate il cleartext disattivato, perché il tunnel cifra il percorso fino alla sua uscita e nulla oltre.
Quando l’endpoint risponde in HTTPS, togliete l’autorizzazione, ricostruite e provate sulla VPN e su un Wi-Fi normale nella stessa sessione. La risoluzione dei nomi può differire tra questi due percorsi, e solo la coppia vi dice quale sta dicendo la verità.