Fix it now
Windows authentication was attempted and the security layer could not complete it. Microsoft publishes 18452 as the login being from an untrusted domain and unusable with integrated authentication; the server-side SSPI handshake failure is the same event seen from the other end. In most cases a service principal name is missing, duplicated, or on the wrong account.
setspn -L DOMAIN\svc_sql
setspn -Q MSSQLSvc/sqlhost.contoso.com:1433
setspn -X
- Find out how connections that do work are authenticating:
SELECT net_transport, auth_scheme FROM sys.dm_exec_connections WHERE session_id = @@SPID;returns KERBEROS, NTLM or SQL. - Read the setspn output. You want exactly one
MSSQLSvc/host.domain.com:1433for a default instance on 1433, andMSSQLSvc/host.domain.com:<port>for a named instance, because the port is what ties an SPN to an instance when TCP is used. - If the SPN is missing, register it against the service account:
setspn -S MSSQLSvc/sqlhost.contoso.com:1433 DOMAIN\svc_sql.-Schecks for a duplicate first. - If
setspn -Xshows a duplicate, delete the wrong one:setspn -D MSSQLSvc/sqlhost.contoso.com:1433 DOMAIN\old_account. A duplicate breaks Kerberos for everyone who uses that name. - Reconnect and check auth_scheme again. Microsoft also publishes Kerberos Configuration Manager, which finds missing and duplicate SPNs and dynamic-port problems for you.
Do not test from the server console. A local connection usually goes over shared memory and needs no ticket, which is why SPN faults are invisible from the machine that has them.
If auth_scheme now reports KERBEROS from a client machine, you are done. If it does not, the next section covers what happens before the login and which of the four causes you have.
Why it happens
When a client connects with integrated security, the two ends negotiate through the Security Support Provider Interface and Kerberos is tried first. The client asks a domain controller for a ticket to a specific service, identified by its service principal name and built from the server name and the port or instance it is connecting to. If exactly one account holds that SPN, the ticket it issues can be decrypted by the server and authentication succeeds.
Everything that goes wrong here goes wrong in that sentence. No account holding the SPN means no ticket, and the pair fall back to NTLM. Two accounts holding the same SPN means the domain controller cannot tell which key to encrypt with. The wrong account holding it, because the service changed identity and the old registration was never removed, has the same result.
The SPN format is where most hand-written registrations go wrong. Microsoft documents MSSQLSvc/<FQDN>:<port> as the provider-generated SPN when TCP is used, for default and named instances alike, and MSSQLSvc/<FQDN>:<instancename> as the form used for a named instance when a protocol other than TCP is used. A named instance that clients reach over TCP therefore needs the port form. Registering only the instance-name form and expecting TCP clients to find it is a common and quiet failure.
That is also why a named instance on a dynamic port cannot work reliably with Kerberos. The port changes at every restart, the SPN does not, and the SPN the client asks for stops matching. Microsoft’s guidance is to give the instance a static TCP port under IPAll before troubleshooting anything else about it.
The SPN is missing, so Kerberos cannot be used at all
You have this one if setspn -L on the service account shows no MSSQLSvc entry, and connections that succeed report NTLM rather than KERBEROS.
- Register both name forms if clients use the short name too:
setspn -S MSSQLSvc/sqlhost:1433 DOMAIN\svc_sqlandsetspn -S MSSQLSvc/sqlhost.contoso.com:1433 DOMAIN\svc_sql. - For a named instance reached over TCP, use its static port in place of 1433.
- Restart the SQL Server service and read the error log, which records whether the instance registered its own SPN at startup.
- Reconnect and confirm auth_scheme now reports KERBEROS.
Automatic registration needs the service to run as Local System, NETWORK SERVICE, a virtual account, or a managed service account with the right permissions: validated write to service principal name, read servicePrincipalName and write servicePrincipalName. A plain domain user account does not have those by default, which is why so many estates have missing SPNs.
A duplicate SPN exists somewhere in the forest
You have this one if Kerberos worked until a server was rebuilt or renamed, and now fails intermittently or for a subset of clients.
- Search the whole directory:
setspn -X. - Query the specific name:
setspn -Q MSSQLSvc/sqlhost.contoso.com:1433. - Delete the wrong one:
setspn -D MSSQLSvc/sqlhost.contoso.com:1433 DOMAIN\old_account. - Leave exactly one registration per name and port, then reconnect.
Duplicates are usually created by registering an SPN by hand against a new service account without removing it from the old one, or by a machine account keeping an SPN after the service moved to a domain user.
The credential cannot be delegated across a second hop
You have this one if A user connects to a web or reporting tier successfully, and that tier’s onward connection to SQL Server fails or arrives as an anonymous identity.
- Confirm both hops have valid SPNs. Delegation cannot work without Kerberos on the first hop.
- Configure constrained delegation on the intermediate service account, listing the SQL Server SPN it may present credentials to.
- For a linked server using impersonation, Microsoft documents that the SQL Server startup account needs the account is trusted for delegation right.
- Confirm no account in the chain is marked as sensitive and not to be delegated.
If delegation is more than you want to configure, define the linked server to connect with a specific remote login instead. That removes the double hop, at the cost of one shared identity at the far end.
Channel binding does not match
You have this one if 0x80090346 in the server-side entry, and the failure began after a hardening change on either end.
- Read the code for what it is: SEC_E_BAD_BINDINGS, the SSPI channel bindings supplied by the client are incorrect.
- Check the Extended Protection setting on the instance’s protocol properties in SQL Server Configuration Manager.
- Confirm the client driver supports channel binding; older drivers cannot satisfy a server that requires it.
- Update the client drivers, or relax the setting while you do, then set it back and retest with the client that failed.
Full reference
Reading the symptom
| What you observe | Where to look |
|---|---|
| Works from the server console, fails from other machines | The console is on shared memory and needs no ticket. Test from a client |
| Works for some users, fails for others | A duplicate SPN, or delegation missing on one path |
| Fails on one client only | Time skew or a broken secure channel. w32tm /query /status and Test-ComputerSecureChannel |
0x80090346 in the server-side entry |
Channel binding: extended protection settings disagree between client and server |
| Worked until the server was rebuilt | A stale SPN on the old computer or service account |
| Named instance only, after a restart | A dynamic port. The SPN no longer matches the port the client asks for |
SPN forms, as Microsoft publishes them
| Form | When it applies |
|---|---|
MSSQLSvc/<FQDN>:<port> |
The provider-generated SPN when TCP is used. <port> is the TCP port number |
MSSQLSvc/<FQDN> |
A default instance, without a port |
MSSQLSvc/<FQDN>:<instancename> |
A named instance when a protocol other than TCP is used |
Microsoft also notes that the SPN format does not require a port number at all, and that a multiple-port server or a protocol without ports can still use Kerberos. What it does require is that the SPN the client constructs and the SPN registered in the directory are the same string, held by exactly one account. That is the whole test.
Command reference
| Command | What it does |
|---|---|
setspn -L DOMAIN\account |
Lists every SPN registered against that account |
setspn -Q <spn> |
Queries one SPN and shows which account, if any, holds it |
setspn -X |
Finds duplicate SPNs across the directory |
setspn -S <spn> <account> |
Registers an SPN after checking it does not already exist |
setspn -D <spn> <account> |
Removes an SPN from an account |
SELECT net_transport, auth_scheme FROM sys.dm_exec_connections WHERE session_id = @@SPID; |
Shows how the current connection actually authenticated |
Microsoft publishes two tools for this that are worth more than the command list: Kerberos Configuration Manager, which identifies missing and duplicate SPNs, dynamic-port problems and TCP configuration and can fix several of them, and SQLCHECK, which prints a suggested-SPN table showing which ones exist and which do not. Both save time over reading setspn output by eye.
The nearby error that is not this one
18483 is a different failure that turns up in the same investigations. Microsoft publishes it as being unable to connect to a server because the login is not defined as a remote login there, with advice to verify the login name. That is a linked-server or remote-server mapping question, not a Kerberos one, so if 18483 is the number you actually have, the SPN work in this article will not help.
What is not published
The server-side entry for an SSPI handshake failure carries error 17806 along with an error code and a state. Microsoft does not publish a page defining 17806 itself, so this article does not assign it a meaning beyond the class of failure it belongs to. What is published, and what you should work from, is the SSPI troubleshooting guidance and the SSPI status codes: the numeric code carried in that entry, such as 0x80090346, is where the real detail is.
Before you conclude Kerberos is unfixable here
- Check name resolution. Microsoft lists DNS problems as a cause of an invalid SPN being formed in the first place, so a client resolving the server to the wrong name asks for the wrong ticket.
- Check the clocks. Kerberos refuses beyond a few minutes of skew regardless of everything else.
- Check the trust.
Test-ComputerSecureChannelon the client tells you whether its own channel to the domain is healthy. - Give named instances a static port under IPAll before anything else, because without one the SPN is chasing a moving target.
- Treat a fallback to NTLM as a finding rather than a resolution. It hides the fault and takes delegation away with it.
Every code this article covers
| Code | What it points at | Source |
|---|---|---|
18452 |
Login failed: the login is from an untrusted domain and cannot be used with Integrated authentication. Severity 14 | Microsoft Learn |
17806 |
The server-side entry recorded when an SSPI handshake fails during an integrated-security connection. Microsoft publishes no definition for the number itself; read the error code and state it carries | not published by the vendor |
18483 |
Could not connect to the server because the login is not defined as a remote login there. A linked-server mapping problem, not a Kerberos one. Severity 16 | Microsoft Learn |
0x80090346 |
SEC_E_BAD_BINDINGS: the SSPI channel bindings supplied by the client are incorrect. This is the extended protection case | Microsoft Learn |
Confirm the fix worked
- From a client machine,
SELECT net_transport, auth_scheme FROM sys.dm_exec_connections WHERE session_id = @@SPID;reports KERBEROS. setspn -Xshows no duplicates for the SQL Server names.setspn -Lon the service account lists exactly the SPNs you intended, in the right form for the protocol clients use.- Restart the SQL Server service and check the error log for a clean SPN registration entry at startup.
- A double-hop scenario, if you have one, reaches SQL Server as the end user rather than as an anonymous identity.
Questions people ask about this
Is NTLM good enough if I cannot fix the SPN?
It will often work, and plenty of estates run on it without knowing. It costs you Kerberos delegation, so any double hop breaks, and it is the weaker protocol. Treat a fallback to NTLM as a finding to fix.
What SPN does a named instance need?
If clients reach it over TCP, the port form: MSSQLSvc/host.domain.com:<port>. Microsoft documents the instance-name form as the one used when a protocol other than TCP is in play. Registering only the instance-name form and expecting TCP clients to use it is a common mistake, and it needs a static port to be stable.
Do I need a particular edition or licence for Kerberos?
No. Kerberos is a Windows feature and works identically on every SQL Server edition, including the free ones. This is solved with setspn and Active Directory, not with a purchase.
Why does it work when I remote onto the server itself?
A connection made on the server usually goes over shared memory or the loopback, which needs no Kerberos ticket for a remote service. That is why local testing hides SPN problems, and why you should always reproduce from a client machine.
Who can register an SPN?
A domain administrator, or the service account itself if it has validated write to service principal name along with read and write on servicePrincipalName. Microsoft documents automatic registration for Local System, NETWORK SERVICE, virtual accounts and managed service accounts with those rights. A plain domain user account normally cannot, which is why so many estates have missing SPNs.
