Managing users in Spring Security
The application provided in Chapter 1, Anatomy of an Unsafe Application, provides a mechanism for creating a new CalendarUser object, so it should be fairly trivial to create our CalendarUser object after a user signs up. However, Spring Security has no knowledge of CalendarUser. This means that we will need to add a new user in Spring Security too. Don't worry, we will remove the need for the dual maintenance of users later in this chapter.
Spring Security provides an o.s.s.provisioning.UserDetailsManager interface for managing users. Remember our in-memory Spring Security configuration?
auth.inMemoryAuthentication().
withUser("user").password("user").roles("USER");
The .inMemoryAuthentication() method creates an in-memory implementation of UserDetailsManager, named o.s.s.provisioning.InMemoryUserDetailsManager, which can be used to create a new Spring Security user.
While converting from an XML configuration to a Java-based configuration in Spring Security, there is currently a limitation with the Spring Security DSL where exposing multiple beans is not currently supported. There is a JIRA opened for this issue at https://jira.spring.io/browse/SPR-13779.
Let's see how we can manage users in Spring Security by performing the following steps:
- In order to expose UserDetailsManager using a Java-based configuration, we need to create InMemoryUserDetailsManager outside of the WebSecurityConfigurerAdapter DSL:
//src/main/java/com/packtpub/springsecurity/configuration/
SecurityConfig.java
@Bean
@Override
public UserDetailsManager userDetailsService() {
InMemoryUserDetailsManager manager = new
InMemoryUserDetailsManager();
manager.createUser(
User.withUsername("user1@example.com")
.password("user1").roles("USER").build());
manager.createUser(
User.withUsername("admin1@example.com")
.password("admin1").roles("USER", "ADMIN").build());
return manager;
}
- Once we have an exposed UserDetailsManager interface in our Spring configuration, all we need to do is update our existing CalendarService implementation, DefaultCalendarService, to add a user in Spring Security. Make the following updates to the DefaultCalendarService.java file:
//src/main/java/com/packtpub/springsecurity/service/
DefaultCalendarService.java
public int createUser(CalendarUser user) {
List<GrantedAuthority> authorities = AuthorityUtils.
createAuthorityList("ROLE_USER");
UserDetails userDetails = new User(user.getEmail(),
user.getPassword(), authorities);
// create a Spring Security user
userDetailsManager.createUser(userDetails);
// create a CalendarUser
return userDao.createUser(user);
}
- In order to leverage UserDetailsManager, we first convert CalendarUser into the UserDetails object of Spring Security.
- Later, we use UserDetailsManager to save the UserDetails object. The conversion is necessary because Spring Security has no understanding of how to save our custom CalendarUser object, so we must map CalendarUser to an object Spring Security understands. You will notice that the GrantedAuthority object corresponds to the authorities attribute of our SecurityConfig file. We hardcode this for simplicity and due to the fact that there is no concept of roles in our existing system.