apache / apache/druid

Kerberos authenticator sends 403 and bypasses auth chain when hadoop.auth cookie has been cleared to empty value

Open
#19,519 0 comments 0 reactions 0 assignees View on GitHub
Uncategorized problem report
Dominant language
Java
Stars
14.1k
Forks
3.8k
Avg merge
2d 58m
Merged PRs (30d)
233

Description

### Affected Version

Druid 35.x (confirmed), likely all versions with `druid-kerberos` extension.

### Description

When using a mixed authenticator chain of `["ldap", "kerberos"]` (or any chain where Kerberos is not the only authenticator), users accessing the web console encounter an HTTP 403 error after their Kerberos authentication session expires:

```
HTTP ERROR 403 org.apache.hadoop.security.authentication.util.SignerException: Invalid signed text:
URI: /unified-console.html
STATUS: 403
MESSAGE: org.apache.hadoop.security.authentication.util.SignerException: Invalid signed text:
```

Clearing all browser cookies for the Druid hostname resolves the issue temporarily. Simply setting the `hadoop.auth` cookie to empty does not reproduce the issue, because the browser will also attempt SPNEGO negotiation in that case — the real problem is described below.

---

**Root cause — two interacting bugs:**

**Bug 1: Cookie "clear" does not instruct the browser to delete the cookie.**

When a Kerberos-authenticated session ends (token expiry, SPNEGO failure, or any unauthenticated request), `doFilterSuper` in `KerberosAuthenticator` calls:

```java
tokenToAuthCookie(httpResponse, "", getCookieDomain(), getCookiePath(), 0, false, isHttps);
```

The resulting `Set-Cookie` header is:

```
hadoop.auth=; Path=/; HttpOnly
```

No `Max-Age=0` or past `Expires` directive is included. Browsers treat this as setting a session cookie with an empty value rather than deleting the cookie. On subsequent requests, the browser keeps sending `hadoop.auth=` (empty value).

**Bug 2: An empty cookie value short-circuits the entire authenticator chain with a 403.**

In `KerberosAuthenticator.getToken()`, the cookie value is passed directly to `Signer.verifyAndExtract()` without checking whether it is empty:

```java
tokenStr = cookie.getValue(); // ""
tokenStr = mySigner.verifyAndExtract(tokenStr); // throws SignerException: "Invalid signed text:"
```

`Signer.verifyAndExtract("")` throws `SignerException` because the empty string contains no `&s=` signature separator. This exception is caught and stored as `authenticationEx`. Later in `doFilterSuper`:

```java
if (authenticationEx == null) {
filterChain.doFilter(request, response); // pass to next authenticator (e.g. LDAP)
} else {
httpResponse.sendError(errCode, authenticationEx.getMessage()); // 403, chain bypassed
}
```

Because `authenticationEx` is non-null, the filter immediately sends a 403 error and never passes the request to other authenticators in the chain. In a `["ldap", "kerberos"]` setup, the LDAP authenticator never gets a chance to handle the request, so the user cannot recover by entering their LDAP credentials — they see a 403 with no login prompt.

---

**Reproduction steps:**

1. Configure Druid with an authenticator chain that includes both LDAP and Kerberos (e.g. `druid.auth.authenticatorChain=["ldap","kerberos"]` with `skipOnFailure=true` on both).
2. Log in to the Druid web console via SPNEGO/Kerberos. The browser receives a signed `hadoop.auth` cookie (valid for ~10 hours by default).
3. Wait for the Kerberos authentication token to expire (default: 36000 seconds / 10 hours).
4. Attempt to access any Druid UI page (e.g. `/unified-console.html`).
5. Observe HTTP 403 with `SignerException: Invalid signed text:`.
6. Check browser cookies — `hadoop.auth` is present with an empty value.

**Workaround:** Manually delete (not clear) the `hadoop.auth` browser cookie for the Druid hostname.

Contributor guide

Open the contributing guide

Research direction

Start by reading KerberosAuthenticator.getToken() and doFilterSuper(), then trace the hadoop.auth cookie handling and Signer.verifyAndExtract() call. Reproduce the empty-cookie case with a mixed LDAP/Kerberos authenticator chain. Done means an expired or empty Kerberos cookie no longer causes the 403 path to bypass the remaining authenticator chain.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
authentication, backend, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.