I setup a Tomcat server running on a Linux box with SPNEGO, so that the users can Single-Sign-On the server without typing their password. You can follow the instructions on http://spnego.sourceforge.net/spnego_tomcat.html. Although this tutorial uses Windows for example, but the steps are same as the ones on Linux.
The big problem I faced was my company's network settings:
Here is a question: where should you create the pre-auth account: in lab or corp?
I tried to create a service account in lab's AD, and registered SPNs in lab. It didn't work. When I accessed hello_spnego.jsp page on a Windows machine in corp, I always got the dialog asking for username and password. This is because I enabled downgrade to basic authentication for NTLM. If I disabled basic authentication, I would get 500 error.
I used wireshark to catch the packets and found out the traffic as bellow:
Then I tried to use keytab method because I don't like to put username/password in plaintext in web.xml. There are still a log of pitfalls in this step. Here are the working version of my login.conf
The big problem I faced was my company's network settings:
- There are two networks: corp.mycompany.com and lab.mycompany.com.
- lab trusts corp, but corp doesn't trust lab
Here is a question: where should you create the pre-auth account: in lab or corp?
I tried to create a service account in lab's AD, and registered SPNs in lab. It didn't work. When I accessed hello_spnego.jsp page on a Windows machine in corp, I always got the dialog asking for username and password. This is because I enabled downgrade to basic authentication for NTLM. If I disabled basic authentication, I would get 500 error.
I used wireshark to catch the packets and found out the traffic as bellow:
- Browser sends GET /hello_spnego.jsp
- Server returns 401 Unauthorized with Negotiate
- Client sends KRB5 TGS-REQ
- Client receives KRB5 KRB Error: KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
- Browser sends GET /hello_spnego.jsp HTTP/1.1, NTLMSSP_NEGOTIATE
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1\r\n
WWW-Authenticate: Negotiate\r\n
WWW-Authenticate: Basic realm="LAB.MYCOMPANY.COM"\r\n
Kerberos KRB-ERROR
Pvno: 5
MSG Type: KRB-ERROR(30)
stime: 2012-10-10 23:04:48 (UTC)
susec: 394362
error_code: KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
Realm: CORP.MYCOMPANY.COM
Server Name (Service and Instance): HTTP/tomcat.lab.mycompany.com
Then I tried to use keytab method because I don't like to put username/password in plaintext in web.xml. There are still a log of pitfalls in this step. Here are the working version of my login.conf
spnego-client {and krb5.conf.
com.sun.security.auth.module.Krb5LoginModule required;
};
spnego-server {
com.sun.security.auth.module.Krb5LoginModule
required
useKeyTab=true
keyTab="conf/appserver.keytab"
principal="serviceaccount@CORP.MYCOMPANY.COM"
storeKey=true
isInitiator=false;
};
[libdefaults]You may encounter different issues if something is wrong. Here is my experience:
default_realm = LAB.MYCOMPANY.COM
default_tgs_enctypes = arcfour-hmac-md5 des-cbc-crc des-cbc-md5 des3-hmac-sha1
default_tkt_enctypes = arcfour-hmac-md5 des-cbc-crc des-cbc-md5 des3-hmac-sha1
clockskew = 300
[realms]
LAB.MYCOMPANY.COM = {
kdc = kdc1.lab.mycompany.com
kdc = kdc2.lab.mycompany.com
default_domain = lab.mycompany.com
}
[default_realm]
lab.mycompany.com = LAB.MYCOMPANY.COM
.lab.mycompany.com = LAB.MYCOMPANY.COM
- If I don't quote the principal like this principal=serviceaccount@CORP.MYCOMPANY.COM, I will get the configuration error. And the message is misleading because line 9 is keyTab.
- When you use ktab, the first thing you need to know is only windows version has this tool, while Linux RPM from oracle doesn't have it.
- You should use the service account in corp network, not lab, to generate the keytable file like this:
- Make sure your
- I also encountered this error: KrbException: Specified version of key is not available (44). It turns out that the keytab file I generated with kvno=1 and the expected is 2. You can use wireshark to catch the packet for KRB5 TGT-REP, and it will tell you what kvno is expected.
- You have to run ktab command multiple times to achieve the correct kvno just like this page http://dmdaa.wordpress.com/2010/05/08/how-to-get-needed-kvno-for-keytab-file-created-by-java-ktab-utility/. Use can just use ktab -l to find the kvno:
- Which version of JDK seems not important. A keytab file generated by JDK 7 worked in JDK 1.6.0_32.
- I also got this Checksum error if I used my lab service account (serviceaccount@lab.mycompany.com) in pre-auth fields or keytab.
Caused by: java.io.IOException: Configuration Error:
Line 9: expected [option key], found [null]
ktab -a serviceaccount@CORP.MYCOMPANY.COM -k appserver.keytab
Ticket
Tkt-vno: 5
Realm: LAB.MYCOMPANY.COM
Server Name ....
enc-part rc5-hmac
Encryption type: ...
Kvno: 2 *** Here it is
enc-part: ...
ktab -l -k appserver.keytab
SEVERE: Servlet.service() for servlet [jsp] in context with path [] threw exception [GSSException: Failure unspecified at GSS-API level (Mechanism level: Checksum failed)] with root cause
java.security.GeneralSecurityException: Checksum failed
at sun.security.krb5.internal.crypto.dk.ArcFourCrypto.decrypt(ArcFourCrypto.java:388)
at sun.security.krb5.internal.crypto.ArcFourHmac.decrypt(ArcFourHmac.java:74)