# How Kerberos Works, Message by Message

Source: https://startwithidentity.com/guides/protocols/kerberos-message-flow/
Last updated: 2026-11-05
License: content by Start with Identity. Cite the source URL.

---

A Kerberos login is three request and reply pairs between a client, the Key Distribution Center (KDC) and a service: the **AS exchange** gets a ticket-granting ticket (TGT), the **TGS exchange** turns it into a service ticket, and the **AP exchange** presents that ticket to the service. Every message is ASN.1 defined in [RFC 4120 §5](https://www.rfc-editor.org/rfc/rfc4120#section-5). This page decodes each one with fake values, ties the fields to their sections, and lists what each party must check. For what Kerberos is and where it fits, see the [Kerberos standard page](https://startwithidentity.com/standards/kerberos/).

All examples use the realm `EXAMPLE.COM`, user `ada@EXAMPLE.COM` and service `HTTP/app.example.com@EXAMPLE.COM`. Encrypted parts are shown as their decrypted structure, which only the party holding the key can see.

## The sequence at a glance

| # | From → to | Message (`msg-type`) | Spec |
| --- | --- | --- | --- |
| 1 | Client → KDC (88) | `AS-REQ` (10) without pre-authentication | [§3.1.1](https://www.rfc-editor.org/rfc/rfc4120#section-3.1.1), [§5.4.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.4.1) |
| 2 | KDC → client | `KRB-ERROR` (30), code 25 `KDC_ERR_PREAUTH_REQUIRED`, with `PA-ETYPE-INFO2` | [§5.9.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.9.1), [§5.2.7.5](https://www.rfc-editor.org/rfc/rfc4120#section-5.2.7.5) |
| 3 | Client → KDC | `AS-REQ` (10) with `PA-ENC-TIMESTAMP` | [§5.2.7.2](https://www.rfc-editor.org/rfc/rfc4120#section-5.2.7.2) |
| 4 | KDC → client | `AS-REP` (11): TGT plus encrypted session key | [§3.1.3](https://www.rfc-editor.org/rfc/rfc4120#section-3.1.3), [§5.4.2](https://www.rfc-editor.org/rfc/rfc4120#section-5.4.2) |
| 5 | Client → KDC | `TGS-REQ` (12) with `PA-TGS-REQ` carrying an AP-REQ | [§3.3.1](https://www.rfc-editor.org/rfc/rfc4120#section-3.3.1), [§5.2.7.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.2.7.1) |
| 6 | KDC → client | `TGS-REP` (13): service ticket | [§3.3.3](https://www.rfc-editor.org/rfc/rfc4120#section-3.3.3) |
| 7 | Client → service | `AP-REQ` (14), inside SMB, LDAP SASL or HTTP `Negotiate` | [§3.2.2](https://www.rfc-editor.org/rfc/rfc4120#section-3.2.2), [§5.5.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.5.1) |
| 8 | Service → client | `AP-REP` (15), if mutual authentication was requested | [§3.2.4](https://www.rfc-editor.org/rfc/rfc4120#section-3.2.4), [§5.5.2](https://www.rfc-editor.org/rfc/rfc4120#section-5.5.2) |

## Messages 1 to 3: AS-REQ and pre-authentication

```
AS-REQ ::= [APPLICATION 10] {
  pvno      5,
  msg-type  10,
  padata    [ PA-ENC-TIMESTAMP (2): EncryptedData {
                etype 18, cipher <PA-ENC-TS-ENC { patimestamp 20261105140211Z,
                                                  pausec 412 } encrypted with ada's key> },
              PA-PAC-REQUEST (128): include-pac TRUE ],
  req-body {
    kdc-options  forwardable, renewable, canonicalize,
    cname        { name-type NT-PRINCIPAL (1), name-string ["ada"] },
    realm        "EXAMPLE.COM",
    sname        { name-type NT-SRV-INST (2), name-string ["krbtgt", "EXAMPLE.COM"] },
    till         20261106000211Z,
    rtime        20261112140211Z,
    nonce        1953746982,
    etype        [ 18, 17, 20, 19 ] } }
```

The first attempt (message 1) is the same without `padata`. A KDC that requires pre-authentication answers with `KRB-ERROR` code 25 and a `PA-ETYPE-INFO2` hint listing the encryption type and salt to use, and the client retries. The default salt is the realm followed by the name components with no separator, here `EXAMPLE.COMada` (RFC 4120 [§4](https://www.rfc-editor.org/rfc/rfc4120#section-4)).

| Field | Meaning | Spec |
| --- | --- | --- |
| `pvno`, `msg-type` | Always 5; 10 for AS-REQ, 12 for TGS-REQ. | [§5.4.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.4.1) |
| `padata` `PA-ENC-TIMESTAMP` (type 2) | Current time encrypted in the client's long-term key: proof the client knows the password before the KDC returns anything crackable. | [§5.2.7.2](https://www.rfc-editor.org/rfc/rfc4120#section-5.2.7.2) |
| `PA-PAC-REQUEST` (type 128) | Microsoft extension asking for a PAC in the ticket. | [MS-KILE](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/2a32282e-dd48-4ad9-a542-609804b02cc9), registered in RFC 4120 §7.5.2 |
| `kdc-options` | Flags requested for the ticket: `forwardable` (1), `renewable` (8), and `canonicalize` (15, reserved in RFC 4120 and defined in [RFC 6806](https://www.rfc-editor.org/rfc/rfc6806)). | [§5.4.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.4.1), [§2](https://www.rfc-editor.org/rfc/rfc4120#section-2) |
| `cname`, `realm` | Client principal and realm. `cname` appears only in AS-REQ. | [§5.4.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.4.1), [§5.2.2](https://www.rfc-editor.org/rfc/rfc4120#section-5.2.2) |
| `sname` | `krbtgt/EXAMPLE.COM`, the ticket-granting service. | [§7.3](https://www.rfc-editor.org/rfc/rfc4120#section-7.3) |
| `till`, `rtime` | Requested end time and renewable-until time; the KDC may shorten them. | [§5.4.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.4.1) |
| `nonce` | Random number the KDC must echo inside the encrypted reply. | [§5.4.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.4.1), [§3.1.5](https://www.rfc-editor.org/rfc/rfc4120#section-3.1.5) |
| `etype` | Encryption types in preference order: 18 aes256-cts-hmac-sha1-96, 17 aes128 ([RFC 3962](https://www.rfc-editor.org/rfc/rfc3962)), 20 and 19 the SHA-2 variants ([RFC 8009](https://www.rfc-editor.org/rfc/rfc8009)). Seeing 23 (RC4-HMAC) here is a finding. | §5.4.1, [RFC 8429 §7](https://www.rfc-editor.org/rfc/rfc8429#section-7) |

## Message 4: AS-REP

```
AS-REP ::= [APPLICATION 11] {
  pvno 5, msg-type 11,
  crealm "EXAMPLE.COM",
  cname  { NT-PRINCIPAL, ["ada"] },
  ticket {                                   -- the TGT, opaque to the client
    tkt-vno 5, realm "EXAMPLE.COM", sname krbtgt/EXAMPLE.COM,
    enc-part { etype 18, kvno 2, cipher <EncTicketPart encrypted with the krbtgt key> } },
  enc-part { etype 18, kvno 7, cipher <EncASRepPart encrypted with ada's key> } }

EncASRepPart (decrypted by the client) {
  key        { keytype 18, keyvalue <TGT session key> },
  last-req   [...],
  nonce      1953746982,
  flags      forwardable, renewable, initial, pre-authent,
  authtime   20261105140211Z,
  endtime    20261106000211Z,
  renew-till 20261112140211Z,
  srealm     "EXAMPLE.COM",
  sname      krbtgt/EXAMPLE.COM }
```

| Field | Meaning | Spec |
| --- | --- | --- |
| `ticket` | The TGT. Its `enc-part` is encrypted with the `krbtgt` key, so the client cannot read or alter it. | [§5.3](https://www.rfc-editor.org/rfc/rfc4120#section-5.3) |
| `enc-part` | Encrypted with the client's key; contains the session key the client will use with the TGS. | [§5.4.2](https://www.rfc-editor.org/rfc/rfc4120#section-5.4.2) |
| `nonce` | Must equal the request nonce, proving the reply is fresh. | [§3.1.5](https://www.rfc-editor.org/rfc/rfc4120#section-3.1.5) |
| `flags` | `initial` (from the AS exchange) and `pre-authent` (the client was pre-authenticated). | [§5.3](https://www.rfc-editor.org/rfc/rfc4120#section-5.3), [§2](https://www.rfc-editor.org/rfc/rfc4120#section-2) |
| `kvno` | Key version number, so a service can pick the right key after a password change. | [§5.2.9](https://www.rfc-editor.org/rfc/rfc4120#section-5.2.9) |

## Messages 5 and 6: TGS-REQ and TGS-REP

```
TGS-REQ ::= [APPLICATION 12] {
  pvno 5, msg-type 12,
  padata [ PA-TGS-REQ (1): AP-REQ { ticket <the TGT>,
             authenticator <Authenticator encrypted with the TGT session key> } ],
  req-body {
    kdc-options forwardable, canonicalize,
    realm  "EXAMPLE.COM",
    sname  { NT-SRV-INST, ["HTTP", "app.example.com"] },
    till   20261106000211Z,
    nonce  287364510,
    etype  [ 18, 17 ] } }
```

The TGS-REP has the same shape as the AS-REP, but its `ticket` is the **service ticket**, encrypted with the key of `HTTP/app.example.com`, and its `enc-part` is encrypted with the TGT session key rather than the user's password key ([§3.3.3](https://www.rfc-editor.org/rfc/rfc4120#section-3.3.3)). In Active Directory the service key is derived from the password of whichever account holds that SPN. That single fact is [Kerberoasting](https://startwithidentity.com/techniques/kerberoasting/): any authenticated user can request this ticket and attack the service account's password offline.

## Messages 7 and 8: AP-REQ and AP-REP

```
AP-REQ ::= [APPLICATION 14] {
  pvno 5, msg-type 14,
  ap-options mutual-required,
  ticket { tkt-vno 5, realm "EXAMPLE.COM", sname HTTP/app.example.com,
           enc-part { etype 18, kvno 4, cipher <EncTicketPart> } },
  authenticator { etype 18, cipher <Authenticator encrypted with the service session key> } }

EncTicketPart (decrypted by the service with its own key) {
  flags forwardable, pre-authent,
  key   { keytype 18, keyvalue <service session key> },
  crealm "EXAMPLE.COM", cname { NT-PRINCIPAL, ["ada"] },
  transited { tr-type 1, contents "" },
  authtime 20261105140211Z, starttime 20261105140230Z, endtime 20261106000211Z,
  authorization-data [ AD-IF-RELEVANT [ AD-WIN2K-PAC (128): <PAC> ] ] }

Authenticator (decrypted with the session key) {
  authenticator-vno 5,
  crealm "EXAMPLE.COM", cname { NT-PRINCIPAL, ["ada"] },
  cksum  <checksum binding the application request, if any>,
  cusec  418211, ctime 20261105140230Z,
  subkey { keytype 18, keyvalue <optional subkey> },
  seq-number 1093845021 }
```

Over HTTP this AP-REQ travels inside a SPNEGO token: `Authorization: Negotiate YIIH...` ([RFC 4559 §4](https://www.rfc-editor.org/rfc/rfc4559#section-4)). With `mutual-required`, the service replies with an AP-REP whose encrypted part repeats `ctime` and `cusec`, proving it could decrypt the ticket ([§5.5.2](https://www.rfc-editor.org/rfc/rfc4120#section-5.5.2)).

| Field | Meaning | Spec |
| --- | --- | --- |
| `ap-options` | `use-session-key` (1) for user-to-user, `mutual-required` (2). | [§5.5.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.5.1) |
| `EncTicketPart.key` | The session key the KDC generated for this client and service. | [§5.3](https://www.rfc-editor.org/rfc/rfc4120#section-5.3) |
| `authtime`, `starttime`, `endtime` | When the user authenticated and the ticket's validity window. | [§5.3](https://www.rfc-editor.org/rfc/rfc4120#section-5.3) |
| `authorization-data` | Wrapped in `AD-IF-RELEVANT`; in AD carries the PAC (type 128). | [§5.2.6](https://www.rfc-editor.org/rfc/rfc4120#section-5.2.6), [MS-PAC](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/166d8064-c863-41e1-9c23-edaaa5f36962) |
| `Authenticator.ctime`, `cusec` | Client time, the basis of replay protection. | [§5.5.1](https://www.rfc-editor.org/rfc/rfc4120#section-5.5.1) |
| `Authenticator.cksum` | Binds the authenticator to application data, for example GSS-API channel bindings. | §5.5.1, [RFC 4121 §4.1.1](https://www.rfc-editor.org/rfc/rfc4121#section-4.1.1) |

## The checks each party must run

**Client, on AS-REP** ([§3.1.5](https://www.rfc-editor.org/rfc/rfc4120#section-3.1.5))

1. `cname` and `crealm` in the reply match the request; the decrypted `nonce` equals the one sent; `sname` and `srealm` are the expected TGS.
2. A host that uses a password login to grant **local** access must not trust the AS-REP alone. RFC 4120 §3.1.5 says decrypting it "is not sufficient for the host to verify the identity of the user"; the host must also get and verify a ticket for its own service key, or a spoofed KDC can log anyone in.

**KDC**

3. Require pre-authentication for every account ([§5.2.7.2](https://www.rfc-editor.org/rfc/rfc4120#section-5.2.7.2)). Without it, anyone can request an AS-REP for that user and crack the encrypted part offline.
4. Issue only strong encryption types and never RC4 or DES for new keys ([RFC 8429 §7](https://www.rfc-editor.org/rfc/rfc8429#section-7), [RFC 6649](https://www.rfc-editor.org/rfc/rfc6649)).

**Service, on AP-REQ** ([§3.2.3](https://www.rfc-editor.org/rfc/rfc4120#section-3.2.3))

5. Decrypt the ticket with its own key at the `kvno` indicated (`KRB_AP_ERR_BADKEYVER`, `KRB_AP_ERR_BAD_INTEGRITY` on failure), then decrypt the authenticator with the ticket's session key.
6. `cname` and `crealm` in the authenticator match the ticket (`KRB_AP_ERR_BADMATCH`), and client addresses match if present.
7. Client time within the allowable clock skew (`KRB_AP_ERR_SKEW`, RFC 4120 uses 5 minutes as its example), and the authenticator is not in the replay cache (`KRB_AP_ERR_REPEAT`); ticket not yet valid or expired gives `KRB_AP_ERR_TKT_NYV` or `KRB_AP_ERR_TKT_EXPIRED`.
8. **Authorize separately.** Passing these checks "provides only authentication of the named principal" (§3.2.3). In Active Directory, validate the PAC signatures as [MS-PAC](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/166d8064-c863-41e1-9c23-edaaa5f36962) describes before trusting group SIDs.

## Common implementation mistakes, with the CVEs and techniques behind them

| Mistake | What goes wrong | Real examples |
| --- | --- | --- |
| PAC signatures or requester SID not validated | A forged or borrowed PAC grants privileges | [CVE-2024-26248](https://startwithidentity.com/cves/cve-2024-26248/), [CVE-2024-29056](https://startwithidentity.com/cves/cve-2024-29056/), [CVE-2026-27912](https://startwithidentity.com/cves/cve-2026-27912/) |
| A step skipped in a protocol extension | Identity forged through S4U or certificate logon | [CVE-2025-60704](https://startwithidentity.com/cves/cve-2025-60704/) (S4U), [CVE-2025-26647](https://startwithidentity.com/cves/cve-2025-26647/) (PKINIT), [CVE-2022-26923](https://startwithidentity.com/cves/cve-2022-26923/) |
| Client trusts a KDC reply it cannot authenticate | KDC impersonation by a machine in the middle | [CVE-2024-20674](https://startwithidentity.com/cves/cve-2024-20674/) |
| Tickets reflected back to the issuing host | Elevation of privilege over SMB | [CVE-2025-33073](https://startwithidentity.com/cves/cve-2025-33073/), [CVE-2025-58726](https://startwithidentity.com/cves/cve-2025-58726/) |
| RC4 still issued for service tickets | Service account passwords cracked offline | [CVE-2026-20833](https://startwithidentity.com/cves/cve-2026-20833/), [Kerberoasting](https://startwithidentity.com/techniques/kerberoasting/) |
| SPN uniqueness checked on look-alike strings | Service name hijack and NTLM downgrade | [CVE-2026-25177](https://startwithidentity.com/cves/cve-2026-25177/) |
| Over-broad delegation | A service impersonates any user to any service | [Kerberos delegation abuse](https://startwithidentity.com/techniques/kerberos-delegation-abuse/) |
| Certificate templates trusted for logon | PKINIT logons as other users | [AD CS certificate template abuse](https://startwithidentity.com/techniques/adcs-certificate-template-abuse/), [CVE-2024-49019](https://startwithidentity.com/cves/cve-2024-49019/) |

## Try it locally

There is no browser tool for Kerberos, which runs over raw TCP and UDP to the KDC. On a test realm, MIT Kerberos's [kinit](https://web.mit.edu/kerberos/krb5-latest/doc/user/user_commands/kinit.html) runs the AS exchange and [klist](https://web.mit.edu/kerberos/krb5-latest/doc/user/user_commands/klist.html) shows the result: `klist -e -f` prints each ticket's encryption type and flags, so you can confirm no ticket uses etype 23 and that the `pre-authent` flag is set. A packet capture on port 88 shows messages 1 to 6 in clear structure, with the encrypted parts opaque.

## Related

[Kerberos standard page](https://startwithidentity.com/standards/kerberos/), [how LDAP works, message by message](https://startwithidentity.com/guides/protocols/ldap-message-flow/), [how RADIUS works, message by message](https://startwithidentity.com/guides/protocols/radius-message-flow/). Glossary: [Kerberos](https://startwithidentity.com/glossary/kerberos/), [NTLM](https://startwithidentity.com/glossary/ntlm/), [Active Directory](https://startwithidentity.com/glossary/active-directory/).
