Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Configure Passwords With Spring Security

DZone's Guide to

How to Configure Passwords With Spring Security

Learn more about the authentication architecture within the Spring Framework.

· Security Zone ·
Free Resource

Discover how to provide active runtime protection for your web applications from known and unknown vulnerabilities including Remote Code Execution Attacks.

In this article, we will be discussing how to configure passwords with Spring Security and explore the authentication architecture of the Spring Framework.

Spring Security is used for securing a web application API developed in Spring and is comprised of both authentication and authorization components.

Authentication is all about who should get access to the API and who should not, whereas authorization is all about which API can gain access.

Authentication in Spring can be done in two ways, in terms of user password configurations:

  • Using the database to store the password
  • Using an active directory like LDAP to store the password

When the user information is stored in a database, Spring provides two ways to authenticate:

  • UserDetailService
  • JDBCAuthentication

When the user information is stored in some active directory like LDAP, we can use Spring LDAP authentication.

Image title


Authentication Manager and Provider in Spring Security

Authentication manager is the interface that provides the authentication mechanism for any object. The most common implementation of it is the AuthenticationProvider. AuthenticationProvider is similar to the AuthenticationManager interface but it has an extra method, support(), which checks whether the object supports the authentication type or not.

public interface AuthenticationProvider {

Authentication authenticate(Authentication authentication)
throws AuthenticationException;

boolean supports(Class<?> authentication);

}


Sometimes, we have a logical group of the section in the application, which needs to be authenticated differently. And each group is going to have a dedicated AuthenticationManager

Spring Security provides a way of configuring the AuthenticationManager with the help of a AuthenticationManagerBuilderclass, which is used for setting up authentication using JDBC, LDAP, or a customUserDetailsService.

The following examples can be found here.

Configuring Passwords

For simplicity purposes, I have used the h2 database and a single table to hold the user role and password. In a real-life scenario, the role should be part of a different table.

USER table

user_id

name

password

role

joy

Joydip

123

ROLE_USER

admin

Admin

8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918

ROLE_ADMIN

Password is sha256 encoded.

You will need to create a data.sql for loading the insertion query on server startup to the h2 database:

insert into user (user_id, name,password,role) values ('joy','Joydip','A665A45920422F9D417E4867EFDC4FB8A04A1F3FFF1FA07E998E86F7F7A27AE3','ROLE_USER')

insert into user (user_id, name,password,role) values ('admin','admin','8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918','ROLE_ADMIN')


Create a configuration class, as shown below:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
public void configure(AuthenticationManagerBuilder auth)
            throws Exception {
// Various authentication to follow 
}


@Override
    protected void configure(HttpSecurity http) throws Exception {
//various authorizations to follow 
}

}


Then, make these changes in the pom.xml:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>


@EnableWebSecurity is the marker annotation that tells Spring to apply the configuration class to the global WebSecurity. Adding the spring-boot-starter-security jar itself brings multiple Spring Security jars in the classpath, which, itself, will enable the security to display an out-of-the-box Spring Security login page.

JDBC Authentication

Update the configure method to enable JDBC authentication:

@Override
publicvoid configure(AuthenticationManagerBuilder auth) throws Exception {

 auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery("select user_id,password, 'true' as enabled from user where user_id=?")

                    .authoritiesByUsernameQuery("select user_id, role from user where user_id=?").passwordEncoder(new ShaPasswordEncoder(256));

}


Custom UserDetailsService

Next, add the Spring data JPA library in the pom.xml file:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>


Then, you will create a custom UserRepository:

@Transactional
public interface UserRepository extends JpaRepository<User, String> {

}


Then, you need to create a SecureUser that extends the User class and implements the UserDetails to handle roles and set the User ID and password.

public class SecuredUser extends User implements UserDetails {

private static final long serialVersionUID = 1L;

public SecuredUser(User user){

this.setUserId(user.getUserId());
this.setName(user.getName());
this.setPassword(user.getPassword());
this.setRole(user.getRole());
}


@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> authorities = new ArrayList<>();

//TODO Currently handled with one role for an user
String userRole =  super.getRole();
if(userRole != null)
{
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(userRole);
authorities.add(authority);
}
return authorities;
}

@Override
public String getUsername() {
return super.getUserId();
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}

}


Next, you will create a UserDetailsServiceImpl, an implementation of the UserDetailsService:

@Component
public class UserDetailServiceImpl implements UserDetailsService {

@Resource
UserRepository userrepository;

@Override
public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException {
User user=userrepository.findOne(userId);

return new SecuredUser(user) ;
}

}


Next, update the configure class, as shown below:

@Override
public void configure(AuthenticationManagerBuilder auth)
            throws Exception {
auth.userDetailsService(userDetailServiceImpl).passwordEncoder(new ShaPasswordEncoder(256));
}


LDAP Authentication

LDAP authentication is where credentials are stored in the active directory. We will use a sample active directory from Spring. The server will be set up in the 8389 port.

First, add the following in the pom.xml:

 <dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
</dependency>
<dependency>
<groupId>com.unboundid</groupId>
<artifactId>unboundid-ldapsdk</artifactId>
</dependency>


Then, add the LDAP configuration in the application.properties file:

spring.ldap.embedded.ldif=classpath:test-server.ldif
spring.ldap.embedded.base-dn=dc=springframework,dc=org
spring.ldap.embedded.port=8389


Then, you will have created a test-server.LDIF file in the resources folder, as shown below:

dn: dc=springframework,dc=org
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: springframework

dn: ou=roles,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: roles

dn: ou=people,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: people

dn: uid=admin,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Admin1
sn: Admin1
uid: admin
userPassword: admin


dn: uid=joy,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: joydip
sn: Kumar
uid: joy
userPassword: 123


#ROLES
dn: cROLE_USERER,ou=roles,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cnROLE_USERER
member: uid=joy,ou=people,dc=springframework,dc=org

dn: cROLE_n=ADMIN,ou=roles,dc=springframework,dc=org
objectclass: top
objectclass: groupOfNames
cnROLE_ADMININ
member: uid=admin,ou=people,dc=springframework,dc=org


Next, we need to update the configure method:

@Override
public void configure(AuthenticationManagerBuilder auth)
            throws Exception {
auth.ldapAuthentication()
  .userDnPatterns("uid={0},ou=people")
  .groupSearchBase("ou=roles")
  .contextSource().url("ldap://localhost:8389/dc=springframework,dc=org").and()
  .passwordCompare().passwordAttribute("userPassword");
    }


This is how it behaves in an application for all three Spring authentications of the same user and credentials:

Image title

Image title

Conclusion

Spring Security can be configured in a project based on how the user credentials are set up in the system. After reading this article, we hope you learned which method to use and when. 

Happy coding!

Find out how Waratek’s award-winning application security platform can improve the security of your new and legacy applications and platforms with no false positives, code changes or slowing your application.

Topics:
spring ,security ,java ,spring security ,authentication ,authorization ,passwords ,password configuration ,tutorial ,spring tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}