Thomas
Thomas

Reputation: 41

How to save Kerberos Service Ticket using a Windows Java client?

I've written a simple Java HTTP Client that is running under Windows. The client communicates with a web server which requires Kerberos authentication through SPNego.

I'm experiencing two problems:

I've created a TGT via kinit in my JDK's bin folder. The following code snippet is used for making simple GET requests:

  static void testJavaHttpKerberosAuthentication() throws IOException {
    URL obj = new URL(URI);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
    int responseCode = con.getResponseCode();
    System.out.println("\nSending 'GET' request to URL : " + URI);
    System.out.println("Response Code : " + responseCode);

    BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();
    while ((inputLine = in.readLine()) != null) {
      response.append(inputLine);
    }
    in.close();

    //print result
    System.out.println(response.toString());
  }

Here's the content of my jaas.conf (as described here):

com.sun.security.jgss.krb5.initiate {
com.sun.security.auth.module.Krb5LoginModule required doNotPrompt=false useTicketCache=true;
};

I'm running my application with the following parameters:

-Djava.security.auth.login.config=D:\jaas.conf
-Dsun.security.krb5.debug=true
-Djavax.security.auth.useSubjectCredsOnly=false

I'm not using as a krb5.ini since my client obtains the correct KDC from the domain configuration.

I can generate a TGT for my credentials cache via the following command:

C:\Program Files\Java\jdk1.8.0_77\bin>kinit
Password for <user>@<domain>:
New ticket is stored in cache file C:\Users\<user>\krb5cc_<user>

And finally, here's the exception and Kerberos Debug Output for the case where authorization fails (ref. Problem 2). Please note that ctime is obviously wrong. I've had many different attempts and the timespan for the ctime ranges from 1970 to 2040. Interestingly enough, this doesn't happen for every request.

>>>KRBError:
 cTime is Wed Jun 07 12:24:03 CEST 2017 1496831043000
 sTime is Tue Mar 29 16:38:24 CEST 2016 1459262304000
 suSec is 283371
 error code is 34
 error Message is Request is a replay
 sname is HTTP/<spn>@<domain>
 msgType is 30
 KrbException: Request is a replay (34) - PROCESS_TGS

I've already tried to work with JAAS using Subject.doAs, but this is causing the same problems. Accesing the server via the browser works fine (although this is not comparable, as the browsers are using the Windows native credentials cache AFAICT).

I'd be thankful for some advice on how to debug a problem like this.

EDIT: Specifiying the path to the credentials cache via the KRB5CCNAME environment variable explicitly, does not change the behavior. It seems like the TGT is obtained from the Credentials Cache but Service Tickets are not stored there.

Upvotes: 4

Views: 7307

Answers (3)

Fabiano Tarlao
Fabiano Tarlao

Reputation: 3232

JAAS is not going to persist tickets into the cache, you have to use kinit or invoke kinit code programmatically by your code. I have wrote a SO question/answer on this problem here.

Upvotes: 0

Thomas
Thomas

Reputation: 41

Regarding the random time values that occassionally appear: we've found out that setting the udp_preference_limit = 1 in the krb5.ini resolves the problem. This effectively tells Kerberos to always try to use TCP first for sending packages. Apparently there is a problem when switching to UDP (not sure whether UDP is the problem or switching between protocols).

Upvotes: 0

Samson Scharfrichter
Samson Scharfrichter

Reputation: 9067

About the cache >> Looks like you don't specify what is the default cache on your system (cf. env variable KRB5CCNAME) so Java and kinit revert to a hard-coded default. And that's not the same default...

  • your version of kinit clearly uses the Linux standard i.e. a FILE:
  • Java typically uses the Windows standard i.e. the API: managed by the MIT-Kerberos-for-Windows service

Possible workaround: either use the Kerberos UI on Windows to create the TGT, or force Java to use the file cache by setting KRB5CCNAME.

Reference: MIT Kerberos documentation and especially the very last link about hard-coded default

~~~~~~~

About the random time values >> I have no clue.

Upvotes: 0

Related Questions