Each enterprise has many languages they use to solve their technology problems. C# and Java are the predominate languages used in most enterprises. However, I have noticed a distinct difference between these two types of developers. Enterprises that use Microsoft Active Directory have very little problem with authentication for applications developed using C# (or Visual Basic). NTLM and Kerberos are natively supported for authentication by all .Net applications. Authentication looks like the following (C#):
It is literally one property to set on most networking libraries. Even when you do not want to use default credentials, there are a rich set of libraries, particularly the
System.Net.NetworkCredential class that enables better authentication. Now here is the question: which authentication scheme are you using with this? NTLM, or Kerberos?
For Java developers, however, the problem was much more complex. I had many Java developers reaching out to me to understand how to properly authenticate to SharePoint. They assumed they had to use NTLM to authenticate to SharePoint. And indeed, the default way web applications are setup for SharePoint is with NTLM. However, many enterprises whom have hybrid Linux and Windows environments need to use Kerberos as their primary authentication system, as Kerberos works far better on Linux than NTLM.
The purpose of this article is to share how to authenticate Java applications with SharePoint using Kerberos in order to consume SharePoint REST APIs. I did not have extensive experience writing software in Java, much less Java for the enterprise - so these notes may simplify some concepts that are well-known to Java developers. However, if this problem were so easy to solve, why did I have so many Java developers reaching out to me to help them figure out how to solve it?
Note: This article assumes the SharePoint environment you are connecting is properly setup for Kerberos authentication. This includes ensuring that the web application is configured for Kerberos authentication, and all SPNs are properly registered.
Additional Note: For brevity, the code snippets here are greatly simplified and intentionally void of error handling.
Jumping to Code
I first attempted to understand this problem by writing some code that was meant to just connect to a SharePoint REST service and get data. This is my most basic implementation, which you can see is void of really any authentication details. Keep it simple stupid, right?
Needless to say, the above code did not work. At the point where the request was executed, the HTTP response status code would be
HTTP 401 UNAUTHORIZED, indicating that authentication credentials were not sent in the originating request.
After further research, I stumbled upon some samples that were posted online. I tinkered with those samples and resulted in the following class. This was my first attempt which really worked:
I ended up with a proper JSON response (returned as a string) from this. However, there were several things I did not like about this implementation:
- The method
get()had too many responsibilities. It was responsible for configuring authentication as well as executing a REST call.
- The authentication was limited to only SPNEGO, which is a negotiated authentication mechanism of Kerberos first, falling back to NTLM. What happens if I want to use only Kerberos? Or multiple types of authentication?
I continued doing more research and resulted in finding the following, slightly more complex and alternative way to do this. It was derived from the works of the Spring Security Kerberos Client:
The above class worked like a charm, and provided the best of single responsibility (although the private method should be moved to a different class), but nevertheless simplified the responsibilities of each method.
Configuring Java How to Authenticate Using Kerberos
Authentication in Java is performed by the Java Authentication and Authorization Service (JAAS). JAAS has a number of “defaults” that it uses when attempting to perform authentication, including Kerberos. We need to get an understanding of how Java authenticates using Kerberos within your corporate environment. This is dictated by two files, the
login.conf and the
First, let us look at the
login.conf file. From what I can tell, this file has no default “global” configuration, so you will need to create it from scratch. It has the following format:
The following is my
login.conf for the classes above (and classes I depend upon). It may be overkill, but it works:
The second file is the
krb5.conf file. This file is the kerberos configuration file, which tells what domains and realms are supported for authentication via Kerberos. The documentation (and purpose) of this file can get fairly complex given the corporate environment. However, if yours is setup correctly, you may not need to make any changes.
krb5.conf file is located at
%JAVA_HOME%\lib\security\krb5.conf. If you open it up, it may look like the following:
What this means is if I try to authenticate to a host that has a domain suffix of either
exchange.othercorp.chrisweldon.net), Kerberos libraries will know what KDC servers to perform the authentication against.
Now, suppose you have a machine that is in your enterprise, but has an alias for a different domain, such as
sharepoint.chrisweldon.com. Even if that server is connected to the
CORP.CHRISWELDON.NET domain in Active Directory, the fact that you have an alias not listed in your
krb5.conf file will cause you issues. So, copy the default
krb5.conf file to your project directory and edit it to look like the following:
You are ready to execute your Java application! Simply specify the following arguments to ensure your app is looking at your custom configuration files and it will be authenticating to SharePoint!