Saving Multiple Authorities to Database on New User in Spring

In NixMash Spring we’re using both MySQL and H2Database (two different profiles by environment) for saving user and user authority information. The schema consists of three tables, users, user_authorities and authorities.

The Persistence Models

The Models of User and Authority are not unlike other models, though there are a few differences.

User implements the Spring Security UserDetails Interface.

@Entity
@Table(name = "users")
public class User implements UserDetails

Authority implements the Spring Security GrantedAuthority Interface.

@Entity
@Table(name = "authorities")
public class Authority implements GrantedAuthority

The @ManyToMany Users to Authorities relationship is no different than others, and you’ll notice we’re building a simple Authority Collection here as opposed to Collections of GrantedAuthority objects.

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_authorities", 
    joinColumns = @JoinColumn(name = "user_id"),
    inverseJoinColumns = @JoinColumn(name = "authority_id"))
private Collection<Authority> authorities;


@Override
public Collection<Authority> getAuthorities() {
	return authorities;
}

Saving Authorities on New User Creation

Now we get to the heart of the post, adding multiple authorities on new user creation and populating the necessary database tables, specifically the user_authorities table containing the new user_id and the authority_id(s). The UserService implementation for creating a new user is below.

@Transactional
@Override
public User create(UserCreateForm form) {

	User user = new User();
	user.setUsername(form.getUsername());
	user.setFirstname(form.getFirstname());
	user.setLastname(form.getLastname());
	user.setEmail(form.getEmail());
	user.setPassword(new BCryptPasswordEncoder().encode(form.getPassword()));
	User saved = userRepository.save(user);

	for (Authority authority : form.getAuthorities()) {
	    Authority _authority = authorityRepository.findByAuthority(authority.getAuthority());
	    saved.getAuthorities().add(_authority);
	}

	Authentication auth =
		new UsernamePasswordAuthenticationToken(saved, saved.getPassword(), saved.getAuthorities());
	SecurityContextHolder.getContext().setAuthentication(auth);

	return saved;
}

We populate the User Model from our DTO object, the UserCreateForm on which we also perform our validation. (More on validation in a future post.)

We create a new User object upon userRepository.save(), then add the Authorities as normally. To update the Security Context we set the new user authentication and return with a fully Authenticated Environment with a big Hello, Bob Cratchet! waiting for us in the header.

All of the code described in the post is available in the v0.1.6 branch of Spring NixMash on GitHub.