Kerberos Android: SSO con l’Hypergate SDK oltre NTLM

Android bugdroid and Cerberus mascots beside a code window with the com.hypergate:sdk dependency

Lukas Schönbächler · Luglio 2026 · 9 min di lettura

Perché conta

  • NTLM ha una scadenza: NTLMv1 viene bloccato a ottobre 2026 (KB5066470) e l’NTLM di rete sparisce con la prossima Windows Server LTSC. Le app Android che si autenticano ancora con NTLM hanno bisogno di un sostituto, e quel sostituto è Kerberos.
  • L’Hypergate SDK (com.hypergate:sdk su Maven Central) aggiunge i token negotiate SPNEGO a qualsiasi app Android, così la tua app risponde con Kerberos invece che con NTLM.
  • Due percorsi di integrazione: le WebView si autenticano senza scrivere codice, le richieste HTTP native richiedono una chiamata per il token e un header.
  • Le varianti silenziose consegnano i token ai worker in background e ai sync adapter senza mai mostrare interfaccia.
  • La configurazione viene distribuita tramite le managed configuration, quindi funziona con tutte le principali piattaforme MDM/EMM/UEM.

Microsoft sta smantellando l’autenticazione legacy pezzo per pezzo. Gli eventi di audit NTLM sono arrivati con Windows 11 24H2 e Server 2025, il single sign-on NTLMv1 viene bloccato a ottobre 2026 (KB5066470) e l’NTLM di rete scompare del tutto con la prossima Windows Server LTSC. Abbiamo spiegato cosa significa questa deprecazione per i parchi dispositivi mobili in il piano di Microsoft per disattivare NTLM, e la sua pulizia gemella, la rimozione di RC4 da Kerberos, ha già superato il punto di non ritorno questo mese.

Il lato server di questa migrazione è ben documentato. È il lato client il punto in cui i team mobile si bloccano: ogni app Android interna che risponde ancora a una sfida NTLM, sia tramite una WebView sia tramite il proprio stack HTTP, deve iniziare a inviare token negotiate Kerberos. Gli utenti non accetteranno l’alternativa, cioè digitare le password di dominio sul telefono. Questo articolo mostra come colmare quel divario con l’Hypergate SDK: cosa fa, come configurarlo e quale dei suoi metodi di richiesta usare in ogni caso.

Cosa fa davvero l’SDK

L’SDK è la parte lato app di un flusso di single sign-on Kerberos. L’identità Kerberos dell’utente risiede in un’app authenticator Kerberos sul dispositivo, come Hypergate Authenticator, esposta tramite il framework standard degli account Android. Quando la tua app deve chiamare un servizio kerberizzato, l’SDK richiede a quell’account un token negotiate SPNEGO per il service principal name del servizio (per esempio [email protected]) e te lo restituisce come stringa. Lo inserisci nell’header Authorization: Negotiate e la richiesta è autenticata.

La tua app non vede mai una password e non memorizza mai credenziali. Si limita a richiedere token. È anche questo che la rende il punto di approdo naturale per una migrazione da NTLM: il design di NTLM ruota attorno alle risposte di sfida derivate dalla password, esattamente il materiale che gli attaccanti inoltrano e violano, mentre un token negotiate non contiene alcun materiale di password. Nemmeno quali server possono ricevere i token viene deciso nel codice: l’IT lo controlla in modo centralizzato tramite una allowlist nella managed configuration.

Due modi per integrare l’Hypergate SDK Percorso WebView (zero codice) Aggiungi la dipendenza + meta-data nel manifest L’EMM distribuisce la managed configuration Ogni WebView si autentica in modo trasparente Percorso nativo (poche righe) Richiedi il token per il service principal (SPN) Imposta l’header Authorization: Negotiate Funziona con qualsiasi client HTTP (OkHttp, Volley, Retrofit, …)

Figura 1: le app ibride e WebView sono pronte dopo la configurazione. Le app native aggiungono una chiamata per il token a ogni richiesta.

Configurazione: una dipendenza, una voce nel manifest

Aggiungi l’SDK da Maven Central al build.gradle della tua app (controlla Maven Central per la versione più recente):

dependencies {
    implementation "com.hypergate:sdk:1.6.0"
}

Se la tua applicazione non definisce le proprie app restriction, fai riferimento al file di restriction dell’SDK nel tuo AndroidManifest.xml:

<application>
    <meta-data
        android:name="android.content.APP_RESTRICTIONS"
        android:resource="@xml/hypergate_sdk_restrictions" />
</application>

Se distribuisci già le tue restriction, copia invece le voci da hypergate_sdk_restrictions.xml nel tuo file. In entrambi i casi, la tua app ora espone le managed configuration che l’IT imposta nella console EMM:

  • Tipo di account per l’autenticazione HTTP Negotiate: quale tipo di account risponde alle sfide di autenticazione. Per Hypergate è ch.papers.hypergate.
  • Allowlist dei server di autenticazione: quali server possono richiedere token. O un wildcard (*) o un elenco esplicito di domini.
  • Se l’autenticazione NTLMv2 è abilitata: un interruttore di fallback della WebView che non ha nulla a che vedere con Hypergate. Se il tuo obiettivo è un’app senza NTLM, lascialo disabilitato così la WebView risponde solo alle sfide Negotiate.

Vale la pena soffermarsi su quella allowlist centrale: significa che la policy di sicurezza viaggia con il livello di gestione dei dispositivi, non con i rilasci dell’app. Restringere l’elenco dei server che ricevono token non richiede mai di pubblicare un aggiornamento.

Percorso 1: WebView, zero codice

Se la tua app è ibrida (Cordova, Capacitor o simili) o mostra servizi interni in una WebView, hai già finito. Con la dipendenza e le restriction al loro posto, ogni WebView del tuo progetto risponde alle sfide HTTP Negotiate in modo trasparente, sia per il caricamento delle pagine sia per le chiamate AJAX. Non c’è nessun interceptor da scrivere né alcun token da gestire: l’utente apre la schermata ed è autenticato.

Per Cordova in particolare esiste un plugin già pronto e un’app di esempio. L’unico caso in cui la magia della WebView non si applica: un’app ibrida che effettua le richieste HTTP tramite un plugin nativo invece che tramite lo stack della WebView. Quel plugin è un client nativo, quindi segue il percorso 2.

Percorso 2: richieste di token native

Per le chiamate HTTP native richiedi tu stesso un token. L’API è un unico metodo in quattro varianti, lungo due assi: sincrono contro asincrono, e normale contro silenzioso. Le varianti normali accettano un Activity e possono mostrare interfaccia se serve l’interazione dell’utente, per esempio un selettore di account o una schermata di consenso. Le varianti silenziose accettano un semplice Context, non mostrano mai interfaccia e falliscono invece, che è esattamente ciò che vuoi in un worker o in un sync adapter.

MetodoBloccanteAccettaPuò mostrare UIChiamante tipico
requestTokenSyncActivityinterceptor su un thread in background
requestTokenAsyncnoActivityflussi guidati dall’interfaccia
requestTokenSilentlySyncContextmaiWorkManager, sync adapter
requestTokenSilentlyAsyncnoContextmaipush handler, servizi

La chiamata sincrona è una sola riga:

val token = Hypergate.requestTokenSync(activity, "[email protected]")

// or from a background component, without any UI:
val token = Hypergate.requestTokenSilentlySync(context, "[email protected]")

La variante asincrona consegna il token o l’eccezione alle callback:

Hypergate.requestTokenAsync(activity, "[email protected]",
    { negotiateToken -> Log.d("TOKEN", negotiateToken) },
    { exception -> Log.d("ERROR", exception.message) })

In pratica la maggior parte delle app incapsula la chiamata al token una volta sola e poi se ne dimentica. Con OkHttp quel wrapper è un interceptor:

internal class HypergateOkHttpInterceptor(
    private val activity: Activity
) : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()

        val token = Hypergate.requestTokenSync(
            activity,
            "HTTP/${request.url.host}"
        )
        val authenticatedRequest = request.newBuilder()
            .addHeader("Authorization", "Negotiate ${token}")
            .build()

        return chain.proceed(authenticatedRequest)
    }
}

val client = OkHttpClient.Builder()
    .addInterceptor(HypergateOkHttpInterceptor(activity))
    .build()

Ogni richiesta attraverso questo client è ora autenticata. Lo stesso schema vale per Volley (costruisci la mappa degli header in getHeaders() e restituiscila) o per qualsiasi altro stack HTTP: richiedi il token, imposta l’header, invia. Se la tua app portava in precedenza una libreria NTLM o codice di challenge-response scritto a mano per queste chiamate, è questo interceptor a sostituirlo.

Oltre le basi: bundle, round trip, helper per gli account

I metodi requestToken* restituiscono solo la stringa del token, che copre il caso comune. Se ti serve il risultato completo di AccountManager, le controparti requestTokenBundle* restituiscono il Bundle grezzo, con il token sotto AccountManager.KEY_AUTHTOKEN. Le varianti bundle accettano anche due parametri aggiuntivi per i server che negoziano su più round trip: incomingAuthToken, il token che il server ha restituito nel passaggio precedente, e spnegoContext, un identificatore opaco che trasporta lo stato della negoziazione tra una chiamata e l’altra.

val bundle = Hypergate.requestTokenBundleSync(
    activity, "[email protected]", incomingAuthToken, spnegoContext
)
val token = bundle.getString(AccountManager.KEY_AUTHTOKEN, "")

Alcuni helper completano l’API per costruire un onboarding sensato:

// true if a Hypergate account is present on the device
Hypergate.hasAccount(context)

// all Hypergate accounts (honors the managed configuration)
val accounts: Array<Account> = Hypergate.getAccounts(context)

// system intent to let the user pick or add an account
startActivity(Hypergate.getAccountChooserIntent(context))

Controlla hasAccount() all’avvio: se restituisce false, il dispositivo non è arruolato o l’authenticator non è ancora provisionato, e puoi mostrare un messaggio sensato invece di lasciar fallire la prima richiesta.

Quale metodo devo chiamare? Mi serve un token negotiate Posso mostrare interfaccia qui? (è disponibile un Activity?) no requestToken- SilentlySync / Async worker, sync adapter, push handler Serve il bundle grezzo o una negoziazione multi-round-trip? requestToken- Bundle* varianti incomingAuthToken + spnegoContext no requestTokenSync / Async la scelta predefinita

Figura 2: come scegliere la variante giusta. Il codice in background usa i metodi silenziosi, le negoziazioni a più passaggi usano i metodi bundle, tutto il resto usa la coppia predefinita.

Gestione degli errori

Tutte le callback di errore consegnano una HypergateException con due proprietà: un code numerico su cui la tua app può ramificarsi, e un message dettagliato in inglese per i log. Il primo in cui ti imbatterai è il code 101, “no accounts found”. Di solito non significa che il dispositivo non abbia un account Hypergate: significa che il package name della tua app manca dall’elenco di discoverability nella managed configuration di Hypergate, quindi l’account è invisibile alla tua app. Aggiungi il package name nella console EMM e la stessa chiamata va a buon fine.

Dove ti lascia tutto questo

Ogni scadenza dell’autenticazione legacy porta allo stesso punto: Kerberos con AES e, sempre più, certificati al posto delle password. Portare le tue app Android fin lì si riduce a una piccola superficie di integrazione: una dipendenza, una voce nel manifest e o nulla del tutto (WebView) o una chiamata per il token a ogni richiesta (nativo). La gestione delle chiavi e la negoziazione dei ticket restano dentro l’authenticator, dove è giusto che stiano. La tua app richiede i token e l’IT controlla la policy tramite l’EMM. Quando arriveranno il blocco di NTLMv1 di ottobre e il passaggio a LTSC, le tue app saranno già dalla parte giusta. Il codice sorgente dell’SDK e la documentazione completa dell’API si trovano nel repository GitHub.


Vuoi migrare le tue app da NTLM?

Hypergate Authenticator fornisce l’identità Kerberos che le tue app consumano tramite questo SDK, su Android e iOS gestiti, con ogni EMM principale e senza NTLM in nessun punto del percorso. Parlaci della tua migrazione dall’autenticazione legacy.

Other Stories