Created attachment 32059 [details] Tomcat JAAS configuration Hello everyone, I'm successfully using Tomcat 7.0.55 configured with Spnego authentication against Active Directory running Windows 2008 Server and Java 1.7.0.51. After switching to Java 1.8.0_20, authentication does not work anymore, Tomcat logs the following error message: SEVERE: Exception performing authentication javax.naming.AuthenticationException: GSSAPI [Root exception is javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided ( Mechanism level: Failed to find any Kerberos tgt)]]; remaining name 'CN=Users,DC=example,DC=com' at com.sun.jndi.ldap.sasl.LdapSasl.saslBind(LdapSasl.java:169) at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:236) at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2788) at com.sun.jndi.ldap.LdapCtx.ensureOpen(LdapCtx.java:2696) at com.sun.jndi.ldap.LdapCtx.ensureOpen(LdapCtx.java:2670) at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1941) at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1844) at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1769) at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:392) at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:358) at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:341) at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:267) at org.apache.catalina.realm.JNDIRealm.getUserBySearch(JNDIRealm.java:1446) at org.apache.catalina.realm.JNDIRealm.getUser(JNDIRealm.java:1297) at org.apache.catalina.realm.JNDIRealm.getUser(JNDIRealm.java:1233) at org.apache.catalina.realm.JNDIRealm.getPrincipal(JNDIRealm.java:2049) at org.apache.catalina.realm.JNDIRealm.getPrincipal(JNDIRealm.java:1965) at org.apache.catalina.realm.RealmBase.authenticate(RealmBase.java:513) at org.apache.catalina.realm.CombinedRealm.authenticate(CombinedRealm.java:309) at org.apache.catalina.realm.LockOutRealm.authenticate(LockOutRealm.java:249) at org.apache.catalina.authenticator.SpnegoAuthenticator.authenticate(SpnegoAuthenticator.java:255) Tomcat is configured according to the "Windows Authentication How-To" document, I'm attaching the krb5.ini, jaas.conf and server.xml that contains the JNDIRealm definition. I have investigated the problem and I believe it is related to the Kerberos constraint delegation support added in Java 8, see: http://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/jgss-features.html http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6355584 It seems that per default, GSS API in Java 8 will attempt constraint delegation on the acceptor side, see referenced changes and in particular the getCredDelegState() method: http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/a1bbb8805e22 The result of this, is that Tomcat's JNDIRealm now finds the delegated credential delivered with the constraint delegation and switches GSSAPI security mechanism for JNDI/LDAP (this was not the case on Java 7). However, the Kerberos initiation during LDAP authentication does not find the Kerberos TGT in the Subject. After digging further, I noticed that the Subject used during the LDAP authentication is not set. Though the SpnegoAuthenticator initializes a Subject instance using Kerberos login via JAAS and this contains the obtained TGT, this Subject instance is not used for performing the LDAP authentication. I saw the following comment in JNDIRealm.getPrincipal: // Note: Subject already set in SPNEGO authenticator so no need for Subject.doAs() here So I decided to modify this and execute the getPrincipal using Subject.doAs() and the Subject instance available after the Kerberos login. This lead to successful authentication to LDAP and I was able to access the Spnego-secured webapp again. Please note that this setup is not using any file-system Kerberos credential cache, so it requires that the Kerberos TGT is available in the Subject instance associated with current ACC.
Created attachment 32060 [details] Tomcat Kerberos configuration
Created attachment 32061 [details] Tomcat configuration
Created attachment 32062 [details] Error log
I managed to overcome this error by setting -Djavax.security.auth.useSubjectCredsOnly=false Still, I would like to know if there is a reason not to use Subject.doAs when doing GSSAPI authentication against LDAP.
A short update. I can reproduce this with Tomcat 8 and both the latest Java 7 and Java 8 releases. I have a patch that fixes this but it currently depends on an internal Sun API. I am looking at ways to work around that.
I've done a little svn archeology. Originally, the SPNEGO authenticate did call Realm.authenticate using Subject.doAs(). That was removed as it wasn't necessary early in the SPNEGO development. I have just restored this behaviour. At one point Tomcat automatically set javax.security.auth.useSubjectCredsOnly=false but this was removed to enable SPNEGO to work with IBM JREs. This fix has been made to 8.0.x and will be included in 8.0.15 onwards. It still needs to be back-ported to 7.0.x
Thanks Mark, The patch I tested with that proved to work was similar, I have not done any tests with IBM JDK though. Should the following note in "Windows Auth How-to" be removed then: "The system property javax.security.auth.useSubjectCredsOnly is automatically set to the required value of false if a web application is configured to use the SPNEGO authentication method." Detelin
This has now been fixed in 7.0.x for 7.0.57 onwards.
I'll update the 7.0.x docs to remove that comment.