Aa Yy
Aa Yy

Reputation: 1742

Spring Boot: How to specify the PasswordEncoder?

Currently I got the main class:

package com.recweb.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
/*@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})*/
public class SpringbootApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }
}

a members class (id, firstname..), a MemberController class:

package com.recweb.springboot;

import java.util.Arrays;
import java.util.List;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MemberController {
    @GetMapping("/members")
    public List<Member> getAllUsers() {
        return Arrays.asList(new Member(1, "amit"));
    }
}

and a WebSecurityConfig class:

package com.recweb.springboot;

import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("user").password("user").roles("USER").build());
        return manager;
    }
}

When i run "http://localhost:8080/members" i get a login page, i enter "user" as user & "user" as password and then i get the hardcoded Member. It worked fine, but then i right clicked on my project-Run as-Maven install (because i added a dependency, i don't know if that was necessary, first time with Maven too). Since then, when i enter "user" & "user" on the login page i get this error:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
    at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.java:233) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:196) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:86) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:166) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199) ~[spring-security-core-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:94) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) ~[spring-security-web-5.0.0.BUILD-SNAPSHOT.jar:5.0.0.BUILD-SNAPSHOT]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.0.1.RELEASE.jar:5.0.1.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.23.jar:8.5.23]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]

and it stays on the login page. I tried to remove the dependency & Maven install again, but no luck. This is my POM:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.recweb</groupId>
    <artifactId>springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.BUILD-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
                </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.3.0.Final</version>
</dependency>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
<!--         <scope>provided</scope> -->
</dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>


</project>

What went wrong? Thanks

Upvotes: 101

Views: 129200

Answers (17)

providerZ
providerZ

Reputation: 277

PasswordEncoder is already been deprecated so all these three approaches need to be changed :

1- User.withDefaultPasswordEncoder().username("user").password("user").roles("USER").build();

2-User.withUsername("user").password("{noop}user").roles("USER").build();

3-passwordEncoder(NoOpPasswordEncoder.getInstance())

And the new way is to use BCryptPasswordEncoder or DelegatingPasswordEncoder

we are going to use kotlin and the DelegatingPasswordEncoder approach since it is recommended more than the BCryptPasswordEncoder approach

the DelegatingPasswordEncoder approach should be like this :

val encoder= PasswordEncoderFactories.createDelegatingPasswordEncoder()
             
          val user  = User
            .withUsername("khalid")
            .password(encoder.encode("12345"))
            .roles("USER")
            .build()

And another implementation using it with AuthenticationManagerBuilder like this:

 val encoder= PasswordEncoderFactories.createDelegatingPasswordEncoder()
 AuthenticationManagerBuilder().inMemoryAuthentication().withUser("user").password(encoder.encode("user")).roles("USER")

Upvotes: 1

Erycoking
Erycoking

Reputation: 559

This is how I solved it

    @Bean
    public PasswordEncoder delegatingPasswordEncoder() {
        Map<String, PasswordEncoder> encoders = new HashMap<>();
        encoders.put("bcrypt", new BCryptPasswordEncoder());
        DelegatingPasswordEncoder passwordEncoder = new DelegatingPasswordEncoder("bcrypt", encoders);
        passwordEncoder.setDefaultPasswordEncoderForMatches(new BCryptPasswordEncoder());
        return passwordEncoder;
    }

Upvotes: 1

maxeh
maxeh

Reputation: 1593

As I have found many different upvoted answers to this question with very little explanation, I decided to provide my own answer which should provide a more in-depth understanding of how Spring Security password encoding works. I spent some time debugging the Spring code to figure out all the details.

Internally, Spring Security uses a DelegatingPasswordEncoder when authenticating users. Assuming the credentials user:password are provided during login, the DelegatingPasswordEncoder loads the stored password for this particular user and tries to determine its encoding. The DelegatingPasswordEncoder expects passwords to be stored in the form {type}hash:

{bcrypt}hash
{scrypt}hash
{MD5}hash
{noop}hash
...

If the default DelegatingPasswordEncoder now encounters a stored password without the {type}, it cannot infer which encoder to use and instead uses an UnmappedIdPasswordEncoder which throws an exception. This means that the exception occurs because the password is stored without any encoding information and Spring Security uses a DelegatingPasswordEncoder which is not able to handle this.

One way to solve this issue is to also use the DelegatingPasswordEncoder to encode and store the password. The encoder retrieved with PasswordEncoderFactories.createDelegatingPasswordEncoder() will use bcrypt as default encoding so that the password will be stored as {bcrypt}hash:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    auth.inMemoryAuthentication()
        .withUser("user")
        .password(encoder.encode("password"))
        .roles("USER");
}

The DelegatingPasswordEncoder is useful when you want to handle different encodings in your project. For example, assume old passwords were stored in plain text and new passwords are now encoded with bcrypt. You will just have to prefix all your old stored passwords with {noop} and you are good to go. It would work the same if you had stored passwords encoded with MD5, just prefix them with {MD5}.

In a new project it would also be possible and is perfectly fine to define a specific encode like the BCryptPasswordEncoder instead of using the delegating one. When the encoder is registered as a bean, Spring Security will also use this encoder for authentication instead of the DelegatingPasswordEncoder. Passwords are now stored as bcrypt hash without the {type}.

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

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    auth.inMemoryAuthentication()
        .withUser("user")
        .password(passwordEncoder().encode("password"))
        .roles("USER");
}

So you are able to chose one of the described variants. I recently went with PasswordEncoderFactories.createDelegatingPasswordEncoder() as this only requires one line of code and no bean creation is necessary.

Upvotes: 3

Felix Oriedo
Felix Oriedo

Reputation: 26

If you are doing in Memory Authentication, here's the code on how to go about it. Tested on Spring Boot 2.3.3.RELEASE

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    static PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("testuser").password(encoder.encode("testpassword")).roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests().antMatchers("/sites.xhtml/**").hasRole("ADMIN").anyRequest().fullyAuthenticated().and()
                .httpBasic();
    }

    @Bean
    public static PasswordEncoder passwordEncoder() {
        return encoder;

    }
}
    

Upvotes: 0

Nirbhay Rana
Nirbhay Rana

Reputation: 4357

Use NoOpPasswordEncoder for inMemoryAuthentication

auth.inMemoryAuthentication()
    .withUser("user")
    .password("{noop}password")
    .roles("USER")

Upvotes: 71

varren
varren

Reputation: 14731

Had IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" exception in my initial app loading startup housekeeper. (Just needed to normalize data in DB before the app start.) With this (manually set an authenticated user) approach you can create UsernamePasswordAuthenticationToken and setAuthentication. You can get IllegalArgumentException, if you don't specify 3-rd argument AuthorityList.

UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(
        admin.getEmail(), 
        UserServiceImpl.PASSWORD_ENCODER.encode(admin.getPassword()),
        AuthorityUtils.createAuthorityList(admin.getRoles()) // <= had to add this line to resolve the exception
);

SecurityContextHolder.getContext().setAuthentication(authReq);

Maybe some other setup steps could also work, but setting AuthorityList is good enough for me. And you can at least dig in this direction if can't find a solution on this page.

Upvotes: 0

Valix85
Valix85

Reputation: 793

Try this in SecurityConfig extends WebSecurityConfigurerAdapter :

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception{        
    auth
        .inMemoryAuthentication()
            .withUser("user")
            .password(passwordEncoder().encode("password"))
            .roles("USER")
        .and()
            .withUser("admin")
            .password(passwordEncoder().encode("admin"))
            .roles("USER", "ADMIN");
}

Work for me

Upvotes: 13

Arun Kumar N
Arun Kumar N

Reputation: 1669

Use any of the following and it will work fine:-

@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("admin").password("{noop}admin@123").roles("admin");
    }

or

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("admin").password("{noop}admin").roles("admin");
    }

or

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance()).withUser("admin").password("{noop}admin").roles("admin");
    }

Thanks!

Upvotes: 6

Ahmed Salem
Ahmed Salem

Reputation: 1757

You need to set Password encoder , check the following sample

PasswordEncoder encoder =
             PasswordEncoderFactories.createDelegatingPasswordEncoder();
    auth.inMemoryAuthentication().passwordEncoder(encoder).withUser("Ahmad")
            .password("1600").roles("USER", "ADMIN").and().withUser("Belal").password("1515").roles("USER");

Upvotes: 0

Farid Ahmed
Farid Ahmed

Reputation: 719

A few days ago I have to face the same problem on spring security version (5.0.8). See the example version here:

code:

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

auth
                .inMemoryAuthentication()
                .passwordEncoder(NoOpPasswordEncoder.getInstance())
                .withUser("farid").password("farid").roles("USER")
                .and()
                .withUser("admin").password("admin").roles("ADMIN");
    }

OR

When you are configuring the ClientDetailsServiceConfigurer, you have to also apply the new password storag`enter code here`e format to the client secret.

.secret("{noop}secret")

you can see the link: enter link description here

Upvotes: 0

Amar
Amar

Reputation: 19

Prefix all existing passwords with {noop} to keep the default encoder of Spring Security 5.

Example:

auth.inMemoryAuthentication()
    .withUser("admin").password("{noop}admin!234").roles("ADMIN");

Upvotes: 1

Randhir
Randhir

Reputation: 137

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception{    
    auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance())
            .withUser("test").password("test123").roles("USER").and()
            .withUser("test1").password("test123").roles("ADMIN");
}

Upvotes: 11

George Rosario
George Rosario

Reputation: 781

You can use this, but be advised that User.withDefaultPasswordEncoder() is deprecated:

@Bean
@Override
public UserDetailsService userDetailsService() {

    PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    final User.UserBuilder userBuilder = User.builder().passwordEncoder(encoder::encode);
    UserDetails user = userBuilder
            .username("user")
            .password("password")
            .roles("USER")
            .build();

    UserDetails admin = userBuilder
            .username("admin")
            .password("password")
            .roles("USER","ADMIN")
            .build();

    return new InMemoryUserDetailsManager(user, admin);
}

Upvotes: 11

Dzinot
Dzinot

Reputation: 549

You need to set the password encoder like this:

@Bean
public PasswordEncoder passwordEncoder() {
  return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

It's required to use the passwordEncoder for the users and also for the clients in Spring Boot 2

Check out this repository https://github.com/dzinot/spring-boot-2-oauth2-authorization-jwt

You can see how the passwordEncoder is set up and how to use it with users and clients in the database.

Upvotes: 2

KirstenKali
KirstenKali

Reputation: 453

I simply added

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

To the configuration class

Upvotes: 13

Dean
Dean

Reputation: 374

You need to have some sort of a password encoder, but

withDefaultPasswordEncoder()

is deprecated and no more suitable for production. Use this instead:

PasswordEncoder encoder =
     PasswordEncoderFactories.createDelegatingPasswordEncoder();

...

UserDetails user = User.withUsername("someusername")
                       .password(encoder.encode("somepassword"))
                       .roles("USER").build();

Ref: https://docs.spring.io/spring-security/site/docs/5.0.2.BUILD-SNAPSHOT/api/index.html?org/springframework/security/core/userdetails/User.html

Upvotes: 24

dmendezg
dmendezg

Reputation: 1928

In spring-security-core:5.0.0.RC1, the default PasswordEncoder is built as a DelegatingPasswordEncoder. When you store the users in memory, you are providing the passwords in plain text and when trying to retrieve the encoder from the DelegatingPasswordEncoder to validate the password it can't find one that matches the way in which these passwords were stored.

Use this way to create users instead.

User.withDefaultPasswordEncoder().username("user").password("user").roles("USER").build(); 

You can also simply prefix {noop} to your passwords in order for the DelegatingPasswordEncoder use the NoOpPasswordEncoder to validate these passwords. Notice that NoOpPasswordEncoder is deprecated though, as it is not a good practice to store passwords in plain text.

User.withUsername("user").password("{noop}user").roles("USER").build();

For more information, check this post.

https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-encoding

Upvotes: 148

Related Questions