Understanding Authentication in Spring Security
1️⃣ Introduction
Authentication is a fundamental aspect of application security. It ensures that only verified users can access protected resources. Without authentication, anyone could log in and access sensitive information.
Spring Security provides a powerful and flexible authentication mechanism, making it easy to manage user verification and secure login functionalities. This blog will cover how authentication works, different authentication providers, and how to implement a custom authentication system using Spring Security. 🚀
2️⃣ What is Authentication, and How Does Spring Security Handle It?
Authentication is the process of verifying a user's identity before granting access to a system.
🔹 Example: When you log into your email account, you enter a username and password. If your credentials are correct, you gain access; otherwise, you are denied.
Spring Security handles authentication by:
Intercepting login requests and checking credentials.
Comparing credentials with stored user data (in memory, database, etc.).
Granting access if the authentication is successful.
📌 Authentication: The process of verifying a user’s identity before allowing access to a system.
3️⃣ How Does AuthenticationManager Work?
Spring Security uses an AuthenticationManager to process authentication requests.
🔹 Authentication Flow:
The user enters credentials (username/password).
The request is passed to
AuthenticationManager.AuthenticationManagerdelegates to one or more authentication providers.If authentication is successful, the user gains access; otherwise, authentication fails.
🔹 Example: Configuring AuthenticationManager
@Bean
public AuthenticationManager authenticationManager(UserDetailsService userDetailsService) {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(new BCryptPasswordEncoder());
return new ProviderManager(authProvider);
}
📌 AuthenticationManager: The main component in Spring Security that manages authentication logic by delegating to authentication providers.
4️⃣ Custom Authentication Providers
Spring Security allows you to define custom authentication providers to implement specialized authentication logic.
🔹 Example: Authenticating users against an external API, LDAP, or multi-factor authentication system.
🔹 Creating a Custom Authentication Provider
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
if ("admin".equals(username) && "adminpass".equals(password)) {
return new UsernamePasswordAuthenticationToken(username, password, List.of(new SimpleGrantedAuthority("ROLE_ADMIN")));
}
throw new BadCredentialsException("Invalid credentials");
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
📌 AuthenticationProvider: A component in Spring Security that defines custom authentication logic.
5️⃣ Using a Database for Authentication (UserDetailsService)
Instead of hardcoding users, Spring Security allows storing user details in a database using UserDetailsService.
🔹 Implementing UserDetailsService with Database Authentication
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
return new org.springframework.security.core.userdetails.User(
user.getUsername(), user.getPassword(), Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
}
}
📌 UserDetailsService: A Spring Security interface used for retrieving user authentication details from a database or external service.
6️⃣ Password Encryption with BCrypt
Storing passwords in plain text is a security risk. Spring Security recommends using BCrypt for password encryption.
🔹 Encrypting Passwords with BCrypt
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
🔹 Saving Encrypted Passwords to Database
public void saveUser(String username, String password) {
String encryptedPassword = passwordEncoder().encode(password);
userRepository.save(new User(username, encryptedPassword));
}
📌 PasswordEncoder: A Spring Security interface for encrypting and verifying passwords.
📌 BCrypt: A strong hashing algorithm used for password security.
7️⃣ ✅ Hands-on: Implementing Authentication with a Custom UserDetailsService
🔹 Step 1: Add Spring Security & Database Dependencies
Add the following dependencies to pom.xml:
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
🔹 Step 2: Create a User Entity
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
}
🔹 Step 3: Create a Repository Interface
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
🔹 Step 4: Implement UserDetailsService
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
return new org.springframework.security.core.userdetails.User(
user.getUsername(), user.getPassword(), Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
}
}
🔹 Step 5: Configure Security with AuthenticationManager
@Bean
public AuthenticationManager authenticationManager(UserDetailsService userDetailsService) {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(new BCryptPasswordEncoder());
return new ProviderManager(authProvider);
}
Call to Action
Want to learn more about Spring Security? Follow me on Bits8Byte for more hands-on tutorials! 🚀 If you found this helpful, share it with others! 🔥






