# 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:**

1. The user enters credentials (username/password).
    
2. The request is passed to `AuthenticationManager`.
    
3. `AuthenticationManager` delegates to **one or more authentication providers**.
    
4. If authentication is successful, the user gains access; otherwise, authentication fails.
    

### **🔹 Example: Configuring AuthenticationManager**

```java
@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**

```java
@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**

```java
@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**

```java
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}
```

### **🔹 Saving Encrypted Passwords to Database**

```java
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`:

```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**

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

### **🔹 Step 3: Create a Repository Interface**

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

### **🔹 Step 4: Implement UserDetailsService**

```java
@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**

```java
@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**](https://www.bits8byte.com) **for more hands-on tutorials!** 🚀 If you found this helpful, share it with others! 🔥

---
