Question

In order to do client-side HTTP SPNEGO authentication with Java on Windows you need to set the Windows Registry key allowtgtsessionkey. This is well documented. What I do not understand is how people get around this? Most corporate sites would never accept to change this registry key in Windows for the sake of a single piece of software. Also think about the hassle if this needs to be changed on every workstation in the organization. But that's just theory because I've so far been unable to convince any of our customers to change this registry key.

I don't blame them. Most corporate administrators would see this a relaxing the security and will therefore object it.

I've read this: Is there a way in Java or a command-line util to obtain a Kerberos ticket for a service using the native SSPI API?

but it is now rather old.

So I really, really don't understand how people can make Windows + Java client + Kerberos work on anything but university environments, home users, and the like.

The question I get from corporate administrators is "why do we need to set this registry key when applications such as IE and Firefox have no problems doing SPNEGO without setting this key ?". Well, I know what answer is. It is because (most likely) that applications like IE and Firefox are based on the Windows native GSS API (SSPI) while Sun's Java uses its own implementation.

I'm assuming that using something like WAFFLE would solve the problem but I would favor a pure Java solution. I'm also assuming that it won't help to use Java based solutions such as Spring security or Apache HttpClient as they will all be suffering from this problem.

Any help or pointers would be greatly appreciated.

UPDATE1:

I've found that there's an RFE for this in Oracle's bug database. There's also a patch submitted on the matter by an Oracle employee and discussions on the JDK mailing list about this feature. Doesn't make me much wiser other than as far as I can understand this is not available in current Java 7, not even as experimental. Right?

UPDATE2:

The question is now alive again on the OpenJDK Security Dev mailing list.

Was it helpful?

Solution

Thanks for referencing my thread on the security-dev mailing list ;-) My mid-term goal is to make this patch available to Java 6+ through the endorsed class path. You might be interested in this WAFFLE ticket which I have created recently: https://github.com/dblock/waffle/issues/50

I have evaluated WAFFLE too but it is so not-Java-GSS-like that one has to create duplicate code, this is something I want to avoid by all means.

This entire issue is not exactly Oracle's fault. Microsoft is simply blocking any call to the session ticket through the LSA CallPackage function. The pretext is security. I would really like to know how SSPI is able to create a service ticket when I cannot reasonable access the TGT. Therefore such a closed source solution sucks.

Right now at the moment, you have only three options:

  1. Obtain the TGT again through Java means
  2. Try WAFFLE
  3. Write custom code

I have burried the crappy registry key because it does not work for local admin with domain accounts anyway. In my case, Tomcat dev on Windows I have resorted to call Java's kinit in the meantime.

OTHER TIPS

There is now a really good solution for this included in the Apache HTTP Client, using JNA to get the ticket from the native SSPI API. See this answer:

https://stackoverflow.com/a/22865583/381161

For someone looking for a simple solution with Java 8, Waffle is the best choice.

Code:

import java.net.URI;
import java.util.Base64;

import waffle.windows.auth.IWindowsSecurityContext;
import waffle.windows.auth.impl.WindowsSecurityContextImpl;

public class KerberosCredentiels {

  /**
   * Generate current user token using Kerberos ticket
   */
  public String retrieveToken(URI uri) {
    IWindowsSecurityContext clientContext = WindowsSecurityContextImpl.getCurrent("Kerberos", convertToSPN(uri));
    byte[] token = clientContext.getToken();

    return Base64.getEncoder().encodeToString(token);
  }

  private static String convertToSPN(URI uri) {
    StringBuilder builder = new StringBuilder();

    builder.append("http/");
    builder.append(uri.getHost());

    return builder.toString();
  }

}

Maven dependencies:

<dependency>
    <groupId>com.github.waffle</groupId>
    <artifactId>waffle-jna</artifactId>
    <version>1.8.3</version>
</dependency>

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>4.3.0</version>
</dependency>

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>4.3.0</version>
</dependency>

As of Java 13 there's now build-in support in the JDK for Windows' own GSS API (aka SSPI).

See Release Notes for Java 13 as well as JDK-6722928.

Update: This has now been backported to Java 11. You'll need to use Java 11.0.10 or later. You can recognize if your JDK distribution has support for SSPI if it includes a file named sspi_bridge.dll in the bin directory.

There's even a ticket to backport to Java 8 too but as of Nov 2021 it hasn't been implemented.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top