WCF: Time to learn SPN with WCF Kerberos Delegation
What is Kerberos Delegation:
Kerberos Delegation allows us to reuse the client credentials to access recourses hosted on a different server.
Box Level (if the backend server runs with Network service account)
- Full Delegation (we can delegation to any process on back end server application)
- Constrained delegation (we can delegate to selected back end server application)
User Level (if the backend server runs with Domain Account)
- Full Delegation (we can delegation to any process on back end server application)
- Constrained delegation (we can delegate to selected back end server application)
The Kerberos Delegation is configured as a property for the domain account that is used by the application as a service account. For an IIS application that is the application pool account configured for that particular application. That is the also the same domain account that you used when you configured the SPN.
Why do we need SPN ?
SPN is required to support MUTUAL authentication, which is supported only via KERBEROS scheme.
SPN is just a unique way to determine and confirm the backend server identity and used for encrypting the client token.
SPN in play:
- Client request a TOKEN to access the backend server.
- DC will check what is the identity configured for the desired resource/URL (https://myserver.com or https://MyLB.com )
- Identity configured is nothing but the SPN created for the backend server – identity of process (domain\user)
- Once DC finds that for requested URL, the SPN is like this (setspn –a http/myserver domain\user1) then the DC will send a windows token for client identity which will be Encrypted using the password (hash) of server’s process identity or the SPN we have set.
- Once client gets the encrypted Token, he will forward it to server.
At server the process identity will be used to decrypt the incoming token and client will be authenticated
For IIS Kernel mode authentication: https://blogs.msdn.com/b/autz_auth_stuff/archive/2011/05/06/kernel-mode-authentication.aspx
Goal: Understanding the sample
I created below test utility to easily test the WCF Delegation even on production servers. Just get and run them.
1. First start the WCFBackEnd.exe at the backend server
2. Note the TCP Endpoint Identity
- If we start the WCFBackEnd.exe with Network Service (we will see SPN (Host/MachineName))
- Use following command to start the command prompt with Network service account
- psexec -i -u "nt authority\network service" cmd.exe
- If we start the WCFBackEnd.exe with domain account (we will see UPN (user@domain.com))
3. While starting make sure you run as Administrator, otherwise you might get some error.
4. Useful command, in case the URL registration creates any problem for Network service account:
- netsh http add urlacl url=https://+:9000/Service user=NetworkService
5. Once the BackEnd service is up and we log in to the Middle Tier box and start the “WCFMiddleTier.exe” application.
6. Again this app can be started with Network service or domain account.
7. Above screen indicates that I am starting the service as domain account.
8. Next be sure that you specify the right client end point identity in the “WCFMiddleTier” which will eventually be used to make the double hop call to backend server.
9. Now let’s go to client box and run the “Client.exe”
10. There will a two questions asked.
- Press “T” to test the TCP end point
- Press “D” to test double hop.
- By default if you press enter you will test the Http endpoint and Single Hop.
11. Result will be displayed in the client window for success or failure.
12. Once the test completes, there will a Prompt to press “A” to start new test. Pressing Enter will terminate the client application.
13. Further you can go to individual Middle Tier and Back end servers and observe the identity received.
Client can Add and select the back end server (SERVER – my server name) where we want to delegate the token.
I selected service type as (HOST), because the backend server running under the Network service account.
Which will use the default MACHINE NAME SPN (HOST/SERVERNAME).
Remember:
My Front end box name is DC
My Middle Tier box name is Client
My Back End Server box name is Server
SCENARIO 2:
For TCP endpoint:
We set the SPN with following syntax
SETSPN –a SERVICENAME/BOXNAME DOMAIN\USER
Or SETSPN –a SERVICENAME/HostHeader DOMAIN\USER
My service name: service
Box name or let’s say the address I am point to request to: net.tcp://client:8000/service
So I keep the box name / Host Header as CLIENT.
setspn -a service/client:8000 contoso.com\user1
Once done, I can see the delegation tab appeared on DC, and I trusted user for full delegation.
For Http endpoint (Middle Tier)
Again we need to set a SPN for the http protocol along with the host header user for end point address.
SETSPN –a HTTP/HOSTHEADER DOMAIN\USER
setspn -a http/client contoso.com\user1
Now we will be able to make the call to middle tier box from the client.
If we run the test where backend start running under domain account…
The DELEGATION test will fail now..
Call from middle tier to back will fail..
Error we get while making backend call:
I don’t see request reaching to back end server in AUDIT LOGS:
So we need to set the SPN for the backend server as well.
Backend server SPN (back end process runs under user2 domain account):
setspn -a http/server contoso.com\user2
Middle Tier SPN:
setspn -a http/client contoso.com\user1
For TCP:
setspn -a service/server:8000 contoso.com\user2
SCENARIO 4:
For constrained delegation:
Over Http End Point:
Select as per below screen and say Add –
Here specify user2 (because we want to trust User 1 at DC to delegate the token for the service running under user 2)
When we try to search the service running under user 2, we will see the SPN we configured for the HTTP end point.
Indicating that there is a service type called “http” running at server (computer name)
By selecting this we are allowing user1 to delegate the token to same.
We do see credentials flowing to back end server.
For constrained delegation:
Over TCP End Point:
All we need is one more SPN for the back end TCP server…
Similar to what we did for the Middle Tier TCP WCF service
SPN for back end TCP WCF service (Don’t forget to add the PORT number in SPN)
setspn –a service/server:8000 contoso.com\user2
Now we go back to DC and allow user 1 to delegate to the service running under user 2.
This time we can see that for user2, we get two services.
Once added, my screen will look like this..
Assessment:
With the above addition change, my user1 should be able to perform constrained delegation to the back end server running with identity of user2.
Thumb Rule (for adding SPN):
Always (SETSPN –a HTTP or NAME/HOSTHEADER DOMAIN\USER)
- Http : Setspn –a http/xyz.com contoso.com\user1
- Tcp : Setspn – a MYSERVICE/xyz.com constoso.com\user1
- SQL : Setspn -a MSSQLSvc/<sql-server-host-name:1433<sql-service-user-account-name>
Don’t forget to add the PORT for anything other than Http.
References:
- https://www.codeproject.com/Articles/38979/How-to-enable-multi-hop-impersonation-using-constr
- https://social.msdn.microsoft.com/Forums/vstudio/en-US/fd138bb3-0cfd-4cd2-8677-be8156812df6/constrained-delegation-in-kerberos-what-am-i-doning-wrong?forum=wcf
- https://mastermynd-code.blogspot.in/2009/06/service-principal-name-when-using-wcf.html
- https://stackoverflow.com/questions/38779/what-spn-do-i-need-to-set-for-a-net-tcp-service
- https://msdn.microsoft.com/en-us/library/ff648998.aspx
- https://msdn.microsoft.com/en-us/library/ff650896.aspx#Step4
To run the process as Network service:
- PS Exec Tool: https://technet.microsoft.com/en-us/sysinternals/bb897553.aspx
- https://stackoverflow.com/questions/6911310/how-do-i-runas-network-service
I am sure this utility will be useful to many DEV, who would like to learn WCF and Delegation.
You can get source code from following link:
ONE DRIVE: