Kerberos/SPNEGO
Configuration and deployment guidance for Kerberos/SPNEGO authentication in Fortified ID Access.
The KerberosAuthentication authenticator validates browser Kerberos tickets through Java GSS-API. Its own login view starts a background Negotiate request, whether the user enters Kerberos directly or selects it from Selector. It supports Kerberos tokens, not NTLM.
Prerequisites
Section titled “Prerequisites”-
Register an
HTTP/<public-hostname>@<REALM>service principal for the hostname users open in their browser. Include the public load balancer or reverse proxy hostname when one is used. -
Provide a keytab for that service principal on each Access node. Restrict file access to the Access service account. Ensure clocks are synchronized and the nodes can resolve and reach the realm's KDCs.
-
Configure a JAAS entry for the JDK Kerberos login module. For example:
AccessKerberos {com.sun.security.auth.module.Krb5LoginModule requireduseKeyTab=truekeyTab="/path/to/access-http.keytab"storeKey=truedoNotPrompt=trueisInitiator=false;};Start Access with
-Djava.security.auth.login.config=/path/to/jaas.conf. Configure the JVM's Kerberos realm and KDC settings for the environment. Keep the keytab and credentials out of Access configuration and source control. -
Use an Access build that includes the Kerberos login view under
web/authenticator/kerberos. The view is bundled in the authenticator web package and is required for the background probe. Verify that the installed build serves it; no separate frontend deployment is needed.
Prepare the Kerberos environment
Section titled “Prepare the Kerberos environment”The public hostname, service principal, JAAS principal, and Access service_principal must refer to the same HTTP service. For https://access.example.com, the example principal is HTTP/[email protected]; the service class remains HTTP even though the browser uses HTTPS (Microsoft SPN guidance). Use the public hostname seen by the browser, including when TLS terminates at a reverse proxy.
Active Directory
Section titled “Active Directory”Ask the AD administrator to assign the HTTP SPN to the account whose keys will be exported to the keytab. Check whether the SPN already belongs to another account before changing it:
setspn -Q HTTP/access.example.comMicrosoft recommends setspn -S when adding an SPN because it checks for duplicates. See the setspn reference for query, registration, and duplicate checks.
Generate the keytab for that same account and exact principal using the organization's approved AD procedure; Microsoft's ktpass reference describes the mapping and export options. Coordinate the password, encryption type, and key version with the AD administrator. If the account key changes, replace the keytab on every Access node. Do not put an account password on a shared command line or in this configuration.
Realm configuration and keytab checks
Section titled “Realm configuration and keytab checks”Where realm and KDC discovery is not provided by the environment, use a Kerberos configuration file. For example:
[libdefaults] default_realm = EXAMPLE.COM
[realms] EXAMPLE.COM = { kdc = kdc.example.com }Point the Access JVM to it with -Djava.security.krb5.conf=/path/to/krb5.conf, alongside the JAAS setting above. Java can also receive realm and KDC settings through JVM properties; see the Java Kerberos configuration reference.
On an Access node with MIT Kerberos tools, check that the deployed keytab lists the expected principal, key version, and encryption type:
klist -k -e /path/to/access-http.keytabRun this with appropriate access to the keytab. Do not use klist -K: it prints key values. On a test client with MIT Kerberos tools, check for a valid user ticket and request a service ticket:
klistkvno HTTP/[email protected]The kvno result shows that the KDC can issue a service ticket; it does not by itself prove that Access can accept it. See the MIT klist and kvno references.
Configuration
Section titled “Configuration”See Common configuration for properties shared by authenticators.
| Name | Description | Default | Mandatory |
|---|---|---|---|
service_principal | Expected HTTP service principal. It must identify the service configured in JAAS. | "" | true |
jaas_context | Name of the JAAS entry used to load the acceptor credentials. | "" | true |
on_probe_unavailable | stay shows an unavailable message; cancel follows the normal cancel path; skip lets an optional Kerberos step advance to the next Chain step. | stay | false |
username_mapping | principal keeps the realm in the username; short_name removes it after checking allowed_realms. | principal | false |
allowed_realms | Realms accepted for short_name mapping. | [] | false |
max_token_bytes | Maximum decoded Negotiate token size in bytes. | 65536 | false |
max_pending_contexts | Maximum retained GSS exchanges, including cancelled or timed-out exchanges until their worker jobs and disposal finish. Valid range: 1–1024. | 1024 | false |
context_timeout_ms | Maximum time for a pending multi-step GSS exchange, in milliseconds. | 120000 | false |
error_url | Optional error destination for the separate explicit Negotiate flow. Without it, the flow returns HTTP 403. | "" | false |
custom_identifier | Optional identifier added to CEF events. | "" | false |
webroot_dir | Directory containing the Kerberos login view. | web/authenticator/kerberos | false |
{ "id": "kerberos", "type": "KerberosAuthentication", "config": { "base_path": "/authn", "jaas_context": "AccessKerberos", "on_probe_unavailable": "cancel", "username_mapping": "principal" }}By default, the validated client principal is exported as a full name such as [email protected]. For short_name mapping, set allowed_realms, for example ["EXAMPLE.COM"]. If users from multiple realms can have the same short name, keep the full principal or establish how those names map to distinct Access users.
The authenticator example above assumes that a Selector with ID select is configured at /authn/select. The complete Selector flow below shows how the IDs and paths fit together.
Login flow and probe outcomes
Section titled “Login flow and probe outcomes”The Kerberos view starts one same-origin background probe. The browser handles the WWW-Authenticate: Negotiate challenge, which may take several HTTP exchanges. After a valid ticket is accepted, the authenticator completes and the existing Chain continues.
With on_probe_unavailable: "cancel", both the Cancel button and an unavailable probe use the normal AuthN cancellation path. With skip, either action marks an optional Kerberos step as failed so Chain can advance. With stay, the view has no Cancel button and an unavailable probe leaves it open with a message. No redirect URL is configured on Kerberos for these actions. Cancellation and unavailable probes dispose the pending exchange. If a page reload interrupts an active probe, the same configured outcome applies. A later visit in the same login flow shows unavailable without starting another probe or repeating an automatic redirect. The Cancel button remains available on that view when cancel or skip is configured, allowing the user to leave it without a new probe. An unavailable background probe does not destroy the session, enter an IWA retry loop, or publish a CEF authentication-failure event.
The separate ?explicit=1 endpoint on the Kerberos authenticator path performs explicit HTTP Negotiate authentication with its own retry and error handling. It does not use the background probe view.
Kerberos as the only method
Section titled “Kerberos as the only method”Keep the default on_probe_unavailable: "stay" when no other login method exists. The view does not show Cancel in this mode. If the probe is unavailable, the user stays on the view and sees a clear unavailable message. The probe is not repeated in the same login flow, and the session is preserved.
Kerberos selected in Selector
Section titled “Kerberos selected in Selector”Add an ordinary Selector option whose target is the Kerberos authenticator ID. Set on_probe_unavailable: "cancel" on Kerberos and reset_on_selected_cancel: true on Selector. Selector presents and chooses methods; the Kerberos view owns the probe. If the probe is unavailable or the user presses Cancel, the normal cancel path returns to Selector, which presents its choices again. A second Kerberos selection in the same login flow shows unavailable without starting another probe.
This AuthN module example offers Kerberos and username/password as parallel choices. Users enter through /authn/login. Replace <success-path> with the continuation path for your login flow, and configure the referenced password validation pipe separately. Kerberos itself does not require a Pipes module.
{ "name": "AuthN", "enabled": true, "config": { "http_context": "/authn", "authenticators": [ { "id": "login", "type": "Chain", "config": { "base_path": "/authn", "success_location": "<success-path>", "chain": [{ "id": "select", "required": true }] } }, { "id": "select", "type": "Selector", "config": { "base_path": "/authn", "auto_select": false, "reset_on_selected_cancel": true, "options": [ { "id": "kerberos_choice", "target": "kerberos", "label": "Kerberos" }, { "id": "password_choice", "target": "password", "label": "Username and password" } ] } }, { "id": "kerberos", "type": "KerberosAuthentication", "config": { "base_path": "/authn", "jaas_context": "AccessKerberos", "on_probe_unavailable": "cancel" } }, { "id": "password", "type": "UserNameAndPassword", "config": { "base_path": "/authn", "pipe_id": "user_validation_pipe" } } ] }}The JAAS entry and service principal must match the prerequisites above. The user_validation_pipe ID must refer to an existing validation pipe; see Username & password. If Kerberos is the only method, remove Selector and the password authenticator, use the default stay action, and point the Chain directly to Kerberos.
Direct Kerberos followed by Selector
Section titled “Direct Kerberos followed by Selector”If Kerberos is the first step and Selector provides the fallback in the same Chain, make the Kerberos step optional and the Selector step required:
{ "id": "login", "type": "Chain", "config": { "base_path": "/authn", "chain": [ { "id": "kerberos", "required": false }, { "id": "select", "required": true } ] }}Configure Kerberos with "on_probe_unavailable": "skip". Configure Selector with "auto_complete": true and "include_expr": "subject == null" on each alternative option. For example:
{ "id": "select", "type": "Selector", "config": { "base_path": "/authn", "auto_complete": true, "auto_select": false, "options": [ { "id": "password_choice", "target": "password", "label": "Username and password", "include_expr": "subject == null" } ] }}After a successful Kerberos exchange, the subject exists, so Selector has no options to display and completes automatically. When Kerberos is unavailable, the subject is absent and Selector presents the other methods. This configuration assumes Kerberos is the first authentication step and no earlier step has set a subject. Do not use skip when Kerberos is required in the Chain.
Browser and network setup
Section titled “Browser and network setup”Allow integrated authentication for the public Access hostname in the supported browser configuration. In Microsoft Edge, check AuthServerAllowlist; in managed Chrome, check Integrated authentication servers. Both browsers may use intranet detection when the policy is unset, so test the deployed hostname and effective client policy. A browser without a usable ticket or suitable policy may show a native credential prompt rather than silently completing the probe.
Reverse proxies must pass the Authorization and WWW-Authenticate headers and preserve the Access session cookie across GSS steps. A pending multi-step exchange is held in memory on one Access node, so the load balancer must keep that exchange on the same node.
When troubleshooting, check the path in order:
- The browser resolves the public hostname and uses the expected authentication policy.
- The client can obtain a ticket for the HTTP SPN.
- The keytab on each Access node matches the service account's current key, and Access can read it.
- Realm/KDC settings, DNS, and clocks are correct.
- The proxy preserves Negotiate headers and cookies, and multi-step requests stay on the same Access node.
A repeated 401 after a ticket is sent can indicate a principal, key version, encryption, clock, or proxy mismatch. A native credential prompt or immediate automatic cancellation can indicate a missing client ticket or browser policy issue. These are diagnostic starting points, not proof of a specific cause; see Java Kerberos troubleshooting for common realm, keytab, encryption, and clock failures.
Logging and validation
Section titled “Logging and validation”Successful Kerberos authentication publishes CEF event WEB_100015. Explicit authentication failures can publish WEB_100016; an unavailable background probe uses on_probe_unavailable without that failure event. Technical or security-relevant errors remain distinguishable in the application log. Do not log Negotiate tokens or keytab contents in Access or the reverse proxy.
Before rollout, confirm that the installed Access build serves the bundled Kerberos view. Test both direct entry and selection from Selector with real Kerberos credentials. Include a valid ticket, missing or expired ticket, wrong service principal, multi-step exchange, cancel, browser reload, and fallback to another method. Check the resulting Chain and session, CEF events, and native credential-prompt behavior on supported Windows, Linux, and macOS browser setups. Record the tested browser and version, operating system, effective integrated-authentication policy, and whether a native prompt appears when no usable ticket exists. A background request alone does not guarantee that the browser suppresses such a prompt.
See Integrated Windows login, IWA for the existing Windows-specific authenticator.