How do people make Java SPNEGO client work in Windows?
Asked Answered
O

4

17

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.

Onomastics answered 28/1, 2013 at 5:45 Comment(1)
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://mcmap.net/q/368873/-simple-kerberos-client-in-javaBrynne
P
10

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.

Preindicate answered 28/1, 2013 at 10:30 Comment(6)
Thank you SO much for your reply. Depressing, though. :-(Onomastics
"In my case, Tomcat dev on Windows, I have resorted to call Java's kinit in the meantime." Can you elaborate? Is that a potiential solution on the Windows client side or ?Onomastics
@nolan6000, plese leave a comment in the github issue. Regarding the kinit issue: yes I can, what is your use case? Do you have a fat client in Java?Preindicate
@nolan6000, I would go with option one. Gather the upn and password from the user, invoke the LoginContext, obtain the Subject and perform all ops OR you try waffle but as I mentioned earlier that solution is too alien.Preindicate
If I prompt the user for his credentials then I might as well use LDAP. After all the only advantage I see to dealing with the complexity of Kerberos is that it allows promptless SSO.Onomastics
You could perform an LDAP bind but here is more if you do Kerberos. You have mutual auth for example and credential delegation. Other systems do not offer this. If you are user auth only I would try to evaluate Waffle or write JNI code or use JNA to SSPI directly.Preindicate
O
2

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.

Onomastics answered 22/11, 2019 at 22:48 Comment(0)
B
1

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://mcmap.net/q/368873/-simple-kerberos-client-in-java

Brynne answered 2/10, 2015 at 14:57 Comment(3)
Very interesting. Wasn't aware of this. It seems to me that the Apache folks have chosen the only sensible path: getting the ticket from SSPI API. I wish core JRE could do the same. My only concern is why this is somehow tied to a HTTP library (Apache HTTP Client) and not more generally a security lib. Btw: There's a new HTTP Client coming out in Java 9 but I bet this is not on their agenda.Onomastics
You could roll your own Kerberos ticket using JNA if you don't want/don't need HTTP. Check out the WindowsNegotiateScheme source hc.apache.org/httpcomponents-client-ga/httpclient-win/xref/org/…Brynne
For those reading this answer: Do not rely on this module unless you know what you are using. This module is experimental and faulty. I have metioned this already several times on the HttpComponents Dev Mailing List.Preindicate
B
1

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>
Barely answered 4/11, 2021 at 15:59 Comment(2)
Interesting. Thumbs up for sharing. However, it is fully supported in the JDK itself as of v13, and you'll soon be forced away from Java 8 anyway, so maybe give Java 17 a try on this?Onomastics
Sorry, no need for Java 17 as wrote. The native support for SSPI in the JDK has now been backported to Java 11 too.Onomastics

© 2022 - 2024 — McMap. All rights reserved.