Windows Kerberos Authentication with java.net.Authenticator

 

Overview

Http Authentication

* Java SE supports:
– HTTP Basic authentication
– HTTP Digest authentication
– NTLM
– Http SPNEGO Negotiate with Kerberos and NTLM
* Uses java.net.Authenticator to
– enable authentication
– provide access to a store of usernames and passwords
* Work with both proxies and servers

java.net.Authenticator

* Is an abstract class.
* Represents an object that knows how to obtain authentication for a network connection, usually by prompting user for information.

* Subclasses override
getPasswordAuthentication() to acquire username and password.
setDefault(Authenticator) to register with the system and enable autehntication.
* Example:

    class MyAuthenticator extends Authenticator {
 
        public PasswordAuthentication getPasswordAuthentication () {
            return new PasswordAuthentication ("user", "pass1".toCharArray());
        }
    }

* Another example: http://nextmidas.techma.com/nm/nxm/sys/net/HttpAuthenticator.java
* Choose witch authentication scheme is used:
– By default, the implementation chosses the most secure protocol transparently.
– Can be overridden with -Dhttp.auth.preference=”scheme” system property.

Authentication Schemes

* Scheme preference: GSS/SPNEGO -> Digest -> NTLM -> Basic
* Specify no fallback with system proprety: http.auth.preference

Http Basic

* Not secure
* Defined in RFC 2317
* Username and password are encoded in base64
* getRequestingPrompt() returns the basic authentication realm as provided by the server

Http Digest

* More secure than Basic.
* Username and password are hashed with MD5
* Turn on mutual authentication:

  -Dhttp.auth.digest.validateServer="true"
  -Dhttp.auth.digest.validateProxy="true"

NTLM

* More secure than Basic, but less secure than Digest.
* Can be used with proxies or servers, but not both at the same time.
* Specify domain name:
– Prefix username with domain name followed by a backslash: domainName\username
– Use system property: http.auth.ntlm.domain

SPNEGO

* Negotiate scheme
* Only supports
– NTLM
– Kerberos

Kerberos 5 Configuration

* Use java.security.krb5.conf system property to point to Kerberos 5 configurations

java -Djava.security.krb5.conf=krb5.conf ...

or programmatically:

System.setProperty("java.security.krb5.conf", "kbr5.conf");

* Use com.sun.security.jgss.krb5.initiate entry in JAAS login config file to config which login moduel to use:

  com.sun.security.jgss.krb5.initiate {
      com.sun.security.auth.module.Krb5LoginModule
      ...
  };

IIS Kerberos Only Authentication Example

Domain Controller

* Windows 2003 SP1 Enterprise Server
– Computer name: DC01
– AD Domain name: MYTEST.local
– NetBIOS domain name: MYTEST
* Admin User:
– Administrator/Welcome1
* Client user domain name:
Jimmy.Li@MYTEST.local/Password1

* Application domain name (under which IIS runs as):
App.Service@MYTEST.local/Password1

IIS Server

* Windows 7
– Computer name: WIN7X64NOV3
* Local User:
Jimmy/Password1
* Login as domain User (otherwise cannot start IIS?):
Administrator/Welcome1
* IIS run as service account:
App.Service@MYTEST.local/Password1

Configure IIS

* Install IIS for Win 7:

* Enable Kerberos only authentication:

* Run IIS DefaultAppPool as an application user, e.g. App.Service

Setup SPN for IIS HTTP

* Login domain controller.
* Issue setspn commands:

# Add
setspn -A HTTP/win7x64nov3 MYTEST\App.Service
setspn -A HTTP/win7x64nov3.mytest.local MYTEST\App.Service
 
# List
setspn -L App.Service
 
# Delete when not needed anymore
setspn -D HTTP/win7x64nov3 MYTEST\App.Service
setspn -D HTTP/win7x64nov3.mytest.local MYTEST\App.Service

* See http://support.microsoft.com/?id=871179 for setspn command help.

Client Machine

* Turn on allowtgtsessionkey in registry. Otherwise you’ll get Integrity check on decrypted field failed error, because no TGT ticket could be read from LSA cache when you specify userTicketCache=true in the login.conf file.

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters
Value Name: allowtgtsessionkey
Value Type: REG_DWORD
Value: 0x01

* Also, for Windows 2008 domain, client user cannot be in domain administrator group. If you login client machine with a user who is in domain administrator group, you’ll need elevated privileges in order to read LSA ticket cache.

Java App: RunHttpSpnego.java

package test.http.auth.one;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
 
public class RunHttpSpnego {
 
  static final String kuser = "jdoe"; // your account name
  static final String kpass = "SecretPassword"; // your password for the account
 
  static class MyAuthenticator extends Authenticator {
    public PasswordAuthentication getPasswordAuthentication() {
      // I haven't checked getRequestingScheme() here, since for NTLM
      // and Negotiate, the usrname and password are all the same.
      System.err.println("Feeding username and password for "
          + getRequestingScheme());
      return (new PasswordAuthentication(kuser, kpass.toCharArray()));
    }
  }
 
  public static void main(String[] args) throws Exception {
    Authenticator.setDefault(new MyAuthenticator());
    readUrl(args);
    System.out.println("################################");
    System.out.println("Read again...");
    readUrl(args);
  }
 
  private static void readUrl(String[] args) throws MalformedURLException,
      IOException {
    URL url = new URL(args[0]);
    InputStream ins = url.openConnection().getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
    String str;
    while ((str = reader.readLine()) != null)
      System.out.println(str);
  }
}

Kerberos config: krb5.conf

* Mnimal:

[libdefaults]
    default_realm = MYTEST.LOCAL
[realms]
    MYTEST.LOCAL = {
        kdc = DC01.MYTEST.local
    }

* Win 2003 (this one is actually used):

[libdefaults]
    default_realm = MYTEST.LOCAL
	default_tkt_enctypes = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
	default_tgs_enctypes = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
	permitted_enctypes   = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
 
[realms]
	MYTEST.LOCAL  = {
		kdc = DC01.MYTEST.local 
		default_domain = MYTEST.local 
}
 
[domain_realm]
	.MYTEST.LOCAL = MYTEST.local

* For Windows 2008, DES encryption types are turned off by default.

[libdefaults]
    default_realm = MYTEST.LOCAL
    default_tkt_enctypes = rc4-hmac 
    default_tgt_enctypes = rc4-hmac 
    permitted_enctypes = rc4-hmac
 
[realms]
	MYTEST.LOCAL  = {
		kdc = mytest.local 
		default_domain = mytest 
}
 
[domain_realm]
	.mytest = MYTEST.LOCAL

JAAS Config: login.conf

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

* Turn on debugging:

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

Compile and run:

set JAVA_HOME=C:\Program Files\Java\jdk1.6.0_33
SET PATH=%JAVA_HOME%\bin;%path%
 
java -Djava.security.krb5.conf=krb5.conf -Djava.security.auth.login.config=login.conf -Djavax.security.auth.useSubjectCredsOnly=false test.http.auth.one.RunHttpSpnego http://dc01-a/testauth/test.htm
 
# Turn on debugging with -Dsun.security.krb5.debug=true
java -Djava.security.krb5.conf=krb5.conf -Djava.security.auth.login.config=login.conf -Djavax.security.auth.useSubjectCredsOnly=false -Dsun.security.krb5.debug=true test.http.auth.one.RunHttpSpnego http://dc01-a/testauth/test.htm

Caveats

* In krb5.conf, the realm name has to be all upper cases.
– This works:

[libdefaults]
    default_realm = MYTEST.LOCAL
[realms]
    MYTEST.LOCAL = {
 ...

– This does not works

[libdefaults]
    default_realm = mytest.local
[realms]
    mytest.local = {

Windows 2008 Domain Controller

* On the client machine, user cannot be a domain administrator. Otherwise, LSA ticket cannot be accessed. Windows 2003 does not have this restriction.
* Encryption types need to be

    default_tkt_enctypes = rc4-hmac 
    default_tgt_enctypes = rc4-hmac 
    permitted_enctypes = rc4-hmac

Tools

Windows klist.exe

cd c:\Windows\system32
klist
c:\Windows\System32>klist
 
Current LogonId is 0:0x4d672
 
Cached Tickets: (5)
 
#0>     Client: Administrator @ MYTEST.LOCAL
        Server: krbtgt/MYTEST.LOCAL @ MYTEST.LOCAL
        KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
        Ticket Flags 0x60a00000 -> forwardable forwarded renewable pre_authent
        Start Time: 11/22/2012 20:39:15 (local)
        End Time:   11/23/2012 6:05:44 (local)
        Renew Time: 11/29/2012 0:35:44 (local)
        Session Key Type: RSADSI RC4-HMAC(NT)

MIT Kerberos for Windows

* Download MIT Kerberos for Windows from MIT Kerberos dist site, e.g. Installer kfw-3-2-2.exe, 6425k.
* Double click to install.

Sync Time with Windows Server

w32tm /resync

References

* Java SE 6: java.net.Authenticator
* Http Authentication
* Kerberos Programming on Windows
* Class Krb5LoginModule
* http://old.nabble.com/Error-calling-function-protocol-status:-1312-td25889010.html
* http://blog.facilelogin.com/2010/11/kerberos-debugging-tips.html

This entry was posted in kerberos and tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

This site uses Akismet to reduce spam. Learn how your comment data is processed.