“Spring Boot Security” was a hard thing for me to get myself started using. To implement it, you must first understand preliminary concepts of Spring’s “core” such as the Auto Configuration. This error is one of the longest errors I’ve ever encountered in a Java application.
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:510)
When first booting up an application that imports the Spring Boot Security dependency, this error might show up if you don’t have the “UserDetails Bean” auto-configured. Today, we will talk about how I came to the solution regarding this particular statement.
The solution
First, I want to show a larger snippet of the stack trace.
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:510)
at jdk.internal.reflect.GeneratedMethodAccessor75.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy141.authenticate(Unknown Source)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:510)
As far as the browser is concerned, upon receiving this error, you might also see a response on your website that says: “Internal Server Error: 500”.
The trigger that causes this error is attempting to log in as a user to a Spring Security enabled website. I attempted to login as the administrator, and this is the message I received.
The root cause behind this particular error has to do with Spring Auto Configuration. To fix it, the first thing you have to do was select a “Spring User Details Configuration file” where you need to add some important code. It should be a file with a Java class name annotated with the Spring annotation @Configuration or @Component. I would choose a file named UserDetailsConcrete.java. I did not have this file created before enabling web security, so shortly before achieving this error I had to create this file. Be sure to place @Component at the top, and ensure the class implements the UserDetailsService interface, imported from Spring security core.
Step 2: When I insert the following method into a Spring User Details Configuration file, the problem goes away:
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import static org.springframework.security.core.userdetails.User.withUsername;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@Component
class UserDetailsConcrete implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
return UserBuilder.withUsername(username)
.password(password)
.authorities(roles)
.accountExpired(false)
.accountLocked(false)
.credentialsExpired(false)
.disabled(false)
.build();
// be sure to add code to get the username, password, and roles parameters
// you will use these to fill in parameters in when you call this method above
}
}
Explanation why this error will go away
The sole expression in this method creates what is called a “UserDetails” object, which Spring will use in its security context. Just by including this in your Spring security project, you will resolve this error. You don’t even need to call this method directly somewhere else in your application code – it gets called for you when a “UserDetails” object is needed. It is imperative that this code gets called at least once when your application wishes to create a new user and log into your Spring application.
How can you ensure that this method gets called? The answer is Spring “Auto Configuration.” Spring Auto Configuration checks your entire project for classes annotated with certain Spring annotations, including @Component. When it finds this class and this annotation, the methods inside can be used by Spring to manage essential functions that Spring Boot provides on its own, including managing logging in and logging out. UserBuilder.build() can be used to create this object using parameters normally required in such a process (username, password, and roles list).
Your job then is to ensure that before calling UserDetails, you can retrieve all three of these items. Once these parameters are set, you can use UserBuilder.build to log in.