> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/gateway/kerberos.md).

# Kerberos and desktop SSO

Configure Kerberos/SPNEGO desktop single sign-on through the Access Gateway — the principal shape, the Kerberos authentication rule, and the two URI patterns that otherwise silently override it.

## What this is, and when you need it

Kerberos SSO means a domain-joined workstation signs the user into OpenIAM with no login page at all: the browser presents a Kerberos ticket to the gateway, the gateway extracts the principal, and OpenIAM issues a session for the matching identity. Configure it when users are already authenticated to Active Directory and a second password prompt is the only thing in their way. It is the oldest **passwordless** sign-in OpenIAM ships: the shipped `DEF_KERB_AUTH_RULE` is `KERB_AUTH` → `AUTHORIZATION_ACCEPT`, one proof and no password page. The other passwordless options, and what they cost, are on [Passwordless sign-in](/administration-guide/security/authentication-model.md#passwordless-sign-in).

Add it to a gateway that already works with passwords — [Protect an application behind the Access Gateway](/administration-guide/gateway/protect-an-application.md). The gateway module does **not** perform the SPNEGO handshake; a separate module on the proxy host does, and enabling Kerberos without it fails by silently falling back to the login form.

## At a glance

|                          |                                                                                                                                                                                                  |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **You will end up with** | A domain-joined workstation reaching SelfService as the domain user, with no login page and a session cookie set                                                                                 |
| **Where**                | **Access Control → Content Providers** → **Supported Authentication Rules**, plus **Supported Authentication Levels** on two URI patterns                                                        |
| **You need first**       | Password sign-in already succeeding through the content provider; an OpenIAM user whose login on its managed system equals their Active Directory username; a validated keytab on the proxy host |
| **Takes**                | 30 minutes of OpenIAM work, once the domain and proxy-host prerequisites are done — those take days, because they are somebody else's queue                                                      |
| **Reversible**           | Yes — remove the rule and wait out the cache; password sign-in resumes. Do **not** roll back by re-exporting or deleting the keytab or the service account                                       |

## Before you begin

Three systems are involved, and confusing them is the usual reason this does not work:

| System                              | Does what                                          | Who configures it                                                            |
| ----------------------------------- | -------------------------------------------------- | ---------------------------------------------------------------------------- |
| Active Directory                    | Holds the `HTTP/` principal and issues tickets     | The Windows domain team                                                      |
| The SPNEGO module on the proxy host | Performs the handshake with the browser            | The deployment owner                                                         |
| The Access Gateway module           | Takes that principal to OpenIAM and gets a session | The deployment owner sets the directives; **you** decide what they should be |

**Yours:** a content provider whose **Domain Pattern** matches the hostname users type; an OpenIAM user whose login on its managed system equals the Active Directory username — check a real one first, because this is the commonest cause of failure; and the principal shape, taken from that login.

**To be arranged, and covered by the** [**Installation Guide**](/installation/installation.md)**:** the service principal registered and a keytab exported; a dedicated Active Directory service account; the proxy host's fully qualified name resolvable forward *and* reverse; the SPNEGO and Kerberos client packages installed with the keytab in place. The first three steps say what to specify.

{% hint style="warning" %}
This changes how people sign in. Test a break-glass administrator that does not depend on Kerberos before you start — see [Change configuration safely](/administration-guide/start/change-safely.md). The lockout path here is enabling Kerberos while no OpenIAM identity matches the domain principal: every browser then gets a ticket the gateway cannot resolve to a user.
{% endhint %}

## Configure Kerberos sign-in

Three of the six steps are host and domain configuration you will hand over. They are here because the *order* matters and each carries a decision or a check that is yours.

{% stepper %}
{% step %}

### Have the service principal registered and a keytab issued

This step happens on the Windows domain controller, with domain administrator rights, and none of it is an OpenIAM task — see the [Installation Guide](/installation/installation.md). What you need to specify, and then confirm, is short:

* The service principal must be `HTTP/<proxy FQDN>`, using the same fully qualified name as the URL your users type and the content provider's **Domain Pattern**. Not the realm, not a short name, not an alias.
* A dedicated Active Directory service account, used for nothing else.
* The proxy host present as a computer object, with a forward A record **and** a reverse PTR record.
* The keytab exported for that principal and delivered to the proxy host.

{% hint style="warning" %}
**A keytab is issued once.** Exporting a keytab resets the service account's password and moves its key version number, so every re-export invalidates the keytab already in place. Ask for one export, and do not let anybody re-run it to "refresh" a working setup.

The symptom you will see when somebody does: Kerberos worked, then stopped after an Active Directory change, and it stopped for everybody simultaneously. Nothing in OpenIAM changed and nothing in OpenIAM will fix it — a new keytab has to be exported and redistributed.

Encryption types are worth naming up front too. An export that includes the deprecated DES and RC4 types will fail outright if your domain policy has disabled them, so agree the encryption type before the export rather than after.
{% endhint %}
{% endstep %}

{% step %}

### Have the proxy host's hostname, Kerberos client and keytab put in place

Also host configuration, also the [Installation Guide](/installation/installation.md): the proxy host's hostname set to the FQDN in the service principal, the Kerberos client packages installed, the realm and key distribution centre configured, and the keytab placed where the web server — and only the web server — can read it.

Two properties of that configuration are worth asking for by name, because they protect you later:

* The realm and the key distribution centre should be **named explicitly** rather than discovered through DNS. Explicit naming means a DNS change cannot silently redirect authentication somewhere else.
* The keytab must be readable by the web server's own user and by nobody else. It is a credential.
  {% endstep %}

{% step %}

### Get Kerberos proved on the proxy host before anything reaches OpenIAM

Before any OpenIAM configuration can matter, the domain controller and the keytab have to agree with each other. That check runs on the proxy host and is in the [Installation Guide](/installation/installation.md) — but insist on seeing its result, because every later failure looks identical from the browser and this is the only place the real cause is visible.

Three things must match, and this is what to ask for:

| Must match             | Why it matters to you                                                                                                                                                     |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Key version number** | A mismatch means the keytab is older than the account's current key — somebody re-exported it, or reset the service account's password. Nothing in OpenIAM can compensate |
| **Principal**          | It must be `HTTP/<proxy FQDN>@<AD_REALM>` everywhere, and the same FQDN as your content provider's **Domain Pattern**                                                     |
| **Encryption type**    | The keytab and the ticket must share one. A domain policy change that retires an encryption type breaks a working keytab                                                  |

If this check does not pass, stop. Configuring the Kerberos authentication rule in OpenIAM on top of a keytab that does not validate produces a login form and no diagnosis.
{% endstep %}

{% step %}

### Decide the principal shape, and have the gateway directives set

Enabling Kerberos on the gateway is two OpenIAM directives plus the SPNEGO handshake directives, in the proxy's own configuration, followed by a restart — all of which is in the **Installation and Tuning Guide**.

The decision inside it is yours, and it is the one that most often goes wrong: **the principal string the gateway sends has to equal the login on the content provider's managed system, exactly.** Four directives shape it, and you pick one:

| Directive                    | Type   | What it does                                                  |
| ---------------------------- | ------ | ------------------------------------------------------------- |
| `OPENIAM_Kerberos`           | on/off | Accept a GSSAPI-authenticated principal instead of a password |
| `OPENIAM_KrbPrincipalOnly`   | on/off | Strip `@<AD_REALM>`, pass only the username                   |
| `OPENIAM_KrbPrincipalPrefix` | String | Prepend to the principal, for example `CORP\`                 |
| `OPENIAM_KrbPrincipalSuffix` | String | Append to the principal, for example `@example.com`           |

Pick exactly one shape. If your OpenIAM logins on that managed system are bare usernames, `OPENIAM_KrbPrincipalOnly on` is what you want. If they are `DOMAIN\user` or user principal names, use the prefix or the suffix instead. OpenIAM looks up whatever arrives, verbatim — it does not normalise, strip or retry.

So decide it from the data, not from the domain: open a representative user in the Webconsole, read their login on the content provider's **Managed System**, and specify the directive that produces that exact string. Then confirm it after the change, from the symptom side — a principal that does not match appears in the OpenIAM log as `Proxy identity not found for principal '<p>'`, and `<p>` is the string the gateway actually sent. Comparing `<p>` against the login is the whole diagnosis.
{% endstep %}

{% step %}

### In OpenIAM: attach the Kerberos authentication rule

Go to **Access Control → Content Providers**, open the content provider whose **Domain Pattern** matches the proxy hostname, and under **Supported Authentication Rules** add **Def. Kerberos Auth Rule**.

That rule is shipped, not something you build. It is `AUTH_RULE` row `DEF_KERB_AUTH_RULE`, named `Def. Kerberos Auth Rule` and described as `Rule for Kerberos Authentication`, and it is two steps: the `KERB_AUTH` authentication level grouping followed by `AUTHORIZATION_ACCEPT`. The `KERB_AUTH` level itself is `Kerberos Authentication` with `REQUIRES_AUTHENTICATION='Y'`. Open it on **Policy → Authentication Rule** to confirm both steps before you attach it — a rule missing its accept step never grants a session.

Then add the same rule to the URI patterns **`/idp/oauth2/authorize`** and **`/idp/oauth2/handler`**. This is not optional decoration: a URI pattern that carries its own rules ignores the content provider's entirely, and both of those patterns are seeded with rules by **Add Default Patterns**. Skip this and Kerberos will appear to be configured and never engage.

{% hint style="warning" %}
The Webconsole warns you when you add a rule to a content provider, and it means it: *"Are you sure you want to add a new authentication rule to this content provider? This may affect your installation. Proceed only if you understand the impact, or apply changes only to the required URI patterns."* Prefer the per-pattern change where you can: a rule on the content provider applies to every path it serves, including the ones you have not thought about.
{% endhint %}

Finally, confirm an OpenIAM user exists whose login on the content provider's **Managed System** equals the domain username the gateway will send. Changes take effect on the next cache sweep — `org.openiam.am.uri.federation.threadsweep`, `30000` ms for patterns, and `org.openiam.content.provider.threadsweep`, `300000` ms for content providers — so allow five minutes before concluding anything. Both are read from service configuration rather than the Webconsole, so if a deployment has changed them the deployment owner is the one who knows; the values above are what you get if nobody has.
{% endstep %}

{% step %}

### On the client workstation

The workstation must be joined to the domain. Then in **Internet Options → Security → Local intranet → Sites**, add the proxy URL (`http://rproxy.<AD_DOMAIN>`), and in **Internet Options → Advanced** enable **Enable Integrated Windows Authentication**. Chrome and Edge read these Windows settings; Firefox does not, and needs the host added to `network.negotiate-auth.trusted-uris` in `about:config`.

Reboot or sign out and in, so the workstation has a fresh ticket-granting ticket.
{% endstep %}
{% endstepper %}

## Verification

Do these in order — each isolates one of the three systems.

| Check                                           | How                                                                                                                                                                                                                                  | What good looks like                                                                                                                                                   |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The proxy host and Active Directory agree       | Not observable from OpenIAM. The keytab's key version number, principal and encryption type must match what Active Directory currently holds; the check runs on the proxy host — [Installation Guide](/installation/installation.md) | Ask for its output, and do not proceed past a mismatch                                                                                                                 |
| The gateway offers SPNEGO                       | From a machine *not* joined to the domain, request `/selfservice/` on the proxy hostname and read the response headers                                                                                                               | `WWW-Authenticate: Negotiate` is present. If it is not, the SPNEGO module is not active on that path and the gateway module is not involved yet                        |
| The gateway resolves the principal to a session | From the domain-joined workstation, browse to `http://rproxy.<AD_DOMAIN>/selfservice/`                                                                                                                                               | SelfService as the domain user, no login page, and an `OPENIAM_AUTH_TOKEN` cookie set                                                                                  |
| OpenIAM recorded the authentication             | `/webconsole/viewAuditLog`, looking for a `LOGIN` event against the domain user                                                                                                                                                      | The event exists, and its `AUTHENTICATION_TYPE` audit attribute confirms the session came from Kerberos rather than a password — the cookie looks identical either way |

If the third check silently shows the login form instead, the next evidence is the gateway's own debug output, which is a proxy configuration change and a restart. Ask for it specifically: the call the module makes to OpenIAM with the principal, and the principal value it carries. That string is what OpenIAM tried to look up, and comparing it against the user's login on the content provider's managed system is the diagnosis. The switches to name are `OPENIAM_DebugESB` and `OPENIAM_Verbose`, or in a container deployment `OPENIAM_RPROXY_DEBUG_ESB` and `OPENIAM_RPROXY_VERBOSE` — both of which ship as `1`. Ask for them off again afterwards; they are verbose and they log principals.

## When it goes wrong

| Symptom                                                         | Cause                                                                                                                 | Fix                                                                                                                                                                                     |
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| No `WWW-Authenticate: Negotiate` in the response                | The SPNEGO module is not loaded, or its directives are outside the block that serves the URL                          | A proxy configuration fix — [Installation Guide](/installation/installation.md). Nothing in OpenIAM is involved yet                                                                     |
| Browser prompts for a username and password                     | SPNEGO was offered but the browser fell back to Basic                                                                 | Add the host to Local intranet, or to `network.negotiate-auth.trusted-uris` in Firefox. The gateway should also be refusing Basic — [Installation Guide](/installation/installation.md) |
| The keytab validates but the browser still gets the login form  | The gateway never called OpenIAM, or it is presenting the wrong kind of credential                                    | Ask for the gateway's debug output and look for the principal call. If it is absent, the problem is the proxy, not OpenIAM                                                              |
| OpenIAM log: `Proxy identity not found for principal '<p>'`     | No identity with that login on the **content provider's managed system**                                              | Yours to fix: compare `<p>` against the user's login on that managed system, and change the principal shape — `OPENIAM_KrbPrincipalOnly` / `Prefix` / `Suffix` — until they match       |
| Authentication is attempted with a password and fails           | No rule with the `KERB_AUTH` level applies, so OpenIAM did not skip the password check                                | Yours to fix: add **Def. Kerberos Auth Rule** to the URI pattern that is actually being hit. Pattern rules override content provider rules                                              |
| Kerberos configured on the content provider and nothing changed | `/idp/oauth2/authorize` and `/idp/oauth2/handler` still carry their default rules                                     | Add the Kerberos rule to those two patterns as well                                                                                                                                     |
| Worked, then stopped after an Active Directory change           | The keytab was re-exported, or the service account's password was reset, so the key version number moved              | A new keytab, redistributed — [Installation Guide](/installation/installation.md). Nothing in OpenIAM will fix this, and the whole population fails at once                             |
| Worked yesterday, stopped for everybody, nothing changed        | The proxy host's resolver was replaced on a DHCP lease renewal by one that does not hold the Active Directory records | Ask for the resolver to be **pinned** — see [Names have to agree](#names-have-to-agree-and-dns-is-where-they-stop-agreeing)                                                             |
| Works by short name or IP, fails by FQDN, or the reverse        | The service principal, the hostname and the URL disagree                                                              | The URL users type must be the FQDN in the service principal. Either align the URL and the content provider's **Domain Pattern**, or have an additional service principal registered    |
| Works for one user, fails for another                           | The second user has no OpenIAM identity on the content provider's managed system                                      | Create the identity, or run a synchronization from Active Directory                                                                                                                     |
| Change made, no effect for a few minutes                        | The cache sweep                                                                                                       | Wait out `org.openiam.am.uri.federation.threadsweep` (30 s) and `org.openiam.content.provider.threadsweep` (300 s) before you conclude anything                                         |

## Why it fails the way it does

Once SPNEGO has validated the ticket, the gateway calls OpenIAM with the principal instead of a password. Three things about what OpenIAM does with that call decide whether Kerberos works, and all three are OpenIAM configuration you own.

**The principal is looked up on the content provider's managed system.** If no identity matches, the OpenIAM log records `Proxy identity not found for principal '<p>'` and the answer to the gateway is `IDENTITY_NOT_FOUND`. So the content provider's **Managed System** must be the one your Active Directory identities live on, and the Kerberos username must equal the login on it. That log line, with `<p>` in it, is the most useful single piece of evidence on this page: it tells you exactly what string arrived.

**The password check is skipped only if a Kerberos rule applies.** OpenIAM decides to skip the password by asking whether the `KERB_AUTH` authentication level grouping is required for this request — the level ID comes from `org.openiam.auth.level.kerberos.id` and ships as `KERB_AUTH`. With no Kerberos rule in scope, OpenIAM does not skip it: it attempts a *password* login for a principal it has no password for, and the request fails. There is no message saying "no Kerberos rule applied", which is why this is worth knowing in advance.

**Pattern rules override content provider rules — they do not merge.** If the matched URI pattern carries any rules of its own, those are used and the content provider's are not consulted at all. This is the single most common Kerberos misconfiguration: the rule is added to the content provider, but the URI pattern the login flow actually hits already carries its own rules, so the Kerberos rule is never reached. See [The authentication model](/administration-guide/security/authentication-model.md) for the same behaviour in general terms.

## Names have to agree, and DNS is where they stop agreeing

Kerberos is name-sensitive in a way that nothing else on the gateway is. Four names must be identical, and if any one of them drifts the failure looks like a keytab problem:

* the service principal registered in Active Directory, `HTTP/<proxy FQDN>`;
* the proxy host's own hostname;
* the forward DNS A record and its matching reverse PTR record;
* the URL your users actually type, which is also the **Domain Pattern** on the content provider.

Two of those are yours: the content provider's **Domain Pattern** and the URL you publish. The other two — the proxy host's hostname, and how that host resolves its own name and the domain controller's — are host configuration belonging to the [Installation Guide](/installation/installation.md).

Ask for one thing specifically when you hand this over: that the proxy host's resolver is **pinned**, not inherited from DHCP. This is the failure that arrives days or weeks later as *"Kerberos stopped working and nobody changed anything"* — a lease renewal replaced the nameserver with one that does not hold the Active Directory records, and every ticket validation fails at once. A working setup that has never survived a lease renewal has not been tested. The symptom, from where you sit: sign-in that worked yesterday now silently falls back to the login form for everybody at once, with no OpenIAM change and nothing in the audit log, because the gateway never reaches OpenIAM at all.

## Reference topology

The placeholders used above map onto the demo setup OpenIAM's own material is written against. Three hosts, three jobs, and no shortcuts between them: the ticket is issued by the domain controller, presented by the workstation, and validated on the proxy host. When something fails, establish which of the three you are actually testing before you change anything on any of them.

| Host                     | Role                                                                                                                                                                                    |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rproxy.openiamtest.com` | The host where the Access Gateway is configured. Here `<AD_DOMAIN>` is `openiamtest.com`, `<AD_REALM>` is `OPENIAMTEST.COM`, and the service principal is `HTTP/rproxy.openiamtest.com` |
| `DC1.openiamtest.com`    | The Windows Active Directory server acting as the key distribution centre. It is also the only nameserver that knows the Active Directory records Kerberos depends on                   |
| `PC1.openiamtest.com`    | The domain-joined client machine where the user logs in and where SSO is tested                                                                                                         |

## Roll it back

Kerberos comes out in one change at each layer, the layers are independent, and either one alone restores password sign-in.

**The layer you own.** Remove **Def. Kerberos Auth Rule** from the URI patterns and from the content provider, then allow the cache sweep. Password sign-in resumes on the next sweep, and this is the faster of the two for you because it needs nobody else.

**The layer you ask for.** Turning the Kerberos and SPNEGO directives off in the proxy configuration, with a restart — [Installation Guide](/installation/installation.md). Password sign-in through the gateway resumes immediately once it is done.

Do either, or both. Ask for the Kerberos client configuration and the keytab to be **left in place**: they do nothing on their own, and removing them means the whole export has to be repeated. For the same reason, do not have the Active Directory service account or the service principal deleted as part of a rollback — recreating them invalidates any keytab still in the field.

## Related

* [Protect an application behind the Access Gateway](/administration-guide/gateway/protect-an-application.md) — the gateway this page assumes is already working
* [Access Gateway reference](/administration-guide/gateway/access-gateway-reference.md#kerberos) — the Kerberos directives and the properties named here
* [Troubleshoot the Access Gateway](/administration-guide/gateway/troubleshoot-the-gateway.md) — when the failure is the gateway rather than Kerberos
* [Change configuration safely](/administration-guide/start/change-safely.md) — the break-glass administrator this page assumes

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/gateway/kerberos.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
