Kerberos single sign-on for Capacitor apps on Android through
Hypergate Authenticator. This plugin wraps the
Hypergate SDK (com.hypergate:sdk on Maven
Central) so your app can authenticate against Kerberos-protected services without passwords or NTLM.
If you are planning a migration away from NTLM, start with the blog post Moving Your Android App off NTLM: Kerberos SSO with the Hypergate SDK. It covers the full integration story that this plugin implements for Capacitor.
Using Cordova instead? See cordova-plugin-hypergate.
Hypergate Authenticator holds the user's Kerberos credentials (TGT) on the device. Your app never sees a password: it asks Hypergate for a SPNEGO/Negotiate token for a given service principal (SPN) and attaches it to the request. For WebView traffic this happens transparently once the managed configurations below are set.
The plugin is Android-only. On iOS and web, getToken rejects with an "unavailable" error, so
cross-platform apps can share the same code path.
- Capacitor 8+ Android app (
@capacitor/android) - Android SDK platform 37 installed (the Hypergate SDK compiles against API 37); set
compileSdkVersion = 37in your app'sandroid/variables.gradle - A device managed by an MDM/EMM/UEM (supported EMMs) with Hypergate Authenticator deployed
npm install capacitor-plugin-hypergate
npx cap syncConfigure these managed configurations (app restrictions) in your MDM/EMM/UEM:
| Managed configuration | Value |
|---|---|
| Account type for HTTP Negotiate authentication | ch.papers.hypergate |
| Authentication server allowlist | * or an explicit list of domains allowed to request tokens |
| Whether NTLMv2 authentication is enabled | WebView NTLM fallback, unrelated to Hypergate; leave it disabled if you want an NTLM-free app |
In addition, your app's package name must be on the discoverability list in the Hypergate Authenticator managed configuration, otherwise token requests fail with error 101.
import { Hypergate } from 'capacitor-plugin-hypergate';
const { token } = await Hypergate.getToken({
servicePrincipal: 'HTTP@securedbackend.com',
});
// attach to your request:
// headers: { 'Authorization': 'Negotiate ' + token }Do not cache the token. Request a fresh one for every API call, because a cached token may have expired between app start and the actual request. The recommended pattern is a request interceptor that fetches a token per request.
getToken(options: GetTokenOptions) => Promise<GetTokenResult>Request a valid auth token for the passed service principal.
Important: do not cache the returned token. Request a fresh token for each API call, otherwise the token may have expired between app start and the actual call. The recommended pattern is a request interceptor that fetches the token per request.
Only available on Android. Rejects when Hypergate is not in possession of a valid TGT, the device is not managed, or the app is not on the discoverability list.
| Param | Type |
|---|---|
options |
GetTokenOptions |
Returns: Promise<GetTokenResult>
| Prop | Type | Description |
|---|---|---|
token |
string |
The raw Negotiate token. Attach it to your request as Authorization: Negotiate <token>. |
| Prop | Type | Description |
|---|---|---|
servicePrincipal |
string |
Service principal (SPN) of the target service, e.g. HTTP@securedbackend.com. |
- Error 101 ("no accounts found"): the app's package name is missing from the discoverability list, or the device has no Hypergate account at all.
- Token issued but the backend returns 401: verify the SPN matches the backend's service principal and that the account has AES key material (see Kerberos RC4 removal).
- Nothing happens in the WebView: check that the account type managed configuration is set
to
ch.papers.hypergateand the server is covered by the allowlist.
A complete runnable example lives at hypergate-capacitor-sample.
MIT, see LICENSE. Questions go to support@hypergate.com.