You are currently viewing Two-Factor Authentication with Spring Security

Two-Factor Authentication with Spring Security

Two-Factor Authentication (2FA) adds an extra layer of security to your application by requiring users to provide two different authentication factors. In this tutorial, we’ll implement Two-Factor Authentication in a Spring Boot application using Spring Security.

Prerequisites

  • Basic understanding of Spring Boot and Spring Security
  • JDK installed on your machine
  • Maven or Gradle installed

Step 1: Setup a Spring Boot Project

First, let’s create a new Spring Boot project. You can do this manually or use the Spring Initializr to generate a project with the required dependencies.

For Maven, add the following dependencies:

  • Spring Web
  • Spring Security
  • Thymeleaf (for simple web UI)

Here’s an example pom.xml for Maven:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

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

    <!-- Thymeleaf for simple UI -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
</dependencies>

Step 2: Create a Spring Security Configuration

Next, let’s create a Spring Security configuration class to configure our security settings.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/login", "/login-verify").permitAll()
                .anyRequest().authenticated()
            .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/2fa", true)
            .and()
                .logout().permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser(User.withUsername("user")
                .password("password")
                .roles("USER"));
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
}
  • configure(HttpSecurity http) method configures security rules. Here, we permit access to /login and /login-verify without authentication, and require authentication for all other requests. We also specify a custom login page /login and the default success URL as /2fa.
  • configure(AuthenticationManagerBuilder auth) method provides an in-memory user with username user and password password.
  • passwordEncoder() method configures a NoOpPasswordEncoder for simplicity (not recommended for production).

Step 3: Create Login and 2FA Pages

Let’s create Thymeleaf templates for the login and 2FA pages.

Create a file src/main/resources/templates/login.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
    <h1>Login</h1>
    <form action="/login" method="post">
        <div>
            <label for="username">Username:</label>
            <input type="text" id="username" name="username" required autofocus>
        </div>
        <div>
            <label for="password">Password:</label>
            <input type="password" id="password" name="password" required>
        </div>
        <button type="submit">Login</button>
    </form>
</body>
</html>

Create a file src/main/resources/templates/2fa.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>2FA Verification</title>
</head>
<body>
    <h1>Two-Factor Authentication</h1>
    <form action="/login-verify" method="post">
        <div>
            <label for="code">Enter 2FA Code:</label>
            <input type="text" id="code" name="code" required autofocus>
        </div>
        <button type="submit">Verify</button>
    </form>
</body>
</html>

Step 4: Create Controller

Now, let’s create a controller to handle login and 2FA verification.

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class AuthController {

    @GetMapping("/login")
    public String login() {
        return "login";
    }

    @GetMapping("/2fa")
    public String twoFactorAuth() {
        return "2fa";
    }

    @PostMapping("/login-verify")
    public String verify2FA() {
        // Here you would implement the logic to verify the 2FA code
        // For simplicity, we'll assume the code is correct
        return "redirect:/welcome";
    }

    @GetMapping("/welcome")
    public String welcome() {
        return "welcome";
    }
}

Step 5: Test the Application

Now you can run your Spring Boot application and access it at http://localhost:8080/login.

  1. Visit http://localhost:8080/login to see the login page.
  2. Enter user for the username and password for the password.
  3. Upon successful login, you will be redirected to the 2FA page.
  4. Enter any code (since we are not validating it in this example) and submit.
  5. You will be redirected to the /welcome page.

Summary

In this tutorial, we implemented Two-Factor Authentication (2FA) in a Spring Boot application using Spring Security. We created a custom login page, a 2FA verification page, and a simple controller to handle the authentication flow. In a real-world scenario, you would need to implement the logic to validate the 2FA code and enhance security practices.

Leave a Reply