Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security with OAuth2 and JWT: Encoded password does not look like BCrypt

I am trying to implement a spring AuthorizationServer with JWT. I was able to produce JWT tokens and login until I added BCrypt to the mix. Now, when I am trying to login, I get "Bad credentials" from the API.

OAuth2Configuration.java

@Configuration
@EnableAuthorizationServer
public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {

    private DataSource dataSource;
    private AuthenticationManager authenticationManager;
    private BCryptPasswordEncoder passwordEncoder;

    public OAuth2Configuration(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
        this.dataSource = new Jdbc3PoolingDataSource();
        this.passwordEncoder = new BCryptPasswordEncoder();
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.passwordEncoder(passwordEncoder);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("api-client")
                .secret("verysecretivesecret")
                .scopes("READ", "WRITE", "DELETE")
                .authorizedGrantTypes("implicit", "refresh_tokens", "password", "authorization_code");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authorizationCodeServices(authorizationCodeServices())
                .tokenStore(tokenStore())
                .tokenEnhancer(jwtTokenEnhancer())
                .authenticationManager(authenticationManager);
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtTokenEnhancer());
    }

    @Bean
    protected JwtAccessTokenConverter jwtTokenEnhancer() {
        return new JwtAccessTokenConverter();
    }

    @Bean
    protected AuthorizationCodeServices authorizationCodeServices() {
        return new JdbcAuthorizationCodeServices(dataSource);
    }

}

WebSecurityConfig.java

@Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private AccountDetailsService accountDetailsService;
    private BCryptPasswordEncoder passwordEncoder;
    private DataSource dataSource;

    WebSecurityConfig(AccountDetailsService accountDetailsService) {
        this.accountDetailsService = accountDetailsService;
        this.dataSource = new Jdbc3PoolingDataSource();
        this.passwordEncoder = new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(accountDetailsService).passwordEncoder(passwordEncoder).and().jdbcAuthentication().dataSource(dataSource);
    }
}

SeedData.java

@Override
public void run(String... args) throws Exception {      

    Stream.of("alan,test").map(x -> x.split(","))
            .forEach(tuple -> {
                Account user = new Account();
                user.setUsername(tuple[0]);
                user.setPassword(new BCryptPasswordEncoder().encode(tuple[1]));
                user.setEmail(tuple[0]);
                user.setRoles(Collections.singletonList(role));
                user.setActive(true);
                this.accountRepository.save(user);
            });
}

Thanks for your help.

like image 260
Chirdeep Tomar Avatar asked Nov 20 '16 00:11

Chirdeep Tomar


People also ask

How do you fix encoded password does not look like BCrypt?

To fix the login issue and get rid of the warning “Encoded password does not look like BCrypt”, either remove the {bcrypt} prefix or remove the password encoder declaration.

Does Spring Security use BCrypt?

There are a few encoding mechanisms supported by Spring Security, and for this tutorial, we'll use BCrypt, as it's usually the best solution available.

Does spring security support password encoding?

Spring Security supports many password encoders, for both old and modern algorithms. Also, Spring Security provides methods to work with multiple password encodings in the same application.

What can I use instead of NoOpPasswordEncoder?

Class NoOpPasswordEncoder. Deprecated. This PasswordEncoder is not secure. Instead use an adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or SCryptPasswordEncoder.


2 Answers

I needed to make the following change to get it to work. If anyone else needs it.

@Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(accountDetailsService)
                    .passwordEncoder(passwordEncoder)
                    .and()
                    .authenticationProvider(authenticationProvider())
                    .jdbcAuthentication()
                    .dataSource(dataSource);
        }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(accountDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder);
        return authenticationProvider;
    }
like image 75
Chirdeep Tomar Avatar answered Sep 18 '22 09:09

Chirdeep Tomar


This is because you applied a BCrypt both to WebSecurity and AuthorizationServer. So you need to keep not only BCrypt encrypted user passwords in your store, but also BCrypt encrypted client secrets for OAuth2. I guess this was not what you tried to approach.

In order to make your code working, either remove

   @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.passwordEncoder(passwordEncoder);
    }

or manually encrypt your "verysecretivesecret"

like image 37
David Steiman Avatar answered Sep 19 '22 09:09

David Steiman