Simple Kerberos client in Java?
Asked Answered
M

9

45

Applications such a Google's Chrome and IE can transparently handle Kerberos authentication; however I can not find a "simple" Java solution to match this transparency. All of the solutions I have found require the presence of a krb5.conf file and a login.conf file which nether of the above apps seem to require.

What is the best way to build a Java application with Kerberos SSO capabilities that just work?

[update]: to be clear I need a CLIENT side solution for creating tickets not validating them. Also, it seems that SPNEGO is the default "wrapper" protocol that will eventually delegate to Kerberos but I need to be able to handle the SPNEGO protocol as well.

Marven answered 27/4, 2011 at 12:44 Comment(2)
I did not check it out in detail, but have look at projects.apache.org/project.html?directory-kerby - maybe it helps (maybe not).Bunnybunow
I know this is 10 years old question but for me problem I was trying to solve past two weeks. Responding for future searches. Solution that worked for me: #70672908Hahnke
D
9

Oracle has an example using Java's SaslClient. I'm not a Java programmer, but when I pointed this out once to someone who is, they were able to make it work pretty quickly. It may still require a "conf" file somewhere (n.b. Kerberos uses environment variables, often starting with KRB5_, to know where to look for such files). Also note that Kerberos itself does not include a transport of any kind--your app needs to know how to send and receive the Kerberos payloads the way the server expects (and this is different depending on the server you are trying to authenticate with).

Edit: you edited your question, so here's a link related to SPNEGO in Java which might be of some use: http://download.oracle.com/javase/6/docs/technotes/guides/security/jgss/lab/part5.html

Doordie answered 27/4, 2011 at 12:55 Comment(0)
H
16

There is now a simple solution for this using the Apache HTTP Components Client 4.5 or greater. This is still marked as experimental in 4.5 so your milage may vary, but this is working fine for me in an enterprise context.

In addition to the HC 4.5 client jars you will need to have the httpclient-win, jna and jna-platform jars on your classpath, as provided with http-component-client. You then construct a Kerberos enabled HC-client as follows:

CloseableHttpClient httpclient = WinHttpClients.createDefault();

Or using the builder:

HttpClientBuilder clientBuilder = WinHttpClients.custom();

Which can then be customised as required before building the client:

CloseableHttpClient client = clientBuilder.build();

This solution works without any external configuration, and most importantly solves the issue where the in-built JRE mechanism breaks for users with local Admin rights on Windows 7+. This is possible because the Kerberos ticket is being retrieved directly from the SSPI API via JNA, rather than going through the GSSAPI provided by the JRE.

Example code from the http-components team

This was all made possible by the good work of Daniel Doubrovkine Timothy Wall and Ryan McKinley

Hypogenous answered 4/4, 2014 at 14:28 Comment(9)
Are you sure this works? I checked out the 4.4-SNAPSHOT and built and installed it locally (into my Maven repository) and tried the code above but was unable to authenticate. Is there something missing in this example, or am I just doing something wrong?Goodspeed
It is working in my environment. What goes wrong? Have you turned on debug output for HC? Are you sure you have the correct service principle for the service your are wanting to authenticate to?Hypogenous
I'm guessing this solution only works if your Windows/Active Directory credentials (username/password) are the same as the username/password for the Kerberos server. I have a scenario where that is not the case and the above code is not working for me. Is there a way to give it the proper username/password?Stocky
Where is it marked/documented as 'experimental'? Is that still the case, do you know?Gibun
@Gibun github.com/apache/httpclient/blob/trunk/httpclient-win/src/main/…Hypogenous
Thanks. WinHttpClients itself (the entry point AFAICT) doesn't mention that.Gibun
So does this require username/password in order to use it? That defeats the purpose of kerberos in my situation, so I'm just wondering. I want to be able to supply it the keytab file and have that log me in, or to just use the current logged in user.Mcgovern
@NicholasDiPiazza No user/password is required, that's the point! It acquires a Kerberos token from the OS via JNA for the current logged in user.Hypogenous
Will this solution add the "Authorization YII etc" in the client request header? when calling a rest api with kerberos? If not how to verify that kerberos is working and not NTLM. thanksMajormajordomo
M
10

Adding to David Roussels answer on url specific http based kerberos authentication:-

The reason why your code works is because your target SPN(server side principal) is configured to with HTTP/[email protected]. In that case it will work because you are not explicitly setting the token. URLConnection internally sets a token with that SPN

1 Perform steps(from my previous answer) to get a subject

2 Use gss api init sec context to generate a context token. There are numerous tutorials out there for this step

3 Base 64 encode the token

4 Attach the token to urlconnection:-

URL url = new URL("http://myhost/myapp")
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection(); = 
urlConn.setRequestProperty("Authorization", "Negotiate " + encodedToken);

5 Implement a priviledged action:-

//this internally calls the getInputStream
public class PrivilegedGetInputStream implements PrivilegedExceptionAction<InputStream>

6 Wrap the whole thing in Subject.doAs

//use prev answer instructions to get subject
Subject.doAs(subject, new PrivilegedGetInputStream(urlConnection)
Muniment answered 18/9, 2013 at 17:48 Comment(1)
I made an example project: github.com/nddipiazza/spnego-http-client of this approach. not perfect yet but it worksMcgovern
D
9

Oracle has an example using Java's SaslClient. I'm not a Java programmer, but when I pointed this out once to someone who is, they were able to make it work pretty quickly. It may still require a "conf" file somewhere (n.b. Kerberos uses environment variables, often starting with KRB5_, to know where to look for such files). Also note that Kerberos itself does not include a transport of any kind--your app needs to know how to send and receive the Kerberos payloads the way the server expects (and this is different depending on the server you are trying to authenticate with).

Edit: you edited your question, so here's a link related to SPNEGO in Java which might be of some use: http://download.oracle.com/javase/6/docs/technotes/guides/security/jgss/lab/part5.html

Doordie answered 27/4, 2011 at 12:55 Comment(0)
S
7

You don't actually need to do anything. In Java 6, on a Windows client machine you can do this:

new URL("http://myhost/myapp").openStream();

And negotiate authentication just works. At least it does for me. And the server I tested on only supports Negotiate, not NTLM auth.

Skirmish answered 20/7, 2012 at 10:2 Comment(5)
what does this have to do with creating Kerberos tickects?Marven
The original question was "What is the best way to build a Java application with Kerberos SSO capabilities that just work?". And I was pointing out that Java 6 does SPNEGO authenication for you on windows, so you don't need to deal with krb5.conf. Kerberos is used underneath. It just works, much better than I expected. Note this does mean you have to use the default HTTP client, and can't use apache commons http libs.Skirmish
now I understand what you're saying. I'll have to give this a try sometime.Marven
I think I'm being very dense but URL does not seem to have a getInputStream() method, do you mean openStream() (this doesn't work for me though on the same set up you describe.Emblazonry
ah yes, I meant openStream(). Did you install your JRE with the installer, or just unzip it? Maybe the installer does something to make it work.Skirmish
M
4

Ok if you want to avoid using a login.conf file you need to code differently:-

//define your own configuration
import javax.security.auth.login.Configuration;
public class CustomLoginConfiguration extends Configuration

//pass certain parameters to its constructor
//define an config entry
import javax.security.auth.login.AppConfigurationEntry;
private AppConfigurationEntry configEntry;

//define a map of params you wish to pass and fill them up
//the map contains entries similar to one you have in login.conf
Map<String, String> params = new HashMap<String, String>();

//define the configuration
configEntry = new AppConfigurationEntry(
            "com.sun.security.auth.module.Krb5LoginModule",
            AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, params);

//implement getappconfig method
public AppConfigurationEntry[] getAppConfigurationEntry() {
    return new AppConfigurationEntry[] { configEntry };
}

Now once you are done with this definition you can use this in you use this to fetch tickets from kdc

//get ticket in login context
LoginContext lc = null;
    lc = new LoginContext("lc", null, callback, new CustomLoginConfiguration(argumentlist));
    lc.login();

Now from here on you can fetch jaas subject and can basically do a ton of authentication stuff.

In case you need further pointers just leave a comment.

Muniment answered 18/9, 2013 at 17:31 Comment(0)
P
2

You can use system properties instead of config files to specify the KDC hostname and service name, but those things (at least) are mandatory....

Waffle will actually give you the information you need to set most of the properties, even if it won't get you a ticket. Look at the WindowsAuthProviderImpl class (the Waffle.chm help file shows the API).

I use JAAS do obtain a service ticket from Active Directory in two steps:

  1. Use Krb5LoginModule to retrieve the cached TGT and add it to the Subject.

  2. Use the Subject and GSS-API to retrieve a service ticket from the KDC.

There's a lot of good information and example code at The Java Way of Active Directory.

Punk answered 19/5, 2011 at 16:25 Comment(0)
R
1

I created a small tool to simplify connecting with httpclient to kerberos, you might want to give it a try. https://github.com/DovAmir/httpclientAuthHelper

DefaultHttpClient httpclient = new DefaultHttpClient();
AuthUtils.securityLogging(SecurityLogType.KERBEROS,true);
CredentialsUtils.setKerberosCredentials(client, new UsernamePasswordCredentials("xxx", "xxx"), "domain", "kdc");
client.executeMethod(httpget);
Roadbed answered 22/5, 2014 at 17:16 Comment(1)
Assume I have in a client app running in *nix, an Active Directory token, now I need to validate it, and get the user@domain and group list from the token/AD server. Is that possible ?Ealasaid
C
0

Use WAFFLE

Colourable answered 27/4, 2011 at 12:48 Comment(2)
That is for the server site, not a client.Colourable
It supports a client as well.Grinder
Q
0

Here's a good blog post on having a java client to use with Kerberos http://sachithdhanushka.blogspot.com/2014/02/kerberos-java-client-configuration.html

Quanta answered 26/2, 2014 at 3:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.