1// 2// weijun.wang@sun.com 3 4HTTP SPNEGO 5=========== 6 7JPlan 116: SPNEGO HTTP authentication 8 http://jplan.sfbay/feature/116) 9RFE 6260531: SPNEGO HTTP authentication 10 http://monaco.sfbay/detail.jsf?cr=6260531) 11CCC 6244039: more HTTP authentication schemes to support in Java 12 http://ccc.sfbay/6244039 13 14 15What's HTTP SPNEGO 16================== 17 18HTTP SPNEGO supports the Negotiate authentication scheme in an HTTP 19communication. There are 2 types of authentication here: 20 211. Web Authentication. The Web Server responses with 22 HTTP/1.1 401 Unauthorized 23 WWW-Authenticate: Negotiate 24 the client will need to send a header like 25 Authorization: Negotiate YY..... 26 to authenticate itself to the server 272. Proxy Authentication. The Web Server responses with 28 HTTP/1.1 407 Proxy Authentication Required 29 Proxy-Authenticate: Negotiate 30 the client will need to send a header like 31 Proxy-Authorization: Negotiate YY..... 32 to authenticate itself to the proxy server 33 34The new codes support both types of authentication. 35 36 37How to use the new feature 38========================== 39 40There is no new public API function involved in the new feature, but 41several configurations are needed to perform a success communication: 42 431. Since the SPNEGO mechanism will call the Kerberos V5 login module to 44 do real works. Kerberos configurations are needed. which includes: 45 46 a) Some way to provide Kerberos realm and KDC address. This can be 47 achieved with the Java system property java.security.krb5.realm 48 and java.security.krb5.kdc. For example: 49 java -Djava.security.krb5.realm=REALM_NAME \ 50 -Djava.security.krb5.kdc=kdc.realm.name \ 51 ClassName 52 53 b) A JAAS config file denoting what login module to use. HTTP SPNEGO 54 codes will look for the standard GSS_INITIATE_ENTRY entry named 55 "com.sun.security.jgss.initiate". 56 57 For example, you can provide a file spnegoLogin.conf: 58 com.sun.security.jgss.initiate { 59 com.sun.security.auth.module.Krb5LoginModule 60 required useTicketCache=true; 61 }; 62 and run java with: 63 java -Djava.security.krb5.realm=REALM_NAME \ 64 -Djava.security.krb5.kdc=kdc.realm.name \ 65 -Djava.security.auth.login.config=spnegoLogin.conf \ 66 ClassName 67 68 69 Another JAAS login entry "http.auth.negotiate.server" is defined 70 to be used by the server side. 71 722. Just like other HTTP authentication scheme, the client can provide 73 a customized java.net.Authenticator to feed username and password to 74 the HTTP SPNEGO module when they are needed (e.g. there is no keytab 75 cache available). The only authentication information needed to be 76 checked in your Authenticator is the scheme which can be retrieved 77 with getRequestingScheme(). The value should be "Negotiate". 78 79 This means your Authenticator implementation will look like: 80 81 class MyAuthenticator extends Authenticator { 82 83 public PasswordAuthentication getPasswordAuthentication () { 84 if (getRequestingScheme().equalsIgnoreCase("negotiate")) { 85 String krb5user; 86 char[] krb5pass; 87 // get krb5user and krb5pass in your own way 88 .... 89 return (new PasswordAuthentication (krb6user, 90 krb5pass.toCharArray())); 91 } else { 92 .... 93 } 94 } 95 } 96 973. The client can still provide system property http.auth.preference to 98 denote that a certain scheme should always be used as long as the 99 server request for it. You can use "SPNEGO" or "Kerberos" for this 100 system property. "SPNEGO" means you prefer to challenge the Negotiate 101 scheme using the GSS/SPNEGO mechanism; "Kerberos" means you prefer 102 to challenge the Negotiate scheme using the GSS/Kerberos mechanism. 103 Normally, when authenticating against a Microsoft product, you can 104 use "SPNEGO". The value "Kerberos" also works for Microsoft servers. 105 It's only needed when you encounter a server which knows Negotiate 106 but doesn't know about SPNEGO. 107 108 If http.auth.preference is not set, the internal order choosen is: 109 GSS/SPNEGO -> Digest -> BTLM -> Basic 110 111 Noticed that Kerberos does not appear in this list, since whenever 112 Negotiate is supported, GSS/SPNEGO is always chosen. 113 1144. If the server has provided more than one authentication schemes 115 (including Negotiate), according to the processing order mentioned 116 in the last section, Java will try to challenge the Negotiate scheme. 117 However, if the protocol cannot be established successfully (e.g. 118 The kerberos configuration is not correct, or the server's hostname 119 is not recorded in the KDC principal DB, or the username and password 120 provided by Authenticator is wrong), then the 2nd strongest scheme 121 will be automatically used. You can notice this behaviour in the test 122 case: TEST_NAME="Authenticate fallback". 123 124 Attention: If http.auth.preference is set to SPNEGO or Kerberos, then 125 we assume you only want to try the Negotiate scheme even if it fails. 126 we won't fallback to any other scheme and your program will result in 127 throwing an IOException saying it receives a 401 or 407 error from 128 the HTTP response. This behaviour can be observed in the test case: 129 TEST_NAME="Authenticate no fallback" 130 131 132Test 133==== 134 135The test is a bash script spnegoTest, which makes use of the Java class 136WebGet. WebGet.java is included. To run the test, you need these files: 137 138 spnegoTest 139 spnegoLogin.conf JAAS login config file 140 spnegoLog.properties logging config file 141 142The test environment includes 1 or 2 KDC server, 1 or 2 Web server, and 1431 proxy server. The web server and the proxy server need to support 144multiple authentication schemes setting to test the fallback feature. 145 146The environment variables set inside spnegoTest are: 147 148 WWW_REALM The Kerberos realm the Web server belongs to 149 WWW_KDC The Kerberos KDC for the WWW_REALM 150 WWW_URL The URL to test against. It should be protected with 151 Negotiate and Basic authentication 152 153 PROXY_REALM The Kerberos realm the proxy server belongs to 154 PROXY_KDC The Kerberos KDC for the PROXY_REALM 155 PROXY_URL The URL to test against, Should be available to 156 anonymous request 157 PROXY_PARA The proxy server setting. The proxy server should 158 prompt for Negotiate and Basic authentication 159 160 GOOD_PASS Correct user/pass for Basic authentication 161 GOOD_KPASS Correct user/pass for Kerberos 162 BAD_PASS Wrong user/pass for Basic authentication 163 BAD_KPASS Wrong user/pass for Kerberos 164 165 WWW_TAB The keytab file for WWW_REALM 166 PROXY_TAB The keytab file for PROXY_REALM 167 TAB_PATH The standard keytab cache file path 168 169 FILE_CONTENT The content of URL expected 170 171The values set in spnegoTest reflect a temporary testing environment, 172where we use MS-Windows 2000 Advanced Server as the KDC server and Web 173server, and MS ISA 2000 Server as the proxy server. 174 175In order to test the using of keytab cache, you need to get the keytab 176files before starting the test. The pathname of the 2 keytab files (one 177for the WWW_REALM, the other for the PROXY_REALM) should be set inside 178the test script spnegoTest as WWW_TAB and PROXY_TAB respectively. During 179the test process, they will be copied to the system recognized place 180(TAB_PATH) in turn. 181 182This is a manual step since on most systems the kerberos realm is setup 183in krb5.conf, and you need a root privilege to edit the it to get the 2 184ticket cache files. Normally, the process will look like: 185 186 # edit the krb5.conf using $WWW_REALM 187 kinit www_user_name 188 cp $TAB_PATH $WWW_TAB 189 # edit the krb5.conf using $PROXY_REALM 190 kinit proxy_user_name 191 cp $TAB_PATH $PROXY_TAB 192 193Fortunately, you normally will only need to do this once in a day. 194 195However, on MS-Windows platform, the kinit tool provided with the JRE 196has command options including realm, KDC, principal name, and password, 197thus make it possible to generate the keytab files from a batch script. 198 199Finally, you can run the test with 200 201 $ bash spnegoTest || echo $? 202