Skip to content

feat: Add Kerberos support#4640

Open
Jabejixo wants to merge 3 commits intodexidp:masterfrom
Jabejixo:add-kerberos-supportt
Open

feat: Add Kerberos support#4640
Jabejixo wants to merge 3 commits intodexidp:masterfrom
Jabejixo:add-kerberos-supportt

Conversation

@Jabejixo
Copy link
Copy Markdown
Contributor

Overview

Add Kerberos/SPNEGO Single Sign-On support for the LDAP connector, enabling seamless authentication for users in Active Directory/Kerberos environments without requiring password entry.

What this PR does / why we need it

This PR adds optional Kerberos (SPNEGO) authentication to the LDAP connector. When enabled, Dex can authenticate users via the Authorization: Negotiate header on the password login endpoint, completing the OIDC flow without rendering the password form.

Why we need it:

  • Enterprise environments with Active Directory heavily rely on Kerberos for SSO
  • Users on domain-joined machines can authenticate transparently without entering credentials
  • Reduces friction and improves security by leveraging existing Kerberos infrastructure

Key features:

  • Validates SPNEGO tokens using a service keytab
  • Maps Kerberos principals to LDAP usernames (localpart, sAMAccountName, or userPrincipalName)
  • Optional realm validation
  • Configurable fallback to password form when SPNEGO fails
  • Full compatibility with existing LDAP connector functionality

Configuration example:

connectors:
- type: ldap
  id: corp-ldap
  config:
    # ... existing LDAP config ...
    kerberos:
      enabled: true
      keytabPath: /etc/dex/krb5.keytab
      expectedRealm: EXAMPLE.COM
      usernameFromPrincipal: localpart
      fallbackToPassword: false

Special notes for your reviewer

  • The SPNEGOAware interface in connector/spnego.go is designed to be generic, allowing other connectors to implement SPNEGO in the future if needed
  • All Kerberos-specific code is isolated in connector/ldap/kerberos.go for maintainability
  • Comprehensive test coverage included with mock validators

@nabokihms nabokihms added the release-note/new-feature Release note: Exciting New Features label Mar 13, 2026
@nabokihms nabokihms self-requested a review March 13, 2026 12:50
Copy link
Copy Markdown
Member

@nabokihms nabokihms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, looks good. Some minor suggestions. And there are also conflicts.

Comment thread connector/ldap/kerberos.go Outdated
Comment thread connector/ldap/kerberos.go Outdated
Comment thread connector/ldap/kerberos.go Outdated
Comment thread connector/ldap/kerberos.go
Comment thread connector/ldap/kerberos.go Outdated
@nabokihms nabokihms requested a review from sagikazarmark March 17, 2026 12:28
Signed-off-by: Ivan Zvyagintsev <ivan.zvyagintsev@flant.com>
Signed-off-by: Ivan Zvyagintsev <ivan.zvyagintsev@flant.com>
Signed-off-by: Ivan Zvyagintsev <ivan.zvyagintsev@flant.com>
@Jabejixo Jabejixo force-pushed the add-kerberos-supportt branch from d5ff7e9 to d53acc6 Compare March 17, 2026 13:36
@Jabejixo Jabejixo requested a review from nabokihms March 17, 2026 13:42
@nabokihms
Copy link
Copy Markdown
Member

All good from my side here. @sagikazarmark do you have any objections to merging this?

@KubaFajny
Copy link
Copy Markdown

We tracked a Kerberos/SPNEGO issue in the LDAP connector implementation from branch add-kerberos-supportt and ended up with a working fix on our side.

What we observed

  • Firefox completed the Kerberos login flow.
  • Chrome/Edge did not, even with browser allowlist/policy configured.
  • With additional tracing, we found three separate issues in the current connector implementation.

Errors observed in the connector flow

  • KRB Error: (34) KRB_AP_ERR_REPEAT Request is a replay - replay detected
  • kerberos: credentials missing in context
  • err="no credentials in context"

Issues found

  1. AcceptSecContext() was effectively invoked twice for the same authenticated request.

    • First in ValidateRequest()
    • Then again in ContinueToken()
    • This correlated with the replay-style failure:
      • KRB_AP_ERR_REPEAT Request is a replay - replay detected
  2. Credentials were read from the returned context using a typed key:

    • type ctxCredentialsKeyType string
    • const ctxCredentialsKey ctxCredentialsKeyType = "github.com/jcmturner/gokrb5/v8/ctxCredentials"
    • In practice, this did not match how credentials were stored in the context, so ctx.Value(...) returned nil.
    • That matched the runtime errors:
      • kerberos: credentials missing in context
      • err="no credentials in context"
    • Using a plain string key resolved the issue for us.
  3. On the initial request without Authorization: Negotiate, the server was returning a continuation token immediately:

    • WWW-Authenticate: Negotiate <token>
    • Firefox tolerated this, but Chrome/Edge did not start SPNEGO from that response.
    • Returning a bare initial challenge instead:
      • WWW-Authenticate: Negotiate
        fixed Chrome/Edge interoperability for us.

What fixed it

  • Refactor validation so the main request path performs one AcceptSecContext() call only.
  • Return a continuation token only when the client already sent Authorization: Negotiate ... and AcceptSecContext() returns ContinueNeeded.
  • Read credentials from context using a plain string key, with optional fallback for the old typed key.

Effective behavior that worked

  1. No auth header:
    • return bare 401 + WWW-Authenticate: Negotiate
  2. Client sends Authorization: Negotiate ...
    • call AcceptSecContext() once
    • if ContinueNeeded, return 401 + WWW-Authenticate: Negotiate <response-token>
    • if Complete, extract credentials from context and continue

With these changes applied, the connector is now deployed and fully working for our client in production-like use.

I am attaching the patch that implements these changes.

https://gist.github.com/KubaFajny/4d1c7c8f3816591642eb397b62b67ed6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/new-feature Release note: Exciting New Features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants