// // weijun.wang@sun.com HTTP SPNEGO =========== JPlan 116: SPNEGO HTTP authentication http://jplan.sfbay/feature/116) RFE 6260531: SPNEGO HTTP authentication http://monaco.sfbay/detail.jsf?cr=6260531) CCC 6244039: more HTTP authentication schemes to support in Java http://ccc.sfbay/6244039 What's HTTP SPNEGO ================== HTTP SPNEGO supports the Negotiate authentication scheme in an HTTP communication. There are 2 types of authentication here: 1. Web Authentication. The Web Server responses with HTTP/1.1 401 Unauthorized WWW-Authenticate: Negotiate the client will need to send a header like Authorization: Negotiate YY..... to authenticate itself to the server 2. Proxy Authentication. The Web Server responses with HTTP/1.1 407 Proxy Authentication Required Proxy-Authenticate: Negotiate the client will need to send a header like Proxy-Authorization: Negotiate YY..... to authenticate itself to the proxy server The new codes support both types of authentication. How to use the new feature ========================== There is no new public API function involved in the new feature, but several configurations are needed to perform a success communication: 1. Since the SPNEGO mechanism will call the Kerberos V5 login module to do real works. Kerberos configurations are needed. which includes: a) Some way to provide Kerberos realm and KDC address. This can be achieved with the Java system property java.security.krb5.realm and java.security.krb5.kdc. For example: java -Djava.security.krb5.realm=REALM_NAME \ -Djava.security.krb5.kdc=kdc.realm.name \ ClassName b) A JAAS config file denoting what login module to use. HTTP SPNEGO codes will look for the standard GSS_INITIATE_ENTRY entry named "com.sun.security.jgss.initiate". For example, you can provide a file spnegoLogin.conf: com.sun.security.jgss.initiate { com.sun.security.auth.module.Krb5LoginModule required useTicketCache=true; }; and run java with: java -Djava.security.krb5.realm=REALM_NAME \ -Djava.security.krb5.kdc=kdc.realm.name \ -Djava.security.auth.login.config=spnegoLogin.conf \ ClassName Another JAAS login entry "http.auth.negotiate.server" is defined to be used by the server side. 2. Just like other HTTP authentication scheme, the client can provide a customized java.net.Authenticator to feed username and password to the HTTP SPNEGO module when they are needed (e.g. there is no keytab cache available). The only authentication information needed to be checked in your Authenticator is the scheme which can be retrieved with getRequestingScheme(). The value should be "Negotiate". This means your Authenticator implementation will look like: class MyAuthenticator extends Authenticator { public PasswordAuthentication getPasswordAuthentication () { if (getRequestingScheme().equalsIgnoreCase("negotiate")) { String krb5user; char[] krb5pass; // get krb5user and krb5pass in your own way .... return (new PasswordAuthentication (krb6user, krb5pass.toCharArray())); } else { .... } } } 3. The client can still provide system property http.auth.preference to denote that a certain scheme should always be used as long as the server request for it. You can use "SPNEGO" or "Kerberos" for this system property. "SPNEGO" means you prefer to challenge the Negotiate scheme using the GSS/SPNEGO mechanism; "Kerberos" means you prefer to challenge the Negotiate scheme using the GSS/Kerberos mechanism. Normally, when authenticating against a Microsoft product, you can use "SPNEGO". The value "Kerberos" also works for Microsoft servers. It's only needed when you encounter a server which knows Negotiate but doesn't know about SPNEGO. If http.auth.preference is not set, the internal order choosen is: GSS/SPNEGO -> Digest -> BTLM -> Basic Noticed that Kerberos does not appear in this list, since whenever Negotiate is supported, GSS/SPNEGO is always chosen. 4. If the server has provided more than one authentication schemes (including Negotiate), according to the processing order mentioned in the last section, Java will try to challenge the Negotiate scheme. However, if the protocol cannot be established successfully (e.g. The kerberos configuration is not correct, or the server's hostname is not recorded in the KDC principal DB, or the username and password provided by Authenticator is wrong), then the 2nd strongest scheme will be automatically used. You can notice this behaviour in the test case: TEST_NAME="Authenticate fallback". Attention: If http.auth.preference is set to SPNEGO or Kerberos, then we assume you only want to try the Negotiate scheme even if it fails. we won't fallback to any other scheme and your program will result in throwing an IOException saying it receives a 401 or 407 error from the HTTP response. This behaviour can be observed in the test case: TEST_NAME="Authenticate no fallback" Test ==== The test is a bash script spnegoTest, which makes use of the Java class WebGet. WebGet.java is included. To run the test, you need these files: spnegoTest spnegoLogin.conf JAAS login config file spnegoLog.properties logging config file The test environment includes 1 or 2 KDC server, 1 or 2 Web server, and 1 proxy server. The web server and the proxy server need to support multiple authentication schemes setting to test the fallback feature. The environment variables set inside spnegoTest are: WWW_REALM The Kerberos realm the Web server belongs to WWW_KDC The Kerberos KDC for the WWW_REALM WWW_URL The URL to test against. It should be protected with Negotiate and Basic authentication PROXY_REALM The Kerberos realm the proxy server belongs to PROXY_KDC The Kerberos KDC for the PROXY_REALM PROXY_URL The URL to test against, Should be available to anonymous request PROXY_PARA The proxy server setting. The proxy server should prompt for Negotiate and Basic authentication GOOD_PASS Correct user/pass for Basic authentication GOOD_KPASS Correct user/pass for Kerberos BAD_PASS Wrong user/pass for Basic authentication BAD_KPASS Wrong user/pass for Kerberos WWW_TAB The keytab file for WWW_REALM PROXY_TAB The keytab file for PROXY_REALM TAB_PATH The standard keytab cache file path FILE_CONTENT The content of URL expected The values set in spnegoTest reflect a temporary testing environment, where we use MS-Windows 2000 Advanced Server as the KDC server and Web server, and MS ISA 2000 Server as the proxy server. In order to test the using of keytab cache, you need to get the keytab files before starting the test. The pathname of the 2 keytab files (one for the WWW_REALM, the other for the PROXY_REALM) should be set inside the test script spnegoTest as WWW_TAB and PROXY_TAB respectively. During the test process, they will be copied to the system recognized place (TAB_PATH) in turn. This is a manual step since on most systems the kerberos realm is setup in krb5.conf, and you need a root privilege to edit the it to get the 2 ticket cache files. Normally, the process will look like: # edit the krb5.conf using $WWW_REALM kinit www_user_name cp $TAB_PATH $WWW_TAB # edit the krb5.conf using $PROXY_REALM kinit proxy_user_name cp $TAB_PATH $PROXY_TAB Fortunately, you normally will only need to do this once in a day. However, on MS-Windows platform, the kinit tool provided with the JRE has command options including realm, KDC, principal name, and password, thus make it possible to generate the keytab files from a batch script. Finally, you can run the test with $ bash spnegoTest || echo $?