Search code examples
single-sign-onkerberosgssapisspi

SSO using Kerberos on Windows and Linux


We have a client/server based application that is developed internally. Clients and server communicate over a TCP/IP connection with an application-specific protocol. The clients run on Windows and the server runs on Linux. All machines are in the same Active Directory/Kerberos domain/realm.

Currently, the user enters a username and password when they start the application. The server checks the username and password (authentication). Based on the username, the server also determines access to resources (authorization).

We want to add Single Sign-On (SSO) capabilities to the application. That is, we do not want the user to enter a username and password but we want to automatically logon as the current Windows user.

Of course, determining the current Windows user has to be done securely.

I have come up with the following setup:

  1. I use SSPI (Negotiate) on Windows and GSSAPI on Linux.
  2. When the client connects to the server, it uses AcquireCredentialsHandle (Negotiate) to get the credentials of the current Windows user.
  3. The client uses InitializeSecurityContext (Negotiate) to generate a token based on these credentials.
  4. The client sends the token to the server.
  5. The server uses gss_acquire_cred() to get the credentials of the service. These are stored in a .keytab file.
  6. The server receives the token from the client.
  7. The server uses gss_accept_sec_context() to process the token. This call also returns the "source name", that is the current Windows user of the client.
  8. The server uses the "source name" as the username: the server performs no additional authentication. The server still performs authorization.

This works but I do have some questions:

  1. Is this secure? It should not be possible for the client to specify any other username than the Windows user of the client process. If a user has the credentials to create a process as another user (either legally or illegally) than this is allowed.
  2. Should I perform additional checks to verify the username?
  3. Are there alternative ways to achieve SSO in this setup? What are their pros and cons?

Solution

  • What you've described here is the correct way to authenticate the user. You should not have to worry about the user specifying a different name; that's what Kerberos takes care of for you.

    If the client is able to obtain a service ticket, then they must have been able to authenticate against the KDC (Active Directory). The KDC creates a service ticket that includes the user's name, and encrypts it with the service's secret key.

    The client would not be able to create a ticket for the server with a fake name, because it doesn't have the necessary key to encrypt the ticket.

    Of course, this all assumes that you've set everything up correctly; the client should not have access to the service's keytab file for example, and the service should not have any principals in its key tab except its own.

    There's a pretty detailed explanation of how it works here.