How to get Service Token from Kerberos using SSPI

11,962

Solution 1

You can use below to get the token by giving the SPN

  public String getToken(string userName)
    {
     using (var domainContext = new PrincipalContext(ContextType.Domain, "domain"))
        {
          using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName))
            {
                Console.WriteLine("User Principale name" + UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName).UserPrincipalName);
                string spn = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName).UserPrincipalName;
                KerberosSecurityTokenProvider k1 = new KerberosSecurityTokenProvider(spn, System.Security.Principal.TokenImpersonationLevel.Impersonation, new System.Net.NetworkCredential(userName, "password", "domain"));
                KerberosRequestorSecurityToken T1 = k1.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
                string sret = Convert.ToBase64String(T1.GetRequest());
                Console.WriteLine("=====sret========" + sret);
                return sret;
            }
        }

    }

Solution 2

Code provided by Hasanthi worked perfectly for my need and I didn't have to use SSPI. I was asking wrong questions but I learned a lot about Kerberos and SSPI. Here is my code in a nutshell:

AppDomain.CurrentDomain.SetPrincipalPolicy(System.Security.Principal.PrincipalPolicy.WindowsPrincipal);
var domain = Domain.GetCurrentDomain().ToString();

using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
{
    string spn = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, serviceName).UserPrincipalName;
    KerberosSecurityTokenProvider tokenProvider = new KerberosSecurityTokenProvider(spn, System.Security.Principal.TokenImpersonationLevel.Impersonation, CredentialCache.DefaultNetworkCredentials);
    KerberosRequestorSecurityToken securityToken = tokenProvider.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
    string serviceToken = Convert.ToBase64String(securityToken.GetRequest());
}
Share:
11,962

Related videos on Youtube

Furkat Kholmatov
Author by

Furkat Kholmatov

Updated on October 16, 2022

Comments

  • Furkat Kholmatov
    Furkat Kholmatov over 1 year

    Objective: I am trying to build Proof Of Concept client app to implement Single Sign On by using SSPI. I am new to C# and I am getting confused.

    What I know and have done so far: All users are part of Active Directory domain, so I know Kerberos is being used for authentication during login. All I need to do at this point is to get service token from Kerberos so I can pass it to the service resource instead of username and password (correct me if I am wrong). I have been provided Service Principle Name (SPN) and password that has been registered with Kerberos for the service.

    I was hoping not to use Platform Invocation Services to call SSPI functions, but I will if I have to. I read through ".NET Remoting Authentication and Authorization Sample - Part I" and used Microsoft.Samples.Security.SSPI for testing. I also tried using C#/.Net Interface To The Win32 SSPI Authentication API.

    So far, I can get user/client credentials, build client security context. But how do I request a Service Ticket for a given SPN?

    I would appreciate your help and guidance. Please be specific if you can and let me know if you have any questions.

  • Furkat Kholmatov
    Furkat Kholmatov almost 8 years
    Thank You for the answer, could you please elaborate on the following? With Kerberos there are 3 main steps that need to occur. First is authenticating client and getting Ticket Granting Ticket. Second is requesting a ticket for a Service using the Ticket Granting Ticket and the third is having the service validate the ticket that the client requested for it. With the code sample above I am confused because the username variable is used for foundUser and spn. Can you elaborate on answer and specify which is truly client user and service user please?
  • Hasanthi
    Hasanthi almost 8 years
    Hi, the above code states how you can obtain a ticket for a given spn. Here the user name is the logon name of the AD user and by using the method it will create the spn as logon name@domain. By using that spn you can generate the ticket. I am also doing the same kind of task and I'm following C#/.Net Interface To The Win32 SSPI Authentication API. I could also get the TGT by using nsspi and searching for a way to get SGT :)
  • Scott Lin
    Scott Lin almost 8 years
    Do you know how to go backwards and get the user principal name from the 'serviceToken'? Is this even possible?
  • Furkat Kholmatov
    Furkat Kholmatov almost 8 years
    I didn't implement server side but it is possible. I believe user principal name is included in service token and in order to decrypt it you would need to get the key from Kerberos server that issued the token.
  • valorl
    valorl over 5 years
    @FurkatKholmatov could you give an example what is the "serviceName"? I'm trying to similarly request a ticket for a service with the current network credentials, but within an impersonated context (delegation). I'm confused about why you are getting a UPN and then use it as an SPN, as for me it worked (without delegation) simply by setting the spn to e.g. "HTTP/myservice.domain.com" when initializing the TokenProvider. Could you elaborate on your use-case? It might help me debug mine :)
  • Furkat Kholmatov
    Furkat Kholmatov over 5 years
    @valorl - this was a while back and I can't remember the details. I think for some reason we were allowing client's network administrator to name their own SPN and provide it to the user if they allowed Single Sign On. I think "serviceName" was that SPN entered by the user.
  • Steve
    Steve about 5 years
    For everyone that copies the above code please note that spn in it's current form is not useful. The point of spn is to indicate which service you want to prove your authentication to, and getting a ticket to an spn of yourself provides very little value. Your spn value is likely wrong if it's in the form of user@realm and instead should be foo/service.domain or foo/service.domain@realm
  • neelesh bodgal
    neelesh bodgal over 2 years
    are there any downsides of this approach compared to using SSPI?
  • Travis Rivera
    Travis Rivera over 2 years
    How do you verify this service token?