16

I'm trying to learn Spring security currently. I used BCryptPasswordEncoder to encode user password before persisting into a database

Code:

@Override
    public void saveUser(User user) {
        user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
        user.setActive(1);
        Role userRole = roleRepository.findByRole("ADMIN");
        user.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
        userRepository.save(user);
    }

Then used it during authentication as well and User was getting authenticated as expected.

@Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.
            jdbcAuthentication()
                .usersByUsernameQuery(usersQuery)
                .authoritiesByUsernameQuery(rolesQuery)
                .dataSource(dataSource).passwordEncoder(bCryptPasswordEncoder);
    }

Then I removed .passwordEncoder(bCryptPasswordEncoder); from configure() method, still users with encoded password is getting authenticated successfully.

Then I removed password encoder from both the saveUser() and the configure() method, and persisted a User into the database(i.e without password encoding) and tried to access an authenticated page but I got AccessedDeniedException,

But users with encoded password still gets authenticated even though i removed passwordEncoder() from configure() method. Why is this happening?

Does spring security by default use password encoder during authentication?

If so how to use spring security without password encoding?

10
  • Have you created BCryptPasswordEncoder bean? Commented Jul 6, 2018 at 10:33
  • @efex09 yes and it works perfectly with encoded password , but authentication fails if i do not use password encoding Commented Jul 6, 2018 at 10:41
  • 1
    Why is my question downvoted? Commented Jul 6, 2018 at 10:45
  • 2
    Unfortunately, many downvoters don't bother explaining why they think the question is bad. We may never know. Commented Jul 6, 2018 at 10:54
  • 3
    Which has that enabled by default. Actually it has an even better scheme for security as you can specify in your password which encoding to use (and it defaults to Bcrypt I believe). So if you have a plain password prefix it with {noop}<the-password> and it will use a plain encoder. Use {bcrypt} as the prefix for crypt (which is also the default). See docs.spring.io/spring-security/site/docs/current/reference/… Commented Jul 6, 2018 at 11:49

4 Answers 4

25

Maybe you can implement this simple code to evade Spring Encoder

public class PasswordEnconderTest implements PasswordEncoder {
    @Override
    public String encode(CharSequence charSequence) {
        return charSequence.toString();
    }

    @Override
    public boolean matches(CharSequence charSequence, String s) {
        return charSequence.toString().equals(s);
    }
}

and add in your WebSecurityConfig:

@Bean
public PasswordEncoder passwordEncoder(){
    return new PasswordEnconderTest();
}

it's not recommended but you can implement

Sign up to request clarification or add additional context in comments.

Comments

11

With Spring Security 5 encryption on passwords is always enabled. The encryption used by default is bcrypt. What is neat about Spring Security 5 is that it actually allows you to specify, in your password, which encryption was used to create the has.

For this see the Password Storage Format in the Spring Security Reference Guide. In short it allows you to prefix your password for a well known key to an algorithm. The storage format is {<encryption>}<your-password-hash>.

When using nothing it would become {noop}your-password (which would use the NoOpPasswordEncoder and {bcrypt}$a2...... would use the BcryptPasswordEncoder. There are several algorithms supported out-of-the-box, but you can also define your own.

To define your own create your own PasswordEncoder and register it under a key with the DelegatingPasswordEncoder.

4 Comments

Would you mind replacing “encrypt” with “hash” or “encode” or something in that vein? It’s not encryption.
@M. Deinum In my application admin need to login to user account and admin has the encoded password.So is there a way for admin to bypass this password encoding while login???Please help me.ie,in my app there are two way of logging one by the user which happens normally by the clear text password which uses password encoding in spring boot and the other is by the admin where hashed password is used by admin and which needs to bypass the spring boot password encoding.I am using BCryptEncoder.
Where did you find that the default hash algorithm is bcrypt? Here it seems to say the opposite, but I'm not sure how to interpret it: "Based upon the Password History section you might expect that the default PasswordEncoder is now something like BCryptPasswordEncoder. However, this ignores three real world problems:"
The default is DelegatingPasswordEncoder which, when not explicitly configured, uses the BCryptPasswordEncoder as the default.
1

Unsure if it is what you're after but a little cheap workaround I used so I didn't have to worry about encoding my database yet was

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
  DataSource dataSource;

  @Autowired
  public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
    auth.jdbcAuthentication().dataSource(dataSource)
        .usersByUsernameQuery("select username,CONCAT('{noop}',password),true from 
public.\"Users\" where username=?")
        .authoritiesByUsernameQuery("select username,role from public.\"Users\" where 
username=?");
}
...

Note instead of grabbing the password I am concatenating it with {noop} first to tell the system to not use encoding.

Probably a sin but it works for now.

Comments

0

Did you try

@Bean
public static NoOpPasswordEncoder passwordEncoder() {
  return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}

And then in configure global security

@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().usersByUsernameQuery(usersQuery).dataSource(dataSource)
                .authoritiesByUsernameQuery(rolesQuery).passwordEncoder(passwordEncoder());
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.