The biggest mistake: ServicePrincipalName’s

Note: All of your Kerberos configuration questions can be answered by using the DelegConfig tool that I wrote. You can find that tool here 

Literally 99% of all Kerberos problems revolve around an incorrect, missing, or duplicate ServicePrincipalName (SPN).  To be honest, the concept of an SPN is so simple that I am often confused that other people don't understand even after I explain. I suppose it is the 5+ years that I've had of helping people configure and troubleshoot Kerberos related issues that have finally made it all clear to me ;-p. I like to think in simple terms instead of making things complex . This is a carry-over from my Algebra-1 days when my teacher used to pick the easiest problem possible when explaining a concept.

Think of an SPN as a “username” used to identify a program that is busy dealing with credentials. And we're only allowed to talk to this program using its “username”. PERIOD. Simple! Yes, that's all an SPN is: a "username". And as with any username, the name itself isn't really that important. It is merely to make identifying a person (or entity) easier to remember to humans. In this particular case, however, there are some naming conventions for this "username". Okay, so what username (SPN) is the right one? And where do we set it? These 2 questions are where all the confusion lies. We split the SPN into 2 parts and occasionally 3 parts: The first part is the “service type” and the second part is the “host name”. And sometimes the 3rd part is present which is the “port”. In the end, however, all these different parts are simply used to come up with this "username" that we call the ServicePrincipalName.

Let’s say I wanted to connect to a process called BrianService.exe. And the DNS name to route my connection was blah.overthere.com. As the designer of this weird service I might come up with a “service type” of BRIAN. So the SPN would be BRIAN/blah.overthere.com. Okay, and where do we set that? Simple, simple, simple. If my BrianService.exe process is running under “DOMAINNAME\someAccount” then we’d set the BRIAN/blah.overthere.com SPN on “DOMAINNAME\someAccount”. If my process (BrianService.exe) were running as something like “Network Service”, “Local Service”, or “Local System” then I’d set BRIAN/blah.overthere.com on the computer account itself that is running that process. If you ever change the account that is running your program then you need to remove the SPN from the original account and set it on the new account because we can't have the same username assigned to multiple "people" (or accounts in our case).

 Recap. An SPN is just a *name* that we've given to a "service" which is in the format of ServiceType/HostName and occasionally ServiceType/HostName:PortNumber. And it is set on which ever account is handling authentication for that service. I should also note that you as an administrator don’t get to pick whether you use a port. I used to think that maybe I could throw a port number on an SPN if I wanted to make it more secure. But it is the client application that has the decision built in on whether to use a port.

Okay, so let’s make this more complicated by using more realistic names. But while I do that I want you to maintain faith in what I just explained above regarding how simple these concepts are. Let’s say you’re connecting to an IIS server with a machine name of “iis-prod-01”. And let’s say the active directory domain name is “company.com.” In Internet Explorer you use an address of http://someInventedName. The “application pool” (i.e. the w3wp.exe process) is running under the account of “COMPANY\myserviceAccount”. With the knowledge that the web service’s Kerberos “service type” is “HTTP” (don’t confuse this with the browser’s protocol type) you’re probably thinking we can set an SPN of “HTTP/someInventedName” on “COMPANY\myserviceAccount”.  Doh!! Sorry no. Almost, but Kerberos would probably not work with that. The problem with that idea is that you have to know how name resolution is working also because it is ultimately name resolution that dictates what the "host name" part of the SPN should be. If you open a CMD prompt and ping someInventedName, it will most likely resolve to someInventedName.company.com. Therefore the SPN that “IE” will request is “HTTP/someInventedName.company.com”. IE was not programmed to request an SPN using the port so that part of the SPN is not needed nor can it ever be used. What if the ping did show the name as just “someInventedName”? Then IE would in-fact use Kerberos with an SPN of “HTTP/someInventedName” When dealing with NetBIOS names, because name resolution can be affected by many things, the key is to make sure an SPN of both “HTTP/someInventedName” and “HTTP/someInventedName.company.com” are set on the “COMPANY\myserviceAccount” account. Or the way I prefer to say that is you need to create an SPN that represents both the NetBIOS name and the Fully Qualified name.

Okay, so I can hear what many of you are thinking. “But I thought that KB article said to set the SPN on the computer account!” Well, yes, that would be accurate *IF* the process handling authentication was running as “SYSTEM”. If the process for that service is not running as SYSTEM (or Network Service, or Local Service) then you can’t set the SPN on the computer account (well you can but Kerberos isn’t going to work).

Recap 2: An SPN should actually be in the format of ServiceType/NetBIOSName *and* ServiceType/FQDN. And we *always* set that on whatever account is running the process that is handling the authentication. Read the above paragraphs a couple times and just maintain faith that it is really that simple. Don’t complicate it with questions!!  

I want to mention one last thing before I go. Whenever a computer is joined to a domain, it is assigned 2 SPN's by default: HOST/netbiosName, and HOST/FQDN.com. netbiosName being the machine name of the computer you're joining to the domain, and FQDN.com being the fully qualified machine name. These two SPN's use the generic "HOST" service type which includes all the various services that *come* with Windows. Therefore, if you connect to http://machineName or http://machineName.company.com, you will already have SPN's set that will handle Kerberos when using those names. Or if you connected to \\machineName\SomeShareName you'd also be all set for Kerberos (UNC's need a "CIFS" SPN which is included under "HOST" also). For a full list of the different service types included in HOST please see Table 1 of this technet article.

--Brian Murphy-Booth

17 Comments

  • If spn's are so critical for kerberos to work, why oh why is it so simple to create duplicate spn's in the AD?
    a nice, simple ldap warning - duplicate field not allowed, would probably save hours/days of troubleshooting.
    We've written our own SetSPN app that runs a simple search preventing our IIS admins from shooting themselves in the foot.
    The best advice I've ever seen was this a call into Search.vbs:
    Cscript "C:\Program Files\Support Tools\search.vbs" "LDAP://dc=Domain,dc=com" /C:"(serviceprincipalname=%1)" /S:Subtree /P:DistinguishedName  
    Replacing dc=Domain,dc=com with our domain.
    Chris!

  • I like your question. I don't really have "the" answer. My guess is that when Microsoft first added Kerberos capability to Windows, these sort of issues just didn't come to mind. As more and more people become security conscious the whole "Kerberos" issue is becoming a common support call to us. I think like any product, the more people that use it, the more problems or suggestions will be presented, and the Devs will dedicate more resources to make the product better. If nobody ever used Kerberos, there would be no need to make it easier to extend beyond the default settings. In IIS 7.0 (not sure about the rest of Longhorn) there are some plans to add UI features that should help address these problems. We'll see though!!

  • You mentioned about service type "BRIAN". How do I determine the service type for a non-MSFT service? TIA.

  • The creator of that service type will know that. When I create my own service and decide that for my SPN "username" I want BRIAN as the service type, then I'll need to tell that to anybody that creates clients for my service.

  • Just wanted to say thanks for the DelegConfig tool. Very helpful for someone thats trying to learn about any type of delegation. Its straight forward, in plain english, and easy to use.

    Sadly, I had to learn a few things the hard way before coming accross your posts. I did figure out most of the things you talk about here...but the new stuff put it all into perspective.

    Simple. right?

    Thanks again.

  • hello,
    how i can configure constrain delegation for nlb iis(virtual name)? app pool must run under local system account.

  • I have a related question - what's likely the cause of an error in the logs stating a krb_err_badoption logon event trying to connect to a server in server realm abcsteve.com, server name host/silver.abcsteve.com, but a target name of host/abcsteve.com@abcsteve.com

  • Short answer - There is a duplicate SPN.

    Long answer - When a client asks for a ticket it just says "give me a ticket for HTTP/mywebsite.com". Active Directory searches through its accounts for that exact SPN. If it can't find it then it searches again for "HOST/mywebsite.com" instead. Let's say AD finds the SPN it is looking for on MYDOMAIN\web01$. It creates a ticket and then encrypts it with web01$'s NTLM hashed password. The client gets the ticket and sends it off to the web server. Let's say your web site is running under an AppPool Identity of MYDOMAIN\myserviceaccount. Well... we try to decrypt the ticket using the NTLM hashed password of myserviceaccount since that's what the w3wp.exe process knows about. But that fails since that wasn't what the ticket was encrypted with. That's when BADOPTION is logged.

    If you haven't tried already, setup my DelegConfig tool and it should find who has the duplicate SPN. There is a limitaion in the tool currently where it will not search all the trusted domains, but as long as the IIS server and the accounts that you're using for the AppPools are all in the same domain, then it should work fine.

  • hitter - If you want to use Kerberos and NLB then you cannot use a built-in account. You must use a domain user as your AppPool identity. This is because Kerberos revolves around SPN's and a given SPN can only exist on a single AD account.

  • Hi, thanks for the this nice "documentation"! I have a related question: I found out that I have a duplicated SPN. The problem I have is that I don't know which one I have to delete. Everything began with these 2 errors:
    "There are multiple accounts with name cifs/ipl-sbs.ipl.lan of type DS_SERVICE_PRINCIPAL_NAME." and
    "There are multiple accounts with name cifs/IPL-SBS of type DS_SERVICE_PRINCIPAL_NAME."
    After searching the duplicates using ldp, I found 2 enries: one is the HOST named IPL-SBS that is our domaincontroler and the second is the our DomainAdmin user. Which SPN can I remove? It's perhaps a stupid question, but I'm novice in this area... THANK, Marco

  • I'm not really sure how you can have a CIFS service on a domain user so I would start by deleting that one. CIFS is a built in service for the OS. Or if the front-end service is IIS then you can try running my DelegConfig tool that I have mentioned at the top of this blog.

  • Thank you for the tool - it definitely helped me to diagnose my problem.

    However (isn't there always...), I have found some interesting issues with authentication/Kerberos in my domain. The problem exhibits itself on all websites running on the webserver, including your DelegConfig tool.

    [Background: the webserver is Server 2003 running IIS6; client browser is IE7 running on XP Professional SP2; all clients, workstations and servers are members of the same domain, a Windows 2003 domain running in Windows 2000 native mode. The website is set to Integrated Windows Authentication only, and NTAuthenticationProviders is set to "Negotiate".]

    To summarise: I can start a new browser session, go to http://MyServer/Kerberos/ and the page loads, but DelegConfig complains "This tool is unable to verify that the proper SPNs are set because the WrkstaInfo.dll C# ActiveX control failed to load in Internet Explorer". If I add "resolvedName=MyServer", everything works fine. Any idea why adding "MyServer" to the resolvedName helps, when I am already browsing to the exact same server name?

    If I start a new browser session and go to http://MyServer.MyDomain.com/Kerberos/ I get a username/password login box. Without authenticating, I go to http://MyServer/Kerberos/ and the page loads (but with same ActiveX error); I then go back to the FQDN page and everything works, including the SPN lookup!

    As an attempted fix, I have created 2 new SPNs for NT AUTHORITY\NETWORK SERVICE, called HTTP/MyServer and HTTP/MyServer.MyDomain.com, but the strange behaviour remains. There were already 2 "HOST" SPNs, and the Application Pool Identity is NETWORK SERVICE, so this probably hasn't made any difference.

    I fully accept that there might be some strange DNS happenings, but I cannot fathom why when first going to the FQDN I am refused all access, then going to just the ServerName gets me some access, and then returning to the FQDN gets me full access (all without entering any usernames/passwords).

    Any ideas?

  • When it comes to Kerberos, name resolution is very important. In particular, name resolution on the "client" is important. That is because the SPN that the client requests is based on the name that the client determines during a reverse DNS lookup. So to make DelegConfig more accurate I wrote a C# assembly that runs inside IE. It simply does that reverse lookup then appends "resolvedName=whatever" to the URL. That way the server-side code of DelegConfig understands what the client came up with on the reverse lookup. Unfortunately, IE security more often than not, blocks the loading of that C# "activeX control". So you have to manually determine the name that the client comes up with. In regards to you being redirected from the FQDN back to the NetBIOS name... that sounds like a bug in my redirect logic.

  • (from AndyIIS)

    "If I start a new browser session and go to myserver.mydomain.com/Kerberos I get a username/password login box. Without authenticating, I go to http://MyServer/Kerberos/ and the page loads "

    I hope I'm not teaching Grandma to suck eggs, but I did notice that myserver.mydomain has a period in it. As I understand it, IE will by default assume that any URL with a period in it is in the Internet zone, and will not attempt to pass any form of credentials, including Kerberos. You then get that pesky modal dialog box asking for credentials. The resolution is to put myserver.mydomain in the list of Intranet sites (Internet Options -> Security tab -> Local Intranet -> Sites -> Advanced). IE will then submit the client credentials.

    Also, to get WrkstaInfo to load, could you check your vDir execute permissions in IIS? The .dll only functioned properly for me when the permissions were set to Scripts Only (rather than Scripts and Executables).

    Cheers,
    Donna

    p.s. I removed the apostrophe from the title of this thread :-)

  • So what about when the log shows signs of a duplicate, but (now) three methods come up empty with the duplicate record? How frustrating is that?

  • Hi Brian,

    I've been encountering a Kerberos issue that has me a bit puzzeled. I have used your delegconfig to assist with configuring SPN's and that helped identify config issues very clearly thank you!
    I believe our DNS and SPN's and Kerberos config looks good now and works fine most of the time. However from time to time we see an XP client loosing all Kerberos tickets and/or not being granted any and the client defaults back to NTLM thereafter. Both Kerbtray and Klist confirm this. The only way for us to get Kerberos working on the client again is a full reboot. I'm at a loss as to what may cause this behaviour and why a reboot is required to fix. I would be grateful for your expert opinion or suggestion on this?

    Thanks

    David Reilly
    Dublin, Ireland


  • David Reilly,

    If the problem you are seeing effects only a particular user or perhaps a limited set of users, my first guess would be that they are part of too many groups. What I think I'd do first though is enable Kerberos logging on the client to see if that provides any clues.

    A kerberos ticket contains all the security information about a user so the more groups a user is part of, the bigger the ticket gets. Eventually the user's workstation will block the ticket as being too big. I believe you'd want to increate the "MaxTokenSize" registry entry on the client if that's what is causing your problem. My guess on the intermittency of the problem may be that group membership changes are performed frequently and the user's ticket size fluctuates? My second guess on the cause of the problem is that during the ticket renewal there is a networking problem so the user doesn't get a ticket.

    In either case, perhaps Kerberos logging will lead you to the solution.

Comments have been disabled for this content.