Saturday, May 31, 2014

NoSuchMethodError SpnegoAuthenticationProcessingFilter AbstractAuthenticationToken

In a nutshell, the solution to this problem involved cloning the git project, building the sources and deploying the newly created artifact (jar) to my local maven repository; see below for me details.

As part of an attempt to kerberize an web application (see here for details), which uses Spring Security's LDAP, I added in the necessary dependencies shown here:
<dependency>
    <groupId>org.springframework.security.extensions</groupId>
    <artifactId>spring-security-kerberos-core</artifactId>
    <version>1.0.0.M1</version>
</dependency>
and which I found here:
https://spring.io/blog/2009/09/28/spring-security-kerberos-spnego-extension

Next I configured the Spring Security XML configuration file as follows (description can be found at the link above too)

<beans ... >

<sec:http entry-point-ref="spnegoEntryPoint">
    <sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
    <sec:custom-filter ref="spnegoAuthenticationProcessingFilter" position="BASIC_AUTH_FILTER" />
</sec:http>
    
    
<bean id="spnegoEntryPoint" class="org.springframework.security.extensions.kerberos.web.SpnegoEntryPoint" />

<bean id="spnegoAuthenticationProcessingFilter" class="org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref="kerberosServiceAuthenticationProvider" />
</sec:authentication-manager>

<bean id="kerberosServiceAuthenticationProvider" class="org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider">
    <property name="ticketValidator">
        <bean class="org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator">
            <property name="servicePrincipal" value="HTTP/tomcat@EXAMPLE.COM" />
            <property name="keyTabLocation" value="classpath:krb5.keytab" />
            <property name="debug" value="true"/>
        </bean>
    </property>
    <property name="userDetailsService" ref="dummyUserDetailsService" />
</bean>

<bean id="dummyUserDetailsService" class="org.wmmnpr.mykrb.config.Krb5DumyUserService"/>



</beans>

And started the Maven based project using the maven-tomcat-plugin as follows:
>mvn tomcat7:run

When I tried to access a protected URL, I got the following error:

org.apache.catalina.core.StandardWrapperValve invoke
Schwerwiegend: Servlet.service() for servlet [jsp] in context with path [/mykrb5webapp] threw exception [Filter execution threw an exception] with root cause
java.lang.NoSuchMethodError: org.springframework.security.authentication.AbstractAuthenticationToken.<init>(Ljava/util/List;)V
at org.springframework.security.extensions.kerberos.KerberosServiceRequestToken.<init>

Obviously, the SpnegoAuthenticationProcessingFilter was incompatible with the spring-security-core library. I had no option but to clone the spring-security-security repository and see if I could fix the problem.

Using the eclipse git plugin, I cloned the remote repository (https://github.com/spring-projects/spring-security-kerberos.git) and then ran the gradle buiild. To import the code into eclipse I added "apply plugin: 'eclipse'" to the sources build.gradle file and run the "eclipse" target. This generated the proper eclipse project files, which allowed me to import the project into eclipse (see below)



To build and deploy the library, I ran the gradle.gui by calling:

gradlew.bat --gui




This made it very easy to install the jar into my local maven repository. All I had to do was click on the install target shown above.

Next, I updated the eclipse project of my web application to reflect the new version and ran the project again in the debugger. 

The problem was that the source code was the changed but the executable code seemed to be different. When I tried to step through my changed code, the debugger didn't seem to know about the changes. 

I spent lots of time trying to clean and rebuild the gradle project, I even deleted the artifacts in my maven repository, but it didn't help either. 

Then started I started the jvisualvm using the same user, tomcat, under which the web application as running (see here)



I could not see which jar file the class was being loaded from. To do that, I needed to start the server using the -verbose:class JVM option, which I passed to maven by setting in the environment the MAVEN_OPTS variable.

This showed the source jar of the class very nicely.


[Loaded org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter from file:/C:/Users/wnpr/.m2/repository/org/springframework/security/extensions/spring-security-kerberos-core/1.0.0.CI-SNAPSHOT/spring-security-kerberos-core-1.0.0.CI-SNAPSHOT.jar]

Despite all my efforts, I was still getting the NoSuchMethodError. Eventually, I had the idea to look into the publish-maven.gradle file. There I found references to some external resources.

scm {
     url = 'https://github.com/SpringSource/spring-security-kerberos'
     connection = 'scm:git:git://github.com/SpringSource/spring-security-kerberos'
     developerConnection = 'scm:git:git://github.com/SpringSource/spring-security-kerberos'

}

which I changed to something meaningless:

scm {
     url = 'https://githubxxx.com/SpringSource/spring-security-kerberos'
    connection = 'scm:git:git://githubxxx.com/SpringSource/spring-security-kerberos'
     developerConnection = 'scm:git:git://githubxxx.com/SpringSource/spring-security-kerberos'



I ran the gradle clean, the maven install and started the web application. This time java code shown in the debugger agreed what was being executed and the NoSuchMethodError was gone. Obviously, the jars which I had picked up from the recommended setting (shown below) were wrong; however, now it didn't matter as I was building my own using gradle and deploying to my local maven repository.


<repositories>
    <repository>
        <id>spring-snapshots</id>
        <name>Spring Snapshots</name>
        <url>http://repo.spring.io/snapshot</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>

   <repository>
<id>spring-milestone</id>
<name>Spring Portfolio Milestone Repository</name>
<url>http://maven.springframework.org/milestone</url>
   </repository>
</repositories>


All that was left to do, was to comment out the above in my pom.xml file and change my dependency declaration of the kerberos artifact.

<dependency>
   <groupId>org.springframework.security.kerberos</groupId>
   <artifactId>spring-security-kerberos-core</artifactId>
   <version>1.0.0.CI-SNAPSHOT</version>
</dependency>



2 comments:

  1. Hi William, Do you have a copy of the library already patched (jar) for download?
    Thanks

    ReplyDelete
    Replies
    1. Hello Pedro,
      Unfortunately, I don’t have the patched library anymore. I would hope that the incompatibility has since then been fixed. If not, then you’ll have to build your own version as I did.
      Sorry and good luck,
      William

      Delete