# Kerberos.NET: a Kerberos implementation in pure managed code

> Kerberos.NET is a complete Kerberos library for the .NET platform, written entirely in managed code, and the interesting part of it is not only that it exists but the shape of the governance around it. The readme contains one of the most careful statements of support boundaries you will find in an open source security project, explaining in detail exactly who will help you when something goes wrong and who will not.

**dotnet/Kerberos.NET** — A Kerberos implementation built entirely in managed code.

- Repository: https://github.com/dotnet/Kerberos.NET
- Stars: 567 · Forks: 110
- Language: C#
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/dotnet-kerberos-net

## What the library is

Kerberos.NET is a complete Kerberos library built entirely in managed code without many operating system dependencies. The project is supported by the .NET Foundation, is published as a package, and is MIT licensed.

The phrase without many operating system dependencies is doing real work, and the parenthetical about many is careful. Kerberos is a protocol with a long history of implementations that lean on the host's cryptography, its keytab handling, its DNS resolution, and its configuration parsing. A managed implementation can avoid all of that, at the cost of having to implement the pieces itself, and the trade is worth making when the target platform does not ship a client worth using or when the application wants to control the behaviour.

The scope is stated plainly: it is a library that lets you operate on Kerberos messages, and there are three ways to use it. You can run a client, you can host your own key distribution centre, or you can just validate incoming tickets. That third option is the one that gets overlooked, and it is probably the most common one in practice, because a web application that receives a Negotiate header needs to turn it into an identity and does not care about the rest of the protocol.

And the stated intent is to be as lightweight as possible. For a security library, that phrase deserves a second look, because lightweight often means small surface and fewer dependencies, which in a protocol implementation means fewer places where a mistake can hide. The readme links a deep dive into the design, written by the author, and says it is worth a read, which is a reasonable thing to say about a project where the implementation choices are the substance.

The project is primarily a library, and it also ships a set of tools that wrap it, which the readme describes as useful for building applications and troubleshooting Kerberos issues. That word troubleshooting is the clue to why the tools exist: a protocol with this many moving parts is very hard to debug without being able to look at the messages.

## The support statement

The support section of the readme is the most unusual document in the repository, and it is worth reading carefully rather than skimming, because it defines what will happen when you have a problem.

The first line is that this library is not officially supported by Microsoft. Then there is a specific case, which is the reason the section exists at all. If you are using the library through Oracle's data provider for .NET, Kerberos.NET is supported only via Oracle Support. You must contact Oracle Support even if you know the problem is in the library. Oracle Support will work with Microsoft directly if the problem turns out to be in Kerberos.NET. And Microsoft will close support cases created directly with Microsoft for this library.

Then the summary, which is the part worth remembering.

The repository is not officially supported by Microsoft, despite the fact that some Microsoft employees might be managing it and contributing to it. They are doing it either in their free time, or partially as work time for internal usage, without any service level agreement from Microsoft or from Microsoft employees.

There are two things about that paragraph. The first is that it is unusually precise about the ambiguity: a project can be maintained partly by the vendor's own employees and still have no support commitment from the vendor, and the readme says so rather than letting a reader infer support from the fact that the commits come from a particular email domain. The second is that it explains the Oracle arrangement as a workaround rather than as a policy, which tells you the shape of the relationship without pretending it is a partnership.

For a reader choosing a dependency, this is genuinely useful information and it is the kind that usually only appears in a support ticket six months later. A library that says outright that it has no support commitment lets you plan for that. A library that is vague about it lets you discover it at the worst possible moment.

And the corollary is that a user with a problem in this library is best served by the community channels and by reading the source, which is another argument for a managed-code implementation: the code is there, in one language, on the same platform you are running on.

## The client, and the token it produces

The client is described as intentionally simple compared with the clients found on other platforms, and it is fully featured and supports generating SPNEGO messages.

The example shows the whole flow, and it is short enough to take in one look.

```C#
var client = new KerberosClient();

var kerbCred = new KerberosPasswordCredential("user@domain.com", "userP@ssw0rd!");

await client.Authenticate(kerbCred);

var ticket = await client.GetServiceTicket("host/appservice.corp.identityintervention.com");

var header = "Negotiate " + Convert.ToBase64String(ticket.EncodeGssApi().ToArray());
```

The credential takes a principal and a password and is used to authenticate, which yields a ticket granting ticket. Then a service ticket is requested for a service, given as a principal name in the usual slash-separated form. And then the ticket is encoded into the generic security service application programming interface form and base64 encoded behind a Negotiate prefix.

That last line is the part that matters for most applications, because that string is the HTTP authentication header. A server receiving a Negotiate header does not care how the ticket was obtained; it cares that it can validate it and turn it into an identity. Which is why the library's three usage modes all boil down to the same thing at different levels of effort.

The note that the client is intentionally simple is worth pausing on, because a security library that is simpler than the alternatives is usually simpler by omitting something. Here the readme says it is fully featured, and the simplification is in the shape of the interface rather than in the protocol coverage: one credential object, one authenticate call, one call to get a service ticket, and the encoding step. There is no configuration object, no pluggable transport, and no provider chain, because all of that is the kind of thing that a managed implementation on a single platform does not need.

Getting the library is also simple, and the readme offers two routes: download the code and build it locally, or, better, use the package.

```powershell
PM> Install-Package Kerberos.NET
```

The second option being described as better is a small editorial judgement, and it is the right one for a library that is going to be referenced by version in an application's manifest.

## Hosting a key distribution centre

Hosting a key distribution centre is described as a little more complicated, and the reason given is concrete: it requires listening on a particular port, usually port eighty-eight.

That is the whole of the difficulty, and the example shows the shape of the setup.

```C#
var port = 88;

var options = new ListenerOptions
{
    ListeningOn = new IPEndPoint(IPAddress.Loopback, port),
    DefaultRealm = "corp.identityintervention.com".ToUpper(),
    RealmLocator = realmName => new MyRealmService(realmName)
};

var listener = new KdcServiceListener(options);

await listener.Start();
```

Three things in the options object are worth reading individually.

The listening endpoint is an ordinary socket endpoint, and the example binds to the loopback address, which is the right default for a test and the wrong one for a service. Binding to the wildcard address is a one-line change, and the readme's use of the loopback address in the example is a reasonable default for a first run.

The default name is uppercased in the example, and that is not incidental formatting. Kerberos domain names are conventionally upper case, and the library is showing you that the comparison is done in a specific way. The readme does not say the library normalises it for you, and the example uppercasing the string yourself is a hint that you should.

And the domain locator is the extension point that makes the whole thing usable, because it is a function from a name to a domain service object. That single delegate is where your identity store plugs in: the library asks for the domain, you give it something that knows the principals, the keys, and the rules. Everything else about hosting a key distribution centre is protocol mechanics, and this is the one place where the protocol meets your organisation.

The listener itself is started with an await, and the readme says it will wait until the stop method is called or the object is disposed. So the hosting pattern is the ordinary asynchronous one: start, do something else, and the listener runs until you say otherwise. The samples directory carries a host application for exactly this, along with a sample that runs a local key distribution centre, which is the piece a developer needs to test against without involving a directory server at all.

## The authenticator and the two stages

Ticket authentication happens in two stages, and the readme describes them precisely, which is useful because the split tells you where to put your own code.

The first stage validates the ticket for correctness, and it happens through an interface for validation with a default implementation named for the validator. The second stage converts the ticket into a usable claims identity, and the readme names the type: a specific identity type that derives from the framework's claims identity, produced by the authenticator.

So validation and conversion are separate, and the separation is the point. Validation is a question with a yes or no answer: is this ticket well formed, is it for this service, is it within its time window, is it signed by something we trust. Conversion is a question about representation: turn the validated ticket into the set of claims your application uses, with the claim types, the authentication type, and the name.

For most applications, only the second stage matters, because the first stage is where the security is and it should not be skipped or customised. But keeping them apart means you can rely on the default validation and still control how identity is represented, which is exactly the case where a company has its own claim conventions.

And the readme is explicit that the second stage is overridable, for the case where you need to tweak the behaviour of the conversion. That is a deliberate seam in the design: the library will not stop you from writing your own conversion, and it will not let you write your own validation without going around the interface that exists for it.

The easiest way to get started, the readme says, is to create an authenticator and call the authenticate method. So the common case is one object and one call, and everything else is there when you need it.

## The tools, and what is in the repository

The tools are the part of the project that turns a library into something you can operate, and there are two of them.

The first is a Fiddler extension, with the installer published among the releases, and a separate write-up on how to install and use it. A network debugging proxy that can decode Kerberos messages is worth having for anybody who has ever needed to look at what went over the wire during an authentication, and the readme says plainly that the project includes tools for troubleshooting Kerberos issues.

The second is the Bruce command line tool, a collection of utilities that interact with the library's components, installed as a global tool. It covers ticket cache and keytab management, and it includes the ticket decoder. The design rule it follows is stated, and it is the right rule: the tool more or less follows the MIT and Heimdal command line standards, so if you have used the native tools on a Linux machine, the verbs will be familiar. The list reads like that: a tool to view and modify the configuration file, a decoder for tickets that can optionally decrypt them if you know the secrets, a tool to delete ticket cache files, one to authenticate a user and request a ticket granting ticket, one to view the tickets in a cache, one to send a request to a key distribution centre to get metadata for a user, one to view and manipulate keytab files, and one that requests a ticket for the current user and formats the details. And a verbose parameter that turns on detailed logging.

The repository layout matches that split. The main library has its own directory, the command line tool has its own, the Fiddler extension has its own, and there is a separate project for portable name resolution. There is a samples directory with a set of sample projects, and the names are a table of contents of the use cases: a crypto helper, two dump tools, a tester, a client application, a key distribution centre host application, two middleware samples including an end-to-end one, a web sample, and a local key distribution centre sample. There is a tests directory, a tools directory, a configuration directory, a documentation directory, and a build definition.

The supporting files are the ones that show the project's conventions. There is a style configuration, a ruleset for code analysis, a code coverage settings file, an editor configuration, a signing key for strong naming, a version manifest, a notices file, and a support document at the root, next to the contributing guide and the code of conduct. Having the support document at the root rather than only in the documentation site is a small courtesy to whoever arrives with a problem.

## Conclusion

Kerberos.NET fits a.NET application that needs to speak Kerberos without the operating system dependencies that the platform's own tooling brings, and a team that wants to host a key distribution centre or validate tickets inside its own process. It does not fit an organisation that needs a support commitment from a vendor. Verify first which of the three uses you actually need, that the default domain matches your directory, since the default name is uppercased and the locator is what maps a name to your identity store, and that you read the support statement in full before deploying it, because the boundaries in it are specific and they are the boundaries you will hit.

## FAQ

### What is Kerberos.NET?

It is a complete Kerberos library for .NET written entirely in managed code, without many operating system dependencies. It lets you operate on Kerberos messages in three ways: run a client, host your own key distribution centre, or just validate incoming tickets. It is supported by the .NET Foundation and MIT licensed.

### Is Kerberos.NET supported by Microsoft?

No, and the readme says so explicitly. Some Microsoft employees manage and contribute to it in their free time or partially as work time for internal use, without any service level agreement from Microsoft. Usage through Oracle's data provider is supported only through Oracle Support, and Microsoft will close support cases opened directly about this library.

### How do I use the Kerberos.NET client?

Create a client, build a password credential with the principal and password, await the authenticate call, request a service ticket for the service principal, and then encode the ticket into the generic security service form and base64 encode it behind a Negotiate prefix, which is the header a web server expects.

### What does the Kerberos.NET authenticator do?

Authentication happens in two stages. The first validates the ticket for correctness through a validator interface with a default implementation. The second converts the validated ticket into a claims identity, which is a specific identity type deriving from the framework's claims identity. The conversion behaviour can be overridden, while validation is left to the default.

### What command line tools come with Kerberos.NET?

There is a Fiddler extension for inspecting Kerberos messages on the wire, and the Bruce tool, a global command line utility covering configuration files, ticket decoding, ticket cache and keytab management, authenticating a user, listing cached tickets, and querying a key distribution centre for user metadata. The tool follows the MIT and Heimdal command line standards and takes a verbose parameter.

## Sources

- [dotnet/Kerberos.NET on GitHub](https://github.com/dotnet/Kerberos.NET)
- [Issues](https://github.com/dotnet/Kerberos.NET/issues)
- [License: MIT](https://github.com/dotnet/Kerberos.NET/blob/develop/LICENSE)
- [README](https://github.com/dotnet/Kerberos.NET/blob/develop/README.md)
- [Releases](https://github.com/dotnet/Kerberos.NET/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dotnet-kerberos-net
