Skip to content
Advertisement

Spring Boot, Spring-Security – BcrypPasswordEncoder in new component-based security configuration

I am trying to use the new Component-Based (Without WebSecurityConfigurerAdapter) configuration and setted up my Security Configuration as follow:

SecurityConfiguration.java file

JavaScript

but when I run the application and try to log a user the following error appears even though I have the BCryptPasswordEncoder as a bean in my SecurityConfiguration:

Error Stack Trace*

JavaScript

Which is the correct way to set up the PasswordEncoder in the new component-configuration?

Edit: adding login logic

AppUserService interface

JavaScript

and the AppUserServiceImplementation:

JavaScript

Edit2: added CustomAuthenticationFilter.java code

CustomAuthenticationFilter.java

JavaScript

Advertisement

Answer

Judging by the stacktrace I assume your CustomAuthenticationFilter calls AuthenticationManager.authenticate() method on a UsernamePasswordAuthenticationToken object. That, by default, calls DaoAuthenticationProvider, which is created with a DelegatingPasswordEncoder, containing 11 password encoders, and which is trying to match passwords with this encoder (not your BCryptPasswordEncoder bean).

This DelegatingPasswordEncoder tries to match stored password, retrieved from your UserDetailsService, and it assumes your password is stored with a key (prefix), like this:

JavaScript

You’ve registered a bean of type BCryptPasswordEncoder and you’re encoding your password with it, so passwords are stored without {bcrypt} prefix (just the encoded password is stored), and when calling AuthenticationManager.authenticate() mentioned DelegatingPasswordEncoder sees null prefix and cannot find the corresponding PasswordEncoder in a map – that’s what the error message is about.

So you can define a PasswordEncoder bean as a DelegatingPasswordEncoder, which, by default, uses BCryptPasswordEncoder to encode passwords.

Like this:

JavaScript

That way stored passwords will have {prefix} and DaoAuthenticationProvider will be able to match passwords. Also I advise to remove the BCryptPasswordEncoder field from your SecurityConfiguration class – you don’t need it there.

Also you can stuck with bean cycle dependencies, because your UserDetailsService injects PasswordEncoder, and PasswordEncoder is defined in a configuration, where UserDetailsService is injected, so you might also need refactoring.
For example, try to extract UserDetailsService:

JavaScript

Or define a bean of this type UserDetailsService right in your SecurityConfiguration class:

JavaScript

Also you can:

  • instead of a custom filter create your own login endpoint, where you can check password matches using BCryptPasswordEncoder directly;
  • create your own AuthenticationProvider with a BCryptPasswordEncoder as a password encoder and use it in your CustomAuthenticationFilter to authenticate user.
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement