0

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?
rveerd
  • 3,620
  • 1
  • 14
  • 30
  • _"It must not be possible for the client to specify any other username than the current Windows user"_ > Good luck with that. To begin with, "current user" is ambiguous -- the owner of the current process? Because a Windows OS may have multiple sessions running (with legitimate Krb credentials each) -- multiple RDP sessions, scheduled task running in the background for a service account... – Samson Scharfrichter Dec 23 '18 at 20:15
  • Kerberos was designed for secure authentication over an insecure _network_. It does not protect from credentials theft on a client machine (e.g. leak of a keytab file). To protect against creds theft you will need different tools -- e.g. require that client auth uses a smartcard or similar hardware device, in interactive mode, to obtain a Kerberos ticket. – Samson Scharfrichter Dec 23 '18 at 20:20
  • @SamsonScharfrichter I mean the owner of the current process. If someone manages to hack to OS and gets access to things he or she shouldn't have access to, than that's a problem but not something I need to solve in my application. My application should be robust against things any user can do, such as changing an environment variable or using a hacked client application to send custom crafted messages. – rveerd Dec 24 '18 at 09:16
  • Seems I have implemented the solution as described in the answer to [this question](https://stackoverflow.com/questions/1337923/authenticating-users-using-active-directory-in-client-server-application) although that is for Windows only. It's an old question, so there may be better alternatives now. – rveerd Dec 24 '18 at 13:34

1 Answers1

1

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.

John B
  • 3,391
  • 5
  • 33
  • 29