202 lines
8.1 KiB
Plaintext
202 lines
8.1 KiB
Plaintext
//
|
|
// 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 $?
|