RSS feed
<< Implementing decorator templates with Apache Velocity | Home | Exploring the Glassfish commit history with SVNSearch >>

Yes, cross-platform Single Sign-On for Java Webapps is possible.

A customer participating in the SVNSearch beta round asked me about Single Sign-On solutions for SVNSearch. SSO has become something of holy grail in the Enterprise. Everyone wants it but few seem to really achieve it. The Wikipedia article for Single Single-On even cites a Gartner report stating that "no one can achieve it without a homogeneous IT infrastructure".

What could be a better motivation than Gartner saying it's impossible? I decided I'd prove them wrong and took on the task to create a cross platform, Single Sign-On solution for SVNSearch.


The NTLM headache

As it turns out, there are only a couple of options available for Web SSO . The Java CIFS Client Library (JCIFS) implements Microsoft's NTLM technology. NTLM is a challenge-response authentication mechanism, and being a product of Microsoft it's not much of a surprise that it has a history of security weaknesses.

NTLM has caused me lots of headache on a past project because it doesn't play nice with the basic rules of HTTP. NTLM is a connection-oriented protocol, so both the server and the client needs to keep the same TCP connection open for at least the three request it takes to do the authentication. This is just fine when Internet Explorer is talking to Microsoft's IIS server, but when you introduce a web server like Tomcat, weird things start happening.  In our case Tomcat would start sending Connection: close headers under heavy load. This is a perfectly sensible thing to do – if you're running low on available threads, turing off keep-alive is  better than refusing requests. But in the NTLM case it made Internet Explorer fail with a non-decipherable error page.

Finally, NTLM isn't really cross platform. Both Firefox and Safari have adopted NTLM, but they'll pop up a username/password dialog on non Windows platforms.

Enter Kerberos

So you might not be surprised to hear I wanted something better than NTLM. I'd been reading about Kerberos for years, but my impression was that it required an army of sysadmins to set up and a Ph.D in cryptography to create software for it.  Then I realized Microsoft actually use Kerberos for their domain controllers so I already had the infrastructure set up. I started looking for open source projects implementing Kerberos authentication, but I couldn't really find anything. There were a lot of pointers to a an old patch providing Kerberos support for JCIFS, but it doesn't seem like it ever got applied.

So it seemed like I had no option but to roll my own. In doing so, I had to spend some time trying to understand how Kerberos works. And it's not really that hard. Every time you log on to your Windows Domain Controller, Windows acquires a Kerberos token from the Domain Controller. This token can be used to fetch another type of token that lets you log into network services like my Java based web server. The service also has to authenticate itself and that is taken care of by issuing KeyTab files containing secret keys for the service.

The implementation

Kerberos is implemented in Java through the GSS API. GSS is a just a wrapper API around token based security mechanisms like Kerberos and doesn't provide any security itself. The authentication of the service is done through a JAAS LoginModule, the Krb5LoginModule.  The module needs to be configured to use a KeyTab file and to store the credentials in the Subject. This way the credentials can be used in the next step when authenticating users. You only need to do the service login once, after that you can keep the Subject around as long as the service is running.

It's important to name the service principal correctly. The principal name needs to match the host name of the service  and the host name needs to have a DNS A record who's IP address resolves back to the host name. User authentication is done through the GSSAPI. I'm using the GSSManager to create a GSSContext. This context is then fed the Kerberos token in the acceptSecContext() method and  if isEstablished() returns true we can fetch the identity of the authenticated user with getSrcName().

Web-based Kerberos

Kerberos was invented before the web and doesn't specify how tokens should be transported in a web context. Microsoft implemented SPNEGO in Internet Explorer 5.01 as an HTTP authentication mechanism. When the server requires user authentication it sends a HTTP 401 status back to the user with a «WWW-Authenticate: Negotiate» header. The browser then resubmits the request, now with a «Authorization» header containing a security token. This ping-pong game continues until the underlying security mechanism is negotiated and the user is authenticated. SPNEGO is a pseudo mechanism used to negotiate the use of a real mechanism in the case that the server and client don't agree on a mechanism upfront. SPNEGO is implemented in Java 1.6 as a part of the Java GSS API. However, the SPNEGO token is DER encoded so it's pretty straight forward to extract the real  Kerberos token from a SPNEGO token if you're running on Java 5 or 1.4.



Cross-platform support

OS X supports Kerberos. You can set up OS X to acquire Kerberos tickets when logging in or you can use kinit command line tool or the graphical utility Kerberos.app for  ticket administration. Most Linux distributions also have Kerberos support. Kerberos is supported in  both Safari and Firefox, although Firefox doesn't send SPNEGO tokens but pure Kerberos tokens instead. So my code needed to take that into account.

The result

Although it did require a fair amount of research and development I must say I'm very happy with the end result. I now have a 100% pure Java Single Sing-On toolkit. Having complete control of the authentication process also gives some nice extras. I can present the user with a fallback login page if automatic login fails. I can also let the administrator test the Kerberos configuration and provide some useful feedback if something doesn't work.

If there's any interest in this  code please let me know. I might consider making a small open source project out of it or contribute it to an  existing project. And to the Gartner dudes: I now have Kerberos based SSO solution that works great in a cross-platform environment,  so go eat your socks!



Re: Yes, cross-plattform Single Sign-On for Java Webapps is possible.

Yale CAS has been available for years.  It isn't limited to Java webapps.  It's also used by 100's of companies and support for it is built into Spring.

Re: Yes, cross-plattform Single Sign-On for Java Webapps is possible.

I'll definitely look into Yale CAS and the JA-SIG project. I guess my point wasn't that nothing existed but that I didn't find it. So thanks for the pointer! There's also the benefit that implementing something myself gives a better understanding of the technology. But know that I have that knowledge I might be better off using something like JA-SIG.

Thanks, Eirik.

Yes, cross-plattform Single Sign-On for Java Webapps is possible.

You may also want to check out Atlassian's Crowd, which is quick to configure as a standalone application and has connectors for Java, .NET, Apache, Subversion, Ruby and PHP.

The integration API is very simple and can be integrated with just about any application that support pluggable authentication or with custom applications in a few hours.

Yes, cross-plattform Single Sign-On for Java Webapps is possible.

Justen,

While my focus in this entry was Kerberos and Single Sign-On, I'll certainly keep an eye on Crowd. I actually plan to support Crowd as an authentication and user/group backend for SVNSearch.

Do you guys have any plans to include Kerberos support in Crowd? Without that Crowd isn't strictly Single Sign-On. There is one login to your OS and then one to log into any or all Crowd based services. The passwords may be the same but the user still sees two login dialogs.

Re: Yes, cross-plattform Single Sign-On for Java Webapps is possible.

While both Crowd and CAS seems like excellent products, what I was looking for here was a small, standalone library that I could easily embed into SVNSearch. Installing an extra server-based product just for Kerberos support is too much overhead for my use case and for my customers.

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Hi,

To answer your question - YES there definitely is interest in this code. There's nowhere near enough good details on implementing java webapp SSO on the web. It's been driving me mad - seeing your implementation would be a big help!

Thanks.

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

I have interest in your code too.
Correct if i'm wrong, but in an Active Directory infrastructure your code does 2 thing:
- automatic authentication (using logon local PC credentials);
- integration with AD (for full integration,eg. groups you could see it as a generic LDAP, so it could be reused in non-AD scenarios);

If it's correct ,to my knowledge you are the only (eventually open source) one not using NTLM but kerberos, that's why my interest.

Good work.

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Garidan,

The code I'm talking about here provides purely Kerberos automatic authentication against a Kerberos KDC (like Active Directory)

SVNSearch also has LDAP integration, but you'll find tons of open source projects implementing authentication and directory access against LDAP.

I can't guarantee you there's no open source code out there doing Kerberos automatic authentication, but I haven't been able to find it. If somebody does, that's great, let me know!

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Hello Eirik, I'm so happy to see someone else looking into this – and blogging about it! Although source code would be great, just having a description of an implementation that works is a huge help. Also, the knowledge that I'm not crazy; there are others out there doing this makes me so happy! I to have been searching a long time to find some kind of small, standalone Java library for this. Please share the code. Thanks!

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Thanks for explaining your findings. It has been very informative. Right now, I am researching to implement exactly what you did in a web application server. When do you plan to release your code? It would be so helpful for a lot of people. Juan C

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Hello Eric,
  I am curios about your code. Can you send it to me or give me svn url and rights for read?
Also I would like to ask you, whether kerberos is suitable for internet web single sing on. Because internet user is not logging to domain, e.g. he is using web in Internet cafe, etc...

Jan

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Jan,

I hope to realease the code as open source eventually but until then I unfortunately cannot share the code.

Kerberos is typically only useful in an intranet setting. You can however detect that the user is not sending a Kerberos ticket and then provide an alternative way of providing credentials such as a login form.

This is something you should be doing anyway since not all clients on an intranet are guaranteed to have kerberos tickets.

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Can you share your code?

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Hello Eric,

I am looking for spnego java library and I wonder to know if you release your code as open source?

Best Regards
Michal

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Hi Eric,

What is the status on releasing the code as open source? It would be a great help.
Thanks,

Daniel

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Daniel,

The current status is that I'm talking with a company that might want to be a sponsor in releasing the software as open source.

Thanks for you interest,
Eirik.

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Any latest news about open-sourcing your solution? I implemented my NTMLV2 SSO using Jespa. I'm looking for a solution 100% in  kerberos.

 

Thanks,

Alberto Acevedo

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Hi Eirik,

Any news on open-sourcing your code ? I have the same need and jcifs combined with Tomcat doesn't work 100% of the time, so I badly needed a better solution.

Thank you,
Billy

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Hi all!

There's a very interesting commercial solution called Jespa. It is free for small-scale use.

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

 

You may check JOSSO (http://www.josso.org)

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

Spring Security 3.0 will contain a Kerberos/SPNEGO extension and that should do the SSO trick and it's free! There's already a milestone release available. Blog about the Kerberos/SPNEGO extension

Re: Yes, cross-platform Single Sign-On for Java Webapps is possible.

It looks like a lot of people are interested in seeing some source code...

Here's an open source library, http://spnego.sourceforge.net, that implements Kerberos/SPNEGO.

The project also has lots of working examples as well as instructions for Tomcat, JBoss and Glassfish.

Enjoy!

Add a comment Send a TrackBack