Contents
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