Troubleshooting Kerberos on macOS
How to use the Kerberos command-line programs built into macOS to obtain Kerberos tickets
Published in Articles on by Michiel van Oosterhout ~ 8 min read
Using macOS as a developer in an enterprise environment built on Windows Server means you may need to authenticate to servers using the Kerberos protocol at one point or another. This is because Windows Server and Active Directory use Kerberos 1. Having struggled with this recently, I decided to write this guide for connecting to a SQL Server using Kerberos.

About Kerberos
Kerberos is a client-server authentication protocol, and it can be used to connect to SQL Server using an Active Directory credential from a non-Windows operating system such as macOS. This involves a trusted 3rd-party (the authentication server). The current version of Kerberos is version 5, and is described in RFC 4120.
Tickets
The client (a principal) requests a credential to be used with the SQL Server server (also a principal) from the authentication server. The authentication server has a database of principals, which in our case, is the Active Directory database. This server and its database is said to be in a realm, and the realm is part of a principal's identifier.
The client receives either:
- a ticket for the SQL Server server from the authentication server,
- or a ticket for a ticket-granting server.
We'll call the former a normal ticket (not an official term). The latter ticket is called a ticket-granting ticket, and can be used to ask the ticket-granting server for a normal ticket for the SQL Server server.
Exchanges
Communications between client and server are known as exchanges, and there are three such exchanges:
- authentication server exchange: to obtain a normal ticket or a ticket-granting ticket
- ticket-granting server exchange: to obtain a normal ticket (requires a ticket-granting ticket)
- client/server exchange: requires a normal ticket
Configuration on macOS
With all of that theory out of the way, we need to configure Kerberos on our macOS computer. This is done in /etc/krb5.conf
. We will add realms that contain servers we'd like to use to this file. The file uses sections ([section]
) and relations (key-value pairs, key = value
, optionally nested key = { ... }
).
We can add the default_realm
relation to the [libdefaults]
section, but for the sake of learning it helps to do this only when everything is working, because it forces you to be specific in your command-line commands at the start.
First we add the realm to the [realms]
section, with the address of the KDC (i.e. the authentication server and ticket-granting server):
[realms]
EXAMPLE.LOCAL = {
kdc = dc.example.local
}
The address of the KDC is made known to clients via a special type of DNS record, the SRV record. These records are service-, protocol- and domain-specific, meaning they have a key like _service._protocol.domain.
, and they point to an A record. For Kerberos, the key to look for is _kerberos._tcp.example.local.
.
We can use nslookup
on macOS to query for Kerberos SRV records:
nslookup -type=srv _kerberos._tcp.example.local 10.0.0.1
The output of the nslookup
command should give you one or more SRV records, if not, you will have to ask your network administrator for the KDC address.
Configure the realm's kdc
relation in the Kerberos configuration file with the fully-qualified domain name of the KDC.
Getting our first ticket
Now we can use the kinit
command to obtain a ticket. But before we do, we will set an environment variable that will ensure full trace information is printed to stderr
when running kinit
. (Only stdout
output will be provided in the examples below.)
export KRB5_TRACE=/dev/stderr
Running just kinit
you may receive a prompt like this:
> kinit
michiel@LOCAL's password:
And if you provide a password (any password) you'll see this output:
kinit: krb5_get_init_creds: unable to reach any KDC in realm LOCAL, tried 0 KDCs
From this we can surmise that by default, my principal name is michiel@LOCAL. This is probably not my principal name in the database of the authentication server of the EXAMPLE.LOCAL realm. But doesn't matter, since kinit
did not even try to connect to that server, it tried to find a server for the LOCAL
realm.
Remember I said we should be explicit while learning? This is our first opportunity:
kinit michiel.van.oosterhout@EXAMPLE.LOCAL
When you see no output after typing your password, then the command completed successfully. (You can always run echo $?
to check that the exit code of kinit
was 0
.) Otherwise, you should be able to use the output on stderr
to understand the problem.
Now we can add the default realm to our configuration, so that we don't have to type it on the command-line:
[libdefaults]
default_realm = EXAMPLE.LOCAL
So from now on I don't need to be explicit about this realm, I can type kinit michiel.van.oosterhout
and @EXAMPLE.COM
is implied.
Checking the ticket
When the kinit
command completes without error, you will have received a ticket. Typically, this is a ticket for the ticket granting server. You can check your tickets with klist
:
> klist
Principal: michiel.van.oosterhout@EXAMPLE.LOCAL
Issued Expires Principal
Sep 25 14:35:42 2023 Sep 26 00:35:38 2023 krbtgt/EXAMPLE.LOCAL@EXAMPLE.LOCAL
This indicates that I have a ticket for the server krbtgt/EXAMPLE.LOCAL@EXAMPLE.LOCAL
. The name of the server starts with krbtgt
, so it looks like the ticket is for a Kerberos ticket-granting server.
Getting a 'normal' Kerberos ticket for a SQL Server server
The ticket for the ticket-granting server can only be used for that server. To get a normal ticket for some other server, we need to request it from the ticket-granting server using the kgetcred
command. We need to specify the principal identifier of the service for which we want to obtain a ticket.
For SQL Server, there is a default naming scheme for the SPN part of the principal identifier that we can use: MSSQLSvc/<FQDN>
, where <FQDN>
should be replaced by the fully-qualified domain name of the SQL Server server.
Combine the SPN with the realm by adding the @EXAMPLE.LOCAL
suffix to get the principal identifier. Use this to get a ticket for the SQL Server server:
kgetcred MSSQLSvc/sql297b.example.local@EXAMPLE.LOCAL
When the command exits without any output (and has exit code 0
), then you can use klist
again to check the normal ticket:
> klist
Principal: michiel.van.oosterhout@EXAMPLE.LOCAL
Issued Expires Principal
Sep 25 14:39:32 2023 Sep 26 00:39:32 2023 krbtgt/EXAMPLE.LOCAL@EXAMPLE.LOCAL
Sep 25 15:01:45 2023 Sep 26 00:39:32 2023 MSSQLSvc/sql297b.example.local@EXAMPLE.LOCAL
As you can see, the ticket for the SQL Server server expires at the same time that the ticket-granting ticket expires. This implies that the ticket-granting ticket was used to obtain the ticket.
With all of this working, we can be sure that our Kerberos configuration is correct, our username and password are correct, and we are authorized to access the SQL Server server. Now we can configure our database management tool (e.g. Microsoft's Azure Data Studio or JetBrains' DataGrip) to obtain the ticket for the SQL Server server itself. Let's look at the configuraton for DataGrip as an example
Configuring JetBrains DataGrip
DataGrip is a Java application, and it uses JDBC to connect to databases. JDBC uses drivers, Java packages specific to some type of database server (e.g. SQL Server). We will be using the Microsoft SQL Server driver from Microsoft (class com.microsoft.sqlserver.jdbc.SQLServerDriver
).
We will create a new Data Source. We give it a name and optionally a color (helpful to distinguish different environments), select Microsoft's SQL Server driver, set the Host field, and then select Kerberos in the Authentication field.
As we've seen above, when acquiring a ticket for the SQL Server server, we did not need to specify our username and/or password, because we were using our ticket-granting ticket. So we will not enter anything in the User or Password fields.
This should be enough to connect to SQL Server from DataGrip on macOs.
Ticket Viewer.app
macOS has a built-in application to get a ticket-granting ticket. It's called Ticket Viewer, and it can take the place of running the initial kinit
command on the command-line. You can add multiple identities, and it can store the password for each identity in the macOS keychain. After that a single click can renew or refresh a ticket-granting ticket.
Summary
When you have difficulty connecting to SQL Server from some database management software (DBMS) running on macOS using Kerberos, it helps to use the Kerberos command-line programs kinit
and kgetcred
, along with nslookup
to ensure you are able to authenticate and are authorized. Once you can obtain a Kerberos ticket for the SQL Server this way, any DBMS that supports Kerberos should be able to connect to that SQL Server as well.