Kerberos Authentication Fails — Duplicate SPN and KRB_AP_ERR_MODIFIED
When Kerberos logs a KRB_AP_ERR_MODIFIED error, the service ticket was encrypted with one account’s key and decrypted with another’s — nearly always because the same Service Principal Name is registered on two accounts, and the fix is to find the duplicate and remove it.
Service Principal Name — e.g. HTTP/app.corp.example.com. Maps a service to the account that runs it.
Encrypted by the KDC with the target account’s key. Only that account can decrypt it.
The client’s proof that the key the service used does not match the key the ticket was sealed with.
Introduction
A web application, SQL connection, or file service that used integrated Windows authentication suddenly falls back to prompting for a password, or fails outright. Some users are fine; others hitting the same name are not. The application log or System log carries a Kerberos Event ID 4, and the phrase in it — KRB_AP_ERR_MODIFIED — sounds like something was tampered with.
Nothing was tampered with. The error is Kerberos being precise about a key mismatch, and the most frequent reason for that mismatch is mundane: someone registered the same SPN on a second account — often a service account and the computer account, or two service accounts — and now the KDC and the service disagree about which key to use. Find the duplicate, remove the wrong one, and it clears.
What You’re Seeing
The signature is Event ID 4 from source Kerberos. Its own text names the likely cause — identically keyed accounts — which is the clue that sends you to the SPN check:
Log Name: System
Source: Security-Kerberos
Event ID: 4
Level: Error
The Kerberos client received a KRB_AP_ERR_MODIFIED error from the
server app01$. The target name used was HTTP/app.corp.example.com.
This indicates that the target server failed to decrypt the ticket
provided by the client. This can occur when the target server
principal name (SPN) is registered on an account other than the
account the target service is using. Ensure that the target SPN is
only registered on the account used by the server.
What It Actually Means
When a client wants to use a service, it asks the KDC for a ticket to that service’s SPN. The KDC finds the account that owns the SPN, encrypts the ticket with a key derived from that account’s password, and hands it back. The client presents the ticket to the service, and the service decrypts it with its own key. If the account the KDC used and the account the service actually runs as are different, the keys differ and decryption fails — that failure is KRB_AP_ERR_MODIFIED.
Two situations produce that split. In the first, the SPN is registered on the wrong single account — the service runs as svc-app but the SPN sits on the computer object. In the second, and more common, the SPN is registered twice — on both svc-app and the computer, or on two service accounts. The KDC picks one; the service uses the other. This connects to the identity fundamentals in the security basics post and the Kerberos flow in the authentication post.
Step 1: Find Duplicate SPNs
The first command is the whole game. setspn -X scans the entire directory and lists every SPN that is registered on more than one account. If your failing SPN appears, you have your answer immediately.
# Scan the whole forest for duplicate SPNs - run this first
setspn -X
# Ask specifically which account(s) hold the failing SPN
setspn -Q HTTP/app.corp.example.com
# List every SPN registered on a given account
setspn -L svc-app
setspn -L app01
setspn -X prints “found N group of duplicate SPNs” and names the accounts. If HTTP/app.corp.example.com is listed under both a service account and a computer object, that duplication is the fault. setspn -Q confirms it in isolation for the one name you care about.
Step 2: Identify the Correct Owner
Before deleting anything, establish which account the service actually runs as — that is the account that must keep the SPN. Check the service’s logon identity, and match it to the SPN owner.
# What identity does the service run under? (the SPN must live here)
Get-CimInstance Win32_Service -Filter "Name='w3svc'" |
Select-Object Name, StartName
# Confirm the account and its current SPNs
setspn -L svc-app
# For app-pool / custom services, check the configured identity too
sc.exe qc <servicename>
svc-app, the SPN belongs on svc-app — not on the computer object, and not on a second service account. Decide the correct owner first; only then remove the wrong registration.
Step 3: Remove the Duplicate
Delete the SPN from the account that should not have it, leaving it on the correct owner. Then verify the duplicate is gone.
# Remove the SPN from the WRONG account (here, the computer object)
setspn -D HTTP/app.corp.example.com app01
# Confirm the SPN now resolves to exactly one account
setspn -Q HTTP/app.corp.example.com
# Re-scan to confirm no duplicates remain
setspn -X
setspn -D is a directory change — removing the SPN from the correct account by mistake will break the working half of the service. Double-check the account name in the delete command against the service’s real logon identity before you run it. After the change, the affected clients may need to discard cached tickets (klist purge) or wait for ticket lifetime to expire.
Common Causes
KRB_AP_ERR_MODIFIED has a short list of causes. Duplicate and misplaced SPNs dominate; the rest are worth knowing so you do not misdiagnose.
| Cause | How to Confirm | Fix |
|---|---|---|
| SPN registered on two accounts | setspn -X lists the SPN as a duplicate group. |
setspn -D the SPN from the wrong account; keep it on the service’s logon account. |
| SPN on the wrong single account | setspn -Q shows one owner, but not the account the service runs as. |
Delete from the wrong account and add to the correct one (setspn -S). |
| Service account changed, SPN not moved | Service was switched to a new identity; SPN still on the old account or computer. | Move the SPN to the new logon account. |
| Duplicate computer name / account | Two machines share a name; both computer objects hold host SPNs. | Rename or remove the stale duplicate computer object. |
| Machine password / secure channel out of sync | Computer’s key differs from AD; nltest /sc_query fails. |
Repair the secure channel. |
| DNS name resolves to the wrong host | Common with NLB or shared names; the name points at a different server than expected. | Correct the DNS record; register the SPN on the account serving that name. |
| Time skew beyond five minutes | Clock offset from the DC breaks ticket validation. | w32tm /resync; fix the time source. |
Working Through a Fix
The path is short because the cause usually is. Run setspn -X to reveal duplicates and setspn -Q <spn> to see who holds the failing name. Establish the service’s true logon identity, then setspn -D the SPN from every account that is not that identity. Re-run setspn -Q and confirm exactly one owner remains, and setspn -X to confirm the duplicate group is gone.
If setspn -X shows no duplicates at all, do not force the SPN theory — move to the other causes. Confirm the SPN sits on the account the service actually runs as, check the machine’s secure channel, verify the name resolves to the right host, and rule out time skew. KRB_AP_ERR_MODIFIED is a key mismatch; those are simply the other ways two keys can end up different.
klist purge and retry, rather than concluding the fix failed while a stale ticket is still in play. Tickets outlive the directory change that invalidated them.
How to Prevent It
Duplicate SPNs are almost always self-inflicted during service setup. Register SPNs with setspn -S rather than setspn -A — the -S form checks for an existing duplicate and refuses to create a second one, which stops the problem at the source. Keep service identities deliberate: one service, one dedicated account, and the SPN on that account, so there is never ambiguity about who owns a name.
Build a periodic setspn -X into your AD hygiene checks so a duplicate introduced by a hurried install surfaces on a schedule instead of during an outage. And when you retire or re-purpose a service account, clean up its SPNs as part of decommissioning — orphaned and misplaced SPNs are what a later install collides with. Managed service accounts, which handle SPN registration for you, remove much of this risk entirely.
Quick Reference
| Command | Use |
|---|---|
setspn -X | Scan the forest for duplicate SPNs. The first and best check. |
setspn -Q <spn> | Show which account(s) hold a specific SPN. |
setspn -L <account> | List every SPN on a given account. |
setspn -D <spn> <account> | Remove an SPN from an account (delete the duplicate). |
setspn -S <spn> <account> | Add an SPN with a duplicate check — use this instead of -A. |
klist purge | Discard cached tickets so a client picks up the corrected SPN. |
| Event 4 (Kerberos) | KRB_AP_ERR_MODIFIED — the ticket key did not match the service key. |
Final Thoughts
KRB_AP_ERR_MODIFIED is one of those errors whose name oversells the drama. Nothing was modified maliciously — Kerberos is simply reporting, correctly, that the key which sealed a ticket is not the key trying to open it. The overwhelmingly common reason is a Service Principal Name living on two accounts at once.
Run setspn -X, remove the duplicate from the account that should not hold it, purge tickets, and integrated authentication comes back. Register future SPNs with -S and give each service its own account, and the error stops recurring.
setspn -X to find duplicate SPNs, and setspn -Q <spn> to see who owns the failing one. Remove it from the wrong account with setspn -D, leaving it only on the account the service logs on as, then klist purge on the client. Going forward, register SPNs with setspn -S so a duplicate can never be created.
Next: LDAP bind failures after enabling LDAP signing and channel binding — why legacy applications suddenly get “strong authentication required”, how to find them with Event 2889, and how to enforce safely.