Spring Security: How to customize remember-me request parameter name? - spring-security

I'm using password-parameter (as below) to customize the name of the request parameter which contains the password. How to do the same with remember-me (default _spring_security_remember_me) ?
<security:form-login password-parameter="j_password_input" ... />

You have a few options which I have explained in further detail below
Use the Security Namespace with a BeanPostProcessor
Use the services-ref and configure RememberMeServices Manually
Use the Security Namespace with a BeanPostProcessor
The namespace does not have support for configuring the remember me parameter, but you can use a tip from the FAQ on how to still use the namespace support, but customise the result. The trick is to use a BeanPostProcessor to set the parameter field on AbstractRememberMeServices. You can find an example of this below:
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String name) {
if (bean instanceof AbstractRememberMeServices) {
AbstractRememberMeServices rememberMe = (AbstractRememberMeServices) bean;
rememberMe.setParameter("myParamname");
}
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String name) {
return bean;
}
}
Then you would need to use the namespace as you normally would and add MyBeanPostProcessor to your Spring configuration as shown below:
<security:http ..>
...
<security:remember-me/>
</security:http>
<bean class="sample.MyBeanPostProcessor"/>
Use the services-ref and configure RememberMeServices Manually
You can also use the services-ref attribute too, but this involves a little more configuration. For example, if you wanted you could use the following configuration:
<security:http ..>
...
<security:remember-me services-ref="rememberMeServices"/>
</security:http>
<bean id="rememberMeServices"
class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="key" value="mustMatchRememberMeAuthenticationProvidersKey"/>
<property name="parameter" value="myParamName"/>
<!-- You must refer to a bean that implements UserDetailsService
in this example the bean id is userDetailsService -->
<property name="userDetailsService" ref="userDetailsService"/>
</bean>

As of Spring Security 3.2.x, you can set this with the remember-me-parameter parameter on the remember-me element.

Related

How to use/configure JAX-RS 2.0, SpringSecurity 3.1.+, EJB 3.2 all together

I am currently trying to setup a project with these main technologies:
Java EE 7
EJB 3.2
JAX-RS (Jersey) 2.0
Glassfish 4
Spring Security 3.1.5
I saw that it is possible to write something like that
#Stateless
#Path("apath")
public class WebResource {
#EJB
private SomeService serviceInjected;
#GET
public Response doSomething() {
return Response.ok(injectedService.doSomethingElse()).build();
}
}
Then, this means that the SomeService Session Bean is injected by the container and once we call the path: :///apath, everything is working fine.
Now, what I try to achieve is to integrate the SpringSecurity framework in that code. So my code become this:
#Component
#Stateless
#Path("apath")
public class WebResource {
#EJB
private SomeService serviceInjected;
#GET
#PreAuthorized("hasPermission('ROLE_SOMETHING')")
public Response doSomething() {
return Response.ok(injectedService.doSomethingElse()).build();
}
}
But, this does not work. Everything excepted the SpringSecurity annotations continue to work. The authorization annotations are just not taken into account.
In SpringSecurity configuration file, I have something like that:
<security:global-method-security
access-decision-manager-ref="preVoteAccessDecisionManager"
pre-post-annotations="enabled" />
with everything related to the filter chain and so correctly configured. For example, I have that:
<beans:bean id="securityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<beans:property name="securityMetadataSource">
<security:filter-security-metadata-source>
<security:intercept-url pattern="/**" access="ROLE_TEST" />
</security:filter-security-metadata-source>
</beans:property>
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="accessDecisionManager" ref="accessDecisionManager" />
</beans:bean>
And I see in my Glassfish 4 server logs that SpringSecurity managed the ROLE_TEST access for my authenticated user. I also see that my user authenticated has the list of roles that I expect.
I also tried to use this configuration and rely on javax.annotation.security annotations as below:
<security:global-method-security
access-decision-manager-ref="preVoteAccessDecisionManager"
jsr250-annotations="enabled" />
#Stateless
#Path("apath")
public class WebResource {
#EJB
private SomeService serviceInjected;
#GET
#RolesAllowed("ROLE_SOMETHING")
public Response doSomething() {
return Response.ok(injectedService.doSomethingElse()).build();
}
}
This time, the annotation is working and an exception is thrown when the user is authenticated. But in this case, my user has the roles but the SecurityContext used by the container is not filled with the Principal and roles information related to the user authenticated by SpringSecurity.
Finally, my question(s). Is there a way to integrate the JAX-RS / #Stateless / SpringSecurity Authorization together? If not, is there a way to fill a SecurityContext from SrpingSecurity to allow javax.annotation.security to work like a charm?
Thanks in advance for any helps, tips, tricks or anything else that can solve my problems :D
Spring Security's method security annotations will normally only work with Spring beans whose lifecycle is controlled by Spring. This doesn't include EJBs. However, if you wish you can use the AspectJ integration which will work for any object including EJB instances. There's a sample application in the Spring Security codebase which you can use as a reference. It might also be worth considering whether you need to use EJBs at all.

Spring Security #Preauthorize Tag Not Working In Unit Test

(First, I apologize, I can't get more than a single level of indention for my code)
I am attempting to write a unit test to test my service-layer methods. The interface for these service classes are annotated with #Preauthorize:
public interface LocationService {
void setLocationRepository(LocationRepository locationRepository);
/**
* Get all Location objects from the backend repository
* #return
*/
#PreAuthorize("has_role('ROLE_ADMIN')")
List<Location> getAll();
The unit test looks something like this:
#Before
public void setUp() {
admin = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("admin", "admin"));
user = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "user"));
// create Mock Repository
// set up the actual service WITH the repository
locationService = new LocationServiceImpl();
locationService.setLocationRepository(locationRepository);
}
#Test(expected = AccessDeniedException.class)
#SuppressWarnings("unused")
public void testGetAllAsUser() {
SecurityContextHolder.getContext().setAuthentication(user);
List<Location> resultList = locationService.getAll();
}
Finally, here is the security context from my applicationContext.xml:
<!-- Temporary security config. This will get moved to a separate context
file, but I need it for unit testing right now -->
<security:http use-expressions="true">
<security:form-login />
<security:session-management
invalid-session-url="/timeout.jsp">
<security:concurrency-control
max-sessions="1" error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider>
<security:password-encoder hash="plaintext" />
<security:user-service>
<security:user name="admin" password="admin"
authorities="ROLE_ADMIN" />
<security:user name="user" password="user"
authorities="ROLE_USER" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<security:global-method-security
pre-post-annotations="enabled" proxy-target-class="true" />
Unfortunately, the #PreAuthorize tag is being ignored, allowing someone with ROLE_USER to run getAll().
Can anyone help?
Jason
Are you running the unit test with the spring junit runner?
Are you pointing to the correct spring configuration file for that unit test?
Have you configured load time weaving for the security aspects?
The line:
locationService = new LocationServiceImpl();
Creates a new location service, bypassing spring altogether. If you are using the spring junit runner then you should use #Resource to get the locationService injected so that you are using the spring bean and not just your pojo.

How to dynamically decide <intercept-url> access attribute value in Spring Security?

In Spring Security we use the intercept-url tag to define the access for URLs as below:
<intercept-url pattern="/**" access="ROLE_ADMIN" />
<intercept-url pattern="/student" access="ROLE_STUDENT" />
This is hard coded in applicationContext-security.xml. I want to read the access values from a database table instead. I have defined my own UserDetailsService and I read the roles for the logged in user from the database. How do I assign these roles to the URL patterns during runtime?
The FilterInvocationSecurityMetadataSourceParser class in Spring-security (try Ctrl/Cmd+Shift+T in STS with the source code) parses the intercept-url tags and creates instances of ExpressionBasedFilterInvocationSecurityMetadataSource, that extends DefaultFilterInvocationSecurityMetadataSource that implements FilterInvocationSecurityMetadataSource that extends SecurityMetadataSource.
What I did is to create a custom class that implements FilterInvocationSecurityMetadataSource, OptionsFromDataBaseFilterInvocationSecurityMetadataSource. I used DefaultFilterInvocationSecurityMetadataSource as base to use urlMatcher, to implement the support() method and something like that.
Then you must to implement these methods:
Collection getAttributes(Object object), where you can access to database, searching for the 'object' being secured (normally the URL to access) to obtain the allowed ConfigAttribute's (normally the ROLE's)
boolean supports(Class clazz)
Collection getAllConfigAttributes()
Be careful with the later, because it's called at startup and maybe is not well configured at this time (I mean, with the datasources or persistence context autowired, depending on what are you using). The solution in a web environment is to configure the contextConfigLocation in the web.xml to load the applicationContext.xml before the applicationContext-security.xml
The final step is to customize the applicationContext-security.xml to load this bean.
For doing that, I used regular beans in this file instead of the security namespace:
<beans:bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<filter-chain-map path-type="ant">
<filter-chain pattern="/images/*" filters="none" />
<filter-chain pattern="/resources/**" filters="none" />
<filter-chain pattern="/**" filters="
securityContextPersistenceFilter,
logoutFilter,
basicAuthenticationFilter,
exceptionTranslationFilter,
filterSecurityInterceptor"
/>
</filter-chain-map>
</beans:bean>
You have to define all the related beans. For instance:
<beans:bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="authenticationManager"></beans:property>
<beans:property name="accessDecisionManager" ref="affirmativeBased"></beans:property>
<beans:property name="securityMetadataSource" ref="optionsFromDataBaseFilterInvocationSecurityMetadataSource"></beans:property>
<beans:property name="validateConfigAttributes" value="true"/></beans:bean>
I know that is not a well explained answer, but it's not as difficult as it seems.
Just use the spring source as base and you will obtain what you want.
Debugging with the data in your database, will help you a lot.
Actually, spring security 3.2 do not encourage to do this according to http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/faq.html#faq-dynamic-url-metadata
but, it is possible (but not elegant) using http element in namespace with a custom accessDecisionManager..
The config should be:
<http pattern="/login.action" security="none"/>
<http pattern="/media/**" security="none"/>
<http access-decision-manager-ref="accessDecisionManager" >
<intercept-url pattern="/**" access="ROLE_USER"/>
<form-login login-page="/login.action"
authentication-failure-url="/login?error=1"
default-target-url="/console.action"/>
<logout invalidate-session="true" delete-cookies="JSESIONID"/>
<session-management session-fixation-protection="migrateSession">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" expired-url="/login.action"/>
</session-management>
<!-- NO ESTA FUNCIONANDO, los tokens no se ponen en el request!
<csrf />
-->
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="test" password="test" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
<beans:bean id="accessDecisionManager" class="openjsoft.core.services.security.auth.CustomAccessDecisionManager">
<beans:property name="allowIfAllAbstainDecisions" value="false"/>
<beans:property name="decisionVoters">
<beans:list>
<beans:bean class="org.springframework.security.access.vote.RoleVoter"/>
</beans:list>
</beans:property>
</beans:bean>
The CustomAccessDecisionManager should be...
public class CustomAccessDecisionManager extends AbstractAccessDecisionManager {
...
public void decide(Authentication authentication, Object filter,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
if ((filter == null) || !this.supports(filter.getClass())) {
throw new IllegalArgumentException("Object must be a FilterInvocation");
}
String url = ((FilterInvocation) filter).getRequestUrl();
String contexto = ((FilterInvocation) filter).getRequest().getContextPath();
Collection<ConfigAttribute> roles = service.getConfigAttributesFromSecuredUris(contexto, url);
int deny = 0;
for (AccessDecisionVoter voter : getDecisionVoters()) {
int result = voter.vote(authentication, filter, roles);
if (logger.isDebugEnabled()) {
logger.debug("Voter: " + voter + ", returned: " + result);
}
switch (result) {
case AccessDecisionVoter.ACCESS_GRANTED:
return;
case AccessDecisionVoter.ACCESS_DENIED:
deny++;
break;
default:
break;
}
}
if (deny > 0) {
throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
"Access is denied"));
}
// To get this far, every AccessDecisionVoter abstained
checkAllowIfAllAbstainDecisions();
}
...
}
Where getConfigAttributesFromSecuredUris retrieve form DB de roles for the specific URL
I have kind of the same problem, basically I'd like to keep separate the list of intercept-url from the other springsecurity configuration section, the first to belong to the application configuration the latter to the product (core, plugin) configuration.
There is a proposal in the JIRA of spring, concerning this problem.
I don't want to give up to use the springsecurity namespace, so I was thinking to some possible solutions in order to deal with this.
In order to have the list of intercept-url dynamically created you have to inject the securitymetadatasource object in the FilterSecurityInterceptor.
Using springsecurity schema the instance of FilterSecurityInterceptor is created by the HttpBuilder class and there is no way to pass the securitymetadatasource as property defined in the schema configuration file, as less as using kind of workaround, which could be:
Define a custom filter, to be executed before FilterSecurityInterceptor, in this filter retrieving the instance FilterSecurityInterceptor (assuming a unique http section is defined) by the spring context and inject there the securitymetadatasource instance;
The same as above but in a HandlerInterceptor.
What do you think?
This the solution I've applied in order to split the list of intercept-url entries from the other spring security configuration.
<security:custom-filter ref="parancoeFilterSecurityInterceptor"
before="FILTER_SECURITY_INTERCEPTOR" />
........
<bean id="parancoeFilterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor" >
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource" ref="securityMetadataSource"/>
</bean>
The bean securityMetadataSource can be put either in the same configuration file or in another configuration file.
<security:filter-security-metadata-source
id="securityMetadataSource" use-expressions="true">
<security:intercept-url pattern="/admin/**"
access="hasRole('ROLE_ADMIN')" />
</security:filter-security-metadata-source>
Of course you can decide to implement your own securityMetadataSource bean by implementing the interface FilterInvocationSecurityMetadataSource.
Something like this:
<bean id="securityMetadataSource" class="mypackage.MyImplementationOfFilterInvocationSecurityMetadataSource" />
Hope this helps.
This is how it can be done in Spring Security 3.2:
#Configuration
#EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public SecurityConfigDao securityConfigDao() {
SecurityConfigDaoImpl impl = new SecurityConfigDaoImpl() ;
return impl ;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
/* get a map of patterns and authorities */
Map<String,String> viewPermissions = securityConfigDao().viewPermissions() ;
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry interceptUrlRegistry = http
.authorizeRequests().antMatchers("/publicAccess/**")
.permitAll();
for (Map.Entry<String, String> entry: viewPermissions.entrySet()) {
interceptUrlRegistry.antMatchers(entry.getKey()).hasAuthority(entry.getValue());
}
interceptUrlRegistry.anyRequest().authenticated()
.and()
...
/* rest of the configuration */
}
}
A simple solution that works for me.
<intercept-url pattern="/**/**" access="#{#customAuthenticationProvider.returnStringMethod}" />
<intercept-url pattern="/**" access="#{#customAuthenticationProvider.returnStringMethod}" />
customAuthenticationProvider is a bean
<beans:bean id="customAuthenticationProvider"
class="package.security.CustomAuthenticationProvider" />
in CustomAuthenticationProvider class create method:
public synchronized String getReturnStringMethod()
{
//get data from database (call your method)
if(condition){
return "IS_AUTHENTICATED_ANONYMOUSLY";
}
return "ROLE_ADMIN,ROLE_USER";
}

How/where can I manage Authentication at SecurityContext in pre-authentation Scenario

I wonder how/where can I manage Authentication at SecurityContext in pre-authentation Scenario.
I am using spring security 2.x to implement pre-authentation Scenario in my project. now, it patially work.
After user login by pre-authentation process, they can be authrozied with relevant roles, and are able to acecess resources which defined in security:filter.
e.g.
<security:filter-invocation-definition-source lowercase-comparisons="true" path-type="ant">
<security:intercept-url pattern="/resource/**" access="ROLE_ADMIN" />
In a some controller, I want to check principal in security content.
public abstract class AbstractUserAuthenticationController extends AbstractController
{
protected boolean isAuthenticated(String userName)
{
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); // where issue come up
But SecurityContextHolder.getContext().getAuthentication() always return null.
In addition, I also can not use secuiry tag in jsp to check if user has relative roles
<security:authorize ifNotGranted="ROLE_ADMIN">
no role found
</security:authorize>
Below shows the "filterChainProxy" I am using.
<bean id="filterChainProxy" class="org.springframework.security.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/*subscri*=httpSessionContextIntegrationFilter,logoutFilter,j2eePreAuthenticatedProcessingFilter,securityContextHolderAwareRequestFilter,subscribeExceptionTranslationFilter,filterInvocationInterceptor
/**=httpSessionContextIntegrationFilter,logoutFilter,j2eePreAuthenticatedProcessingFilter,logoutFilter,rememberMeProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
</value>
</property>
</bean>
<bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</bean>
<bean id="preAuthenticatedUserDetailsService" class="demo.project.security.auth.RsaAuthenticationUserDetailsService" >
<property name="userService" ref="userService" />
</bean>
<bean id="j2eePreAuthFilter" class="demo.project.security.filter.AutoLoginFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="userService" ref="userService" />
</bean>
I think I need to set Authentication to SecurityContext in somewhere, But I do not know where/where.
What I am missing? Can anyone provide me some clues?
Thanks!
Ian
You should use SecurityContextHolder.setContext method to store your SecurityContext prior to getting it back.
The simplest way for doing this is just SecurityContextHolder.setContext(new SecurityContextImpl()).

Spring LDAP - bind for successful connection

I'm trying to authenticate and then query our corporate LDAP using Spring LDAP and Spring security. I managed to make authentication work but when I attempt to run search I always get the following exception
In order to perform this operation a successful bind must be completed on the connection
After much research I have a theory that after I authenticate and before I can query I need to bind to connection. I just don't know what and how?
Just to mention - I can successfully browse and search our LDAP using JXplorer so my parameters are correct.
Here's section of my securityContext.xml
<security:http auto-config='true'>
<security:intercept-url pattern="/reports/goodbye.html"
access="ROLE_LOGOUT" />
<security:intercept-url pattern="/reports/**" access="ROLE_USER" />
<security:http-basic />
<security:logout logout-url="/reports/logout"
logout-success-url="/reports/goodbye.html" />
</security:http>
<security:ldap-server url="ldap://s140.foo.com:1389/dc=td,dc=foo,dc=com" />
<security:authentication-manager>
<security:authentication-provider ref="ldapAuthProvider">
</security:authentication-provider>
</security:authentication-manager>
<!-- Security beans -->
<bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://s140.foo.com:1389/dc=td,dc=foo,dc=com" />
</bean>
<bean id="ldapAuthProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg>
<bean class="foo.bar.reporting.server.security.ldap.LdapAuthenticatorImpl">
<property name="contextFactory" ref="contextSource" />
<property name="principalPrefix" value="TD\" />
<property name="employee" ref="employee"></property>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="foo.bar.reporting.server.security.ldap.LdapAuthoritiesPopulator" />
</constructor-arg>
</bean>
<!-- DAOs -->
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="contextSource" />
Here's code snippet from LdapAuthenticatorImpl that performs authentication. No problem here:
#Override
public DirContextOperations authenticate(final Authentication authentication) {
// Grab the username and password out of the authentication object.
final String name = authentication.getName();
final String principal = this.principalPrefix + name;
String password = "";
if (authentication.getCredentials() != null) {
password = authentication.getCredentials().toString();
}
if (!("".equals(principal.trim())) && !("".equals(password.trim()))) {
final InitialLdapContext ldapContext = (InitialLdapContext)
this.contextFactory.getContext(principal, password);
// We need to pass the context back out, so that the auth provider
// can add it to the Authentication object.
final DirContextOperations authAdapter = new DirContextAdapter();
authAdapter.addAttributeValue("ldapContext", ldapContext);
this.employee.setqId(name);
return authAdapter;
} else {
throw new BadCredentialsException("Blank username and/or password!");
}
}
And here's another code snippet from EmployeeDao with my futile attempt to query:
public List<Employee> queryEmployeesByName(String query)
throws BARServerException {
AndFilter filter = new AndFilter();
filter.and(new EqualsFilter("objectclass", "person"));
filter.and(new WhitespaceWildcardsFilter("cn", query));
try {
// the following line throws bind exception
List result = ldapTemplate.search(BASE, filter.encode(),
new AttributesMapper() {
#Override
public Employee mapFromAttributes(Attributes attrs)
throws NamingException {
Employee emp = new Employee((String) attrs.get("cn").get(),
(String) attrs.get("cn").get(),
(String) attrs.get("cn").get());
return emp;
}
});
return result;
} catch (Exception e) {
throw new BarServerException("Failed to query LDAP", e);
}
}
And lastly - the exception I'm getting
org.springframework.ldap.UncategorizedLdapException:
Uncategorized exception occured during LDAP processing; nested exception is
javax.naming.NamingException: [LDAP: error code 1 - 00000000: LdapErr:
DSID-0C090627, comment: In order to perform this operation a successful bind
must be completed on the connection., data 0, vece]; remaining name
'DC=TD,DC=FOO,DC=COM'
It looks like your LDAP is configured to not allow a search without binding to it (no anonymous bind). Also you have implemented PasswordComparisonAuthenticator and not BindAuthenticator to authenticate to LDAP.
You could try modifying your queryEmployeesByName() method to bind and then search, looking at some examples in the doc.
I'm going to accept #Raghuram answer mainly because it got me thinking in the right direction.
Why my code was failing? Turned out - the way I wired it I was trying to perform anonymous search which is prohibited by the system - hence the error.
How to rewire example above to work? First thing (and ugly thing at that) you need to provide user name and password of user that will be used to access the system. Very counterintuitive even when you login and authenticated, even if you are using BindAuthenticator system will not attempt to reuse your credentials. Bummer. So you need to stick 2 parameters into contextSource definition like so:
<bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://foo.com:389/dc=td,dc=foo,dc=com" />
<!-- TODO - need to hide this or encrypt a password -->
<property name="userDn" value="CN=admin,OU=Application,DC=TD,DC=FOO,DC=COM" />
<property name="password" value="blah" />
</bean>
Doing that allowed me to replace custom implementation of authenticator with generic BindAuthenticator and then my Java search started working
I got the same error, couldn't find a solution.
Finally I changed the application pool identity to network service and everything worked like a charm.
(I have windows authentication and anonymous enabled on my site)

Resources