How to Implement Simple Authentication in Spring Boot?


Spring Boot is widely acclaimed as a framework used for developing Java applications due to its reputation for simplicity and increased productivity. An essential consideration in numerous applications is the implementation of authentication, which guarantees that only authorized individuals can access specific resources.

In Spring Boot, incorporating authentication is both efficient and convenient by leveraging its built-in security features and libraries. This capability empowers developers to concentrate on the core business logic without needing to reinvent existing solutions.

Developers can ensure the security of their Spring Boot applications and protect sensitive data by following a few simple steps. These steps include implementing authentication in Spring Boot to establish a secure foundation for application development. By doing so, users will be required to authenticate themselves before accessing protected resources. This article explores the process of implementing simple authentication in Spring Boot, providing valuable insights into securing your applications effectively.

Spring Boot

Spring Boot, an open-source framework based on Java, serves as a reliable and user-friendly solution for effortlessly developing and deploying robust standalone applications.

Spring Boot aims to minimize configuration and boilerplate code, enabling developers to swiftly construct robust and scalable applications. With its opinionated approach and automatic setup capabilities, Spring Boot obviates the need for manual configuration and offers a harmonious environment for developing Spring-based applications.

This sentence showcases a wide range of features. It includes embedded servers, dependency management, and robust security options. With these offerings, it has become a popular choice for individuals looking to build microservices, web applications, and RESTful APIs.

Approaches

In Spring Boot, one can find several methods for implementing simple authentication. Let's explore three common approaches:

  • Using In-Memory Authentication

  • Using Database Authentication

  • Using LDAP Authentication

Using In-Memory Authentication

In this method, the application stores user credentials in its memory. To define user details like username, password, and roles, the implementation of UserDetailsService interface comes into play. During authentication, Spring Security compares the provided credentials with those saved in memory. Based on the match, it either grants or denies access to the user.

Algorithm

  • Create a configuration class implementing the UserDetailsService interface.

  • Define user details (username, password, roles) within the configuration class.

  • During authentication, Spring Security compares provided credentials with the in-memory user details.

  • Grant or deny access based on the match.

Example

//pom.xml
<dependencies>
   <!-- Other dependencies -->
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
   </dependency>
</dependencies>
// WebSecurityConfigurerAdapter.java
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.
builde
rs.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.
HttpSecu
rity;
import org.springframework.security.config.annotation.web.configuration.
Ena
bleWebSecurity;
import org.springframework.security.config.annotation.web.configuration.
Web
SecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()
            .antMatchers("/admin").hasRole("ADMIN")
            .antMatchers("/user").hasRole("USER")
            .anyRequest().authenticated()
            .and()
            .formLogin();
   }
}

Output

Using Database Authentication

With this approach, user credentials are stored in a database. A user entity is created, along with a repository to interact with the database. During authentication, Spring Security utilizes the UserDetailsService interface to load user details from the database, comparing them with the provided credentials to grant or deny access.

Algorithm

  • Create a user entity and define a repository to interact with the database.

  • Implement the UserDetailsService interface to load user details from the database.

  • During authentication, Spring Security retrieves user details from the database based on provided credentials.

  • Compare the retrieved credentials with the provided ones and grant or deny access accordingly.

Example

//pom.xml
<dependencies>
   <!-- Other dependencies -->
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
   </dependency>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
   </dependency>
   <!-- Add your database driver dependency -->
</dependencies>

// application.properties
spring.datasource.url=jdbc:<localhost:8080/hello>
spring.datasource.username=<user>
spring.datasource.password=<password>
spring.jpa.show-sql=true

//User.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
   private String username;
   private String password;
   private boolean enabled;

   // Getters and setters
   // Constructors
}

// UserDetailsService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.
UsernameNotFoundExcept
ion;
import org.springframework.stereotype.Service;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

   private UserRepository userRepository;

   @Autowired
   public UserDetailsServiceImpl(UserRepository userRepository) {
      this.userRepository = userRepository;
   }

   @Override
   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
      User user = userRepository.findByUsername(username)
            .orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));

      return new org.springframework.security.core.userdetails.User(
            user.getUsername(),
            user.getPassword(),
            user.isEnabled(),
            true,
            true,
            true,
            Collections.emptyList()
      );
   }
}

// UserRepository.java
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
   Optional<User> findByUsername(String username);
}

// WebSecurityConfigurerAdapter.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.
builde
rs.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.
HttpSecu
rity;
import org.springframework.security.config.annotation.web.configuration.
Ena
bleWebSecurity;
import org.springframework.security.config.annotation.web.configuration.
Web
SecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

   private UserDetailsServiceImpl userDetailsService;
   private PasswordEncoder passwordEncoder;

   @Autowired
   public SecurityConfig(UserDetailsServiceImpl userDetailsService, PasswordEncoder passwordEncoder) {
      this.userDetailsService = userDetailsService;
      this.passwordEncoder = passwordEncoder;
   }

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

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()
            .antMatchers("/admin").hasRole("ADMIN")
            .antMatchers("/user").hasAnyRole("ADMIN", "USER")
            .anyRequest().authenticated()
            .and()
            .formLogin();
   }
}

Output

Using LDAP Authentication

LDAP authentication is suitable when an LDAP server is used for user management. Spring Security integrates with the LDAP server, allowing authentication against it. Configuration involves specifying the LDAP server connection details, including host, port, and credentials. Additionally, a search base and filter are defined to locate user entries within the LDAP directory. Spring Security then verifies the provided credentials against the LDAP server for authentication.

Algorithm

  • Configure the connection details for the LDAP server, including host, port, and credentials.

  • Define a search base and filter to locate user entries within the LDAP directory.

  • During authentication, Spring Security verifies the provided credentials against the LDAP server.

  • Grant or deny access based on the authentication result.

Example

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.ldapAuthentication()
         .userDnPatterns("uid={0},ou=users")
         .groupSearchBase("ou=groups")
         .contextSource()
            .url("ldap://localhost:389/dc=mycompany,dc=com")
            .managerDn("cn=admin,dc=mycompany,dc=com")
            .managerPassword("admin");
   }

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()
         .antMatchers("/user").hasRole("USER")
         .anyRequest().authenticated()
         .and()
         .formLogin();
   }

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

Output

Conclusion

In this tutorial, implementing simple authentication in Spring Boot is essential for securing applications and ensuring that only authorized users can access protected resources. Whether utilizing in-memory authentication, database authentication, or LDAP authentication, Spring Boot provides convenient features through Spring Security to streamline the authentication process. By choosing the most suitable method and configuring the necessary components, developers can establish a robust authentication system to safeguard their applications and protect sensitive data from unauthorized access.

Updated on: 27-Jul-2023

626 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements