Skip to content

Fortified IDDocs

Kerberos/SPNEGO sign-in with Active Directory

Configure Fortified ID Access for browser Kerberos/SPNEGO sign-in against Active Directory.

Kerberos/SPNEGO sign-in with Active Directory

Section titled “Kerberos/SPNEGO sign-in with Active Directory”

This use case configures Fortified ID Access to accept Kerberos tickets from domain-joined browsers. It uses an Active Directory service account, an HTTP service principal name (SPN), and a keytab that Access reads through the Java GSS-API.

Users open Access at a public hostname such as https://idp.example.com. A domain-joined browser obtains a ticket for HTTP/[email protected] and presents it to the KerberosAuthentication authenticator. Access validates the ticket and maps the authenticated principal to its short username.

This use case builds on the Kerberos/SPNEGO authenticator reference. Use the reference for browser policy, proxy, load-balancing, and fallback-flow requirements.

  • An Active Directory administrator can create or manage a dedicated service account and register an SPN.
  • The public hostname resolves to Access and is the hostname that users enter in their browser.
  • Each Access node can resolve and reach the KDC, has synchronized time, and can read its local copy of the keytab.
  • The browser is configured to allow integrated authentication to the public hostname.
  • The Access build includes the Kerberos login view described in the authenticator reference.

Complete the configuration in this order:

  1. Create a dedicated AD service account and register its HTTP SPN.
  2. Generate the keytab and store it outside any configuration Git working tree.
  3. Configure jaas.conf, krb5.conf, and the Access Java options.
  4. Place the configuration files and keytab with the required protection.
  5. Configure KerberosAuthentication in the AuthN module.
  6. Add the Kerberos option to a Selector and restrict it to the intended client network.

Step 1: Create the service identity and SPN

Section titled “Step 1: Create the service identity and SPN”

Create a dedicated AD service account, for example EXAMPLE\access-kerberos.

Register the HTTP SPN for the public browser hostname. Use setspn -S, which checks for duplicate SPNs:

setspn -S HTTP/idp.example.com EXAMPLE\access-kerberos

Verify that the SPN resolves to the intended account before generating the keytab:

setspn -Q HTTP/idp.example.com

The SPN, the keytab principal, the JAAS principal, and Access service_principal must all name the same HTTP service. The service class stays HTTP when users access the service over HTTPS.

Generate a keytab for HTTP/[email protected], mapped to the dedicated service account, using the organization's approved Active Directory procedure. The example environment used AES256-SHA1 and KRB5_NT_PRINCIPAL.

On an AD administration workstation, run the following command in PowerShell to generate the keytab:

ktpass /out C:\secure-output\http.keytab `
/princ HTTP/[email protected] `
/mapuser EXAMPLE\access-kerberos `
/pass * `
/crypto AES256-SHA1 `
/ptype KRB5_NT_PRINCIPAL

Confirm that the command maps the expected principal and writes the keytab, then transfer it through an approved secure channel to each Access node. Do not copy the key value that ktpass can print into logs, tickets, or documentation.

For Linux Access nodes, run ktpass on a Windows-based AD administration workstation and securely distribute the generated http.keytab to each node.

Do not place a service-account password in a shared command line, Access configuration, source control, or this documentation. Store the generated http.keytab outside source control, deploy it to every Access node, and restrict it to the Access service account. See the ktpass reference for the required mapping and export options.

Step 3: Configure JAAS and the Kerberos realm

Section titled “Step 3: Configure JAAS and the Kerberos realm”

Create jaas.conf in a protected Access configuration directory. Replace the example principal and keytab location with the values for the environment. Use forward slashes in the keytab path; Java accepts them on both Windows and Linux.

AccessKerberos {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="<protected keytab path>/http.keytab"
principal="HTTP/[email protected]"
storeKey=true
doNotPrompt=true
isInitiator=false;
};

Create krb5.conf with the Kerberos realm and KDC used by Access:

[libdefaults]
default_realm = EXAMPLE.COM
[realms]
EXAMPLE.COM = {
kdc = dc01.example.com
kdc = dc02.example.com
}

Add the following Java options to the Access service, replacing <installation path> with the Access installation directory:

-Djava.security.auth.login.config=<installation path>\mgmt-center\data\customer\access\jaas.conf
-Djava.security.krb5.conf=<installation path>\mgmt-center\data\customer\access\krb5.conf

Restart the Access service after changing its Java options or either configuration file.

Keep jaas.conf and krb5.conf with the Access customer configuration on each Access node:

<installation path>/mgmt-center/data/customer/access/
├── jaas.conf
├── krb5.conf

Store http.keytab in a protected directory outside any Access configuration Git working tree, and use its absolute path in jaas.conf. The keytab contains the service account's Kerberos key material. When Access runs as Local System, grant NT AUTHORITY\\SYSTEM read access and prevent ordinary users from reading or changing the file. Local administrators remain trusted administrators of the server.

The jaas.conf and krb5.conf files do not normally contain a password or key, but keep them under controlled configuration permissions because they identify the service principal, keytab location, realm, and KDCs. If the Access configuration directory is a Git working tree, do not add the keytab to it. If an operational requirement makes that unavoidable, ignore http.keytab in that repository before copying it there; .gitignore prevents an accidental add but does not provide access control or remove a file that Git already tracks.

Add the Kerberos authenticator to the AuthN module. This example uses the existing ${globals.default_login_suffix} path, accepts only EXAMPLE.COM, and maps [email protected] to alice.

{
"id": "kerberosauthentication_1",
"type": "KerberosAuthentication",
"description": "Cross-platform Kerberos/SPNEGO authentication using Java GSS-API.",
"config": {
"base_path": "${globals.default_login_suffix}",
"service_principal": "HTTP/[email protected]",
"jaas_context": "AccessKerberos",
"username_mapping": "short_name",
"allowed_realms": ["EXAMPLE.COM"],
"on_probe_unavailable": "cancel"
},
"display_name": "Kerberos / SPNEGO"
}

Use short_name only when usernames are unique across all accepted realms. Use the default principal mapping when retaining the realm is necessary to keep user identities distinct.

Step 6: Present Kerberos through a Selector

Section titled “Step 6: Present Kerberos through a Selector”

In this example, the Selector routes the user to kerberosauthentication_1. The Selector contains only the Kerberos option:

{
"id": "select",
"type": "Selector",
"display_name": "Selector",
"description": "Selector",
"config": {
"base_path": "${globals.default_login_suffix}",
"overlay_dir": "${globals.default_overlay_dir}",
"webroot_dir": "web/authenticator/selector",
"options": [
{
"id": "kerberos",
"target": "kerberosauthentication_1",
"order": 1,
"label": "Kerberos / SPNEGO 1",
"include_expr": "ipv4.isInSubnet(request.remote_address, '192.168.10.0/24')"
}
]
}
}

The include_expr makes the Kerberos option available only when Access sees the client address in 192.168.10.0/24. Since this example has no other option, clients outside that subnet cannot select an authentication method from this Selector. When Access is behind a reverse proxy or load balancer, ensure that request.remote_address represents the original client address before relying on this filter. See Selector option filtering and the ipv4.isInSubnet expression for the predicate syntax.

  1. Query the SPN with setspn -Q HTTP/idp.example.com and confirm that it belongs to the dedicated service account.

  2. On each Access node, use klist -k -e <keytab path> to verify that the deployed keytab contains HTTP/[email protected]. Do not use klist -K, because it prints key values.

  3. From a domain-joined Windows test client, signed in as the test user, request a service ticket and inspect the ticket cache:

    Terminal window
    klist get HTTP/idp.example.com
    klist tickets

    The commands should complete without an error and klist tickets should show a cached service ticket for HTTP/idp.example.com. This verifies that Active Directory can find the SPN and that the domain controller can issue a service ticket for it. It does not verify that Access can read or use http.keytab; that is verified in step 2 and by the browser test.

  4. Open the configured Access login path in a browser that is allowed to use integrated authentication for idp.example.com. For example, navigate to a service provider (SP) or relying party (RP) that is protected by this sign-in method and initiate its sign-in flow.

  5. Confirm that Access completes the Kerberos step, continues the configured Chain, and records successful authentication as CEF event WEB_100015.

  6. Test a client without a usable ticket and confirm the configured on_probe_unavailable behavior. When using cancel, also test that the Selector or other fallback path is usable.

  7. Optional — when using the Selector filter in this example: Test a client from 192.168.10.0/24 and confirm that the Selector presents the Kerberos option. Test a client outside that subnet and confirm that the option is absent.

  • Use a dedicated, least-privileged AD service account and document its ownership and keytab-rotation procedure.
  • Replace the keytab on every Access node whenever the service-account key changes. Keep the key version and encryption type aligned with Active Directory.
  • When Access is behind a reverse proxy or load balancer, preserve the Authorization and WWW-Authenticate headers, preserve the Access session cookie, and keep a multi-step GSS exchange on one Access node.
  • Test the exact public hostname, browser version, operating system, and effective browser policy used in production.

If the browser repeatedly receives 401 after sending a ticket, first compare the public hostname, SPN, keytab principal, JAAS principal, and service_principal. Then check the keytab version and encryption type, DNS and KDC reachability, clock synchronization, browser policy, and reverse-proxy headers. Do not log Negotiate tokens or keytab contents.

For additional diagnostic guidance, see Kerberos/SPNEGO troubleshooting.