PowerShell Kerberos and SPNs
A Service Principal Name identifies a service instance so Kerberos can issue a ticket for it. Get it wrong and authentication silently falls back to NTLM, or fails outright.
Documentation: Microsoft Learn
Overview
Duplicate SPNs are the classic fault. The same SPN registered on two accounts makes Kerberos refuse to issue a ticket for either, so a service that worked yesterday stops after someone else registers the same name. setspn -X finds duplicates across the domain and should be the first check on any Kerberos problem.
Format matters exactly: service class, then host, then optionally a port, as in MSSQLSvc/sql01.corp.local:1433. Use the fully qualified name that clients actually connect with. An SPN registered against the short name does not help a client using the FQDN.
SPNs live on the account the service runs as, so changing a service's account without moving the SPN breaks it. That is a very common cause of a service that fails after a routine account change.
klist on the client shows the tickets currently held, and klist purge clears them, which is how you retest without a reboot. Time skew beyond five minutes also breaks Kerberos, so check the clock before anything else.
Accounts with SPNs are targets for Kerberoasting, so service accounts want long passwords or should be gMSAs.
Inspect this example’s structure
Read the command and its supplied arguments. This example requires real PowerShell or its module; this diagram does not execute it.
[pscustomobject]@{
List = 'setspn -L svc-sql'
Find = 'Get-ADUser -Filter "ServicePrincipalName -like ''*MSSQL*''" -Properties ServicePrincipalName'
Dupes = 'setspn -X'
Tickets = 'klist'
} | Format-List- Stage 1[pscustomobject]@{
Positional values or no named parameters - Stage 2Format-List
Positional values or no named parameters
An example to inspect
Preview the example. Sign in for the full lesson and activities.
[pscustomobject]@{
List = 'setspn -L svc-sql'
Find = 'Get-ADUser -Filter "ServicePrincipalName -like ''*MSSQL*''" -Properties ServicePrincipalName'
Dupes = 'setspn -X'
Tickets = 'klist'
} | Format-ListWhat happens
This prints the four commands you need, since none of them work without a domain. The Find line shows the PowerShell equivalent of searching for an SPN, with escaped quotes because the AD filter needs its own quoting. Dupes is where to start when a service that used to authenticate stops.
Worth remembering
- Duplicate SPNs break Kerberos for every account involved. setspn -X finds them.
- Format is class/fqdn:port, matching what clients connect to.
- SPNs belong to the service's account; moving the account breaks them.
- klist purge clears cached tickets for retesting. Check time skew too.
Primary documentation
Try it
Expected output · prints command text; does not execute these commands
[pscustomobject]@{ List = 'setspn -L svc-sql' Find = 'Get-ADUser -Filter "ServicePrincipalName -like ''*MSSQL*''" -Properties ServicePrincipalName' Dupes = 'setspn -X' Tickets = 'klist'} | Format-ListExample reader
Inspect this page's example
Run supported commands against the practice data, or inspect the example without executing it.
Ready to inspect.
Prints the SPN inspection commands, including the duplicate check.
Show reference output
Expected output · prints command text; does not execute these commands
List : setspn -L svc-sql Find : Get-ADUser -Filter "ServicePrincipalName -like '*MSSQL*'" -Properties ServicePrincipalName Dupes : setspn -X Tickets : klist
Keep going
Next: PowerShell GPO troubleshootingCheck your understanding
A service reports a Kerberos failure after its account changes. What evidence do you gather?
Identify the service name requested by the client, inspect its SPN ownership and check for duplicates. Verify DNS and time before changing registrations.