skip to content

What does a KDC's KDC_ERR_PREAUTH_REQUIRED reply to a Kerberos AS-REQ tell the client to do?

level: middleimportance: must knowfreq 50%

answer

  1. the first request is supposed to fail
  2. an error that advertises what to send
  3. e-data lists acceptable pre-authentication types
  4. encrypted current timestamp as proof
  5. PA-ENC-TS-ENC under the long-term key

basics

~20 s

KDC_ERR_PREAUTH_REQUIRED (25) means the KDC will not issue a ticket until the client proves it holds its long-term key. The error's e-data carries METHOD-DATA listing the pre-authentication types accepted, and the client resends the AS-REQ with PA-ENC-TIMESTAMP.

solid answer

~40 s

Where a principal's policy requires Kerberos pre-authentication, the first `AS-REQ` is expected to fail: the KDC answers with a `KRB-ERROR` carrying `KDC_ERR_PREAUTH_REQUIRED (25)`, and the `e-data` field holds `METHOD-DATA` — a list of `PA-DATA` entries naming which pre-authentication types it will accept and the parameters the client needs, typically `pa-etype-info2 (padata-type 19)`, sometimes `pa-etype-info (padata-type 11)` or `pa-pw-salt (padata-type 3)`. The client derives its long-term key using those parameters and resends the same request with a `padata` entry of type `pa-enc-timestamp (padata-type 2)`, whose value is a `PA-ENC-TS-ENC` structure — `patimestamp` and optional `pausec` — encrypted under that key. A current timestamp the client could only have encrypted with the long-term key is the proof of possession; the KDC decrypts it, checks the time against its own clock, and issues the `AS-REP`.

code

asn1 · 21 lines
asn1
-- 1. Bare AS-REQ: no padata. KDC answers KRB-ERROR.
KRB-ERROR ::= SEQUENCE {
    msg-type   [1] INTEGER (30),
    error-code [6] Int32,             -- 25 = KDC_ERR_PREAUTH_REQUIRED
    e-data     [12] OCTET STRING      -- holds METHOD-DATA
}

-- METHOD-DATA ::= SEQUENCE OF PA-DATA, e.g.
--   padata-type 19  (pa-etype-info2)
--   padata-type 3   (pa-pw-salt)

-- 2. The client retries with the proof attached.
PA-DATA ::= SEQUENCE {
    padata-type  [1] Int32,           -- 2 = pa-enc-timestamp
    padata-value [2] OCTET STRING     -- encrypted PA-ENC-TS-ENC
}

PA-ENC-TS-ENC ::= SEQUENCE {
    patimestamp [0] KerberosTime,     -- the client's current time
    pausec      [1] Microseconds OPTIONAL
}

go deeper

for a junior

Recall the shape: the client asks, the KDC says 'prove you hold the key first', and the client asks again with an encrypted timestamp attached. The first refusal is normal traffic.

for a middle

Explain the mechanics: error code 25, the METHOD-DATA in e-data that advertises acceptable types, and the PA-ENC-TS-ENC structure encrypted under the long-term key as the proof of possession.

for a senior

Show the diagnosis. Separate code 25 from a pre-authentication failure and from a clock-skew rejection, and say which of the three a login loop, a wrong salt and a drifting host clock each produce.

for a principal

The judgment is about policy uniformity: requiring pre-authentication everywhere costs a round trip and a clock dependency, while exempting principals to make an integration work weakens the guarantee the whole realm rests on.

## The first request is meant to fail The surprising thing about Kerberos pre-authentication is that the protocol's normal path includes an error. A client that does not already know the realm's policy sends a bare `AS-REQ` with no `padata`. Where the requested principal's policy requires pre-authentication, the KDC does not issue anything; it replies with a `KRB-ERROR` (`[APPLICATION 30]`) whose error code is `KDC_ERR_PREAUTH_REQUIRED (25)`. That is not a credential failure and it says nothing about whether the client's key is right. It is the KDC telling the client which proof it must attach, and it is the reason a log full of code 25 on first contact is ordinary traffic rather than an incident. ## What the error actually carries The useful content is in the error's `e-data` field, which holds a `METHOD-DATA` sequence — a list of `PA-DATA` entries. Each entry names a pre-authentication type and may carry parameters the client needs to construct its proof. | `padata-type` | Name | Direction | Purpose | |---|---|---|---| | 2 | `pa-enc-timestamp` | client to KDC | the proof itself: an encrypted `PA-ENC-TS-ENC` | | 3 | `pa-pw-salt` | KDC to client | the salt string the client needs to derive its long-term key | | 11 | `pa-etype-info` | KDC to client | acceptable encryption types with their salts | | 19 | `pa-etype-info2` | KDC to client | the current form of that hint, used in preference to type 11 | | 1 | `pa-tgs-req` | client to KDC | belongs to the ticket-granting exchange, never to the AS exchange | So the error is also a **capability advertisement**. Without it, a client would have to guess both which pre-authentication method the realm accepts and which parameters to derive its key with. ## The second request The client resends the `AS-REQ` unchanged except for one added `padata` entry: 1. It derives its long-term key using the parameters the KDC advertised. 2. It reads its own clock and builds `PA-ENC-TS-ENC` with `patimestamp` and, optionally, `pausec` for sub-second precision. 3. It encrypts that structure under the long-term key and puts the ciphertext in a `PA-DATA` of type 2. 4. It sends the request again, with the same `cname`, `sname` and a fresh `nonce`. The KDC decrypts the value with the key it holds for that principal. Success means the requester holds the long-term key. The timestamp then has to be within the realm's allowed clock skew of the KDC's own time; if it is not, the KDC rejects it with `KRB_AP_ERR_SKEW`. ## Why a timestamp, and what it proves An encrypted **current** timestamp is a cheap freshness proof that costs no extra round trip. A plain encrypted constant would be replayable forever; a timestamp is only valid inside a narrow window, and the KDC can refuse anything outside it. What it proves is exactly one thing: **something holding the principal's long-term key produced this request recently.** It does not prove a person was at a keyboard, it does not prove which host the key was used from, and it does not bind the request to any hardware. ## When the KDC does not ask for it Pre-authentication is a per-principal policy, not a property of the protocol's message flow. Where a principal's policy does not require it, the KDC answers the very first `AS-REQ` with an `AS-REP` — a reply whose `enc-part` is sealed under that principal's long-term key. That is the structural reason realms require pre-authentication by default; what an adversary does with such a reply is the business of the attack-focused material, not of this exchange. ## The other errors you will meet here - `KDC_ERR_ETYPE_NOSUPP (14)` — none of the encryption types the client offered in the request body is acceptable to the KDC for this principal. This is decided before any pre-authentication value is evaluated. - `KDC_ERR_PREAUTH_FAILED` — a pre-authentication value was supplied and did not verify: the wrong key, or the right key derived with the wrong parameters. - `KRB_AP_ERR_SKEW` — the value decrypted, but `patimestamp` is too far from the KDC's clock. - `KDC_ERR_MORE_PREAUTH_DATA_REQUIRED` — a multi-step pre-authentication method is in progress and the exchange is not finished. Telling `KDC_ERR_PREAUTH_REQUIRED (25)` apart from `KDC_ERR_PREAUTH_FAILED` is the single most useful diagnostic distinction in this exchange: the first is the protocol working, the second is a key problem.

  • A KDC returns KDC_ERR_ETYPE_NOSUPP (14) instead. What went wrong?
    None of the encryption types the client listed in the `KDC-REQ-BODY` is one the KDC will use for that principal, so there is nothing to seal a reply with. It is decided from the request body before any pre-authentication value is looked at, which is why a correct key still produces this error.
  • How do you tell KDC_ERR_PREAUTH_REQUIRED apart from KDC_ERR_PREAUTH_FAILED when diagnosing a login loop?
    Code 25 means no pre-authentication value was supplied yet and the KDC is asking for one — the expected first step. `KDC_ERR_PREAUTH_FAILED` means a value was supplied and did not verify, so the client derived the wrong long-term key. A client stuck alternating between the two is deriving its key with parameters the KDC did not advertise.
  • Why does the KDC advertise the pre-authentication types rather than the client simply trying one?
    Because the client must derive its long-term key before it can encrypt anything, and derivation needs parameters the KDC holds — which is what `pa-etype-info2` and `pa-pw-salt` carry. Advertising also lets a realm change accepted methods without every client being reconfigured first.

saying these in an interview costs you the question

  • Says the first AS-REQ failing means the credential was wrong.
  • Claims the client sends its long-term key inside the padata.
  • Thinks the timestamp travels in the clear and is merely compared.
  • Believes pre-authentication is negotiated before any AS-REQ is sent.
  • Says every principal in a realm must use pre-authentication.