Complete Spring Boot Security Guide - Learn modern security practices with JWT Authentication, Email Verification, Two-Factor Authentication (2FA), and SMTP integration.
- 🎯 About This Project
- ✨ Features
- 🛠️ Technologies
- 📋 Requirements
- ⚡ Quick Start
- 🔧 Configuration
- 📖 API Documentation
- 🏗️ Project Architecture
- 🔍 Detailed Code Review
- 📱 Postman Collection
- 🧪 Testing
- 📚 Learning Resources
- 🤝 Contributing
- 📄 License
This project is a complete guide for developers who want to learn Spring Boot Security implementation in modern web applications. It's designed for real-world scenarios and shows security best practices.
- How to implement JWT (JSON Web Token) authentication
- How to set up an Email verification system
- How to integrate Two-Factor Authentication (2FA)
- How to configure Spring Security
- How to send emails with SMTP
- How to integrate PostgreSQL database
- What are the Security best practices
- JWT Token-based Authentication
- Role-based Authorization (USER, ADMIN)
- Password Encryption (BCrypt)
- Session Management (Stateless)
- Email Verification system
- SMTP Configuration (Gmail)
- HTML Email Templates
- Email Token Management
- Google Authenticator integration
- QR Code generation
- TOTP (Time-based One-Time Password)
- Setup and Verification endpoints
- CORS configuration
- Input Validation
- Exception Handling
- Security Headers
- Spring Boot 3.5.3 - Framework
- Spring Security 6 - Security
- Spring Data JPA - ORM
- Spring Boot Mail - Email
- PostgreSQL - Database
- JWT (jjwt 0.11.5) - Token management
- Google Authenticator (1.5.0) - 2FA
- ZXing (3.5.1) - QR Code generation
- BCrypt - Password hashing
- Lombok - Boilerplate code reduction
- Maven - Dependency management
- H2 - Test database
- Postman - API testing
- Java 17+
- Maven 3.6+
- PostgreSQL 12+
- IDE (IntelliJ IDEA, Eclipse, VS Code)
- Gmail account
- App Password (for Gmail accounts with 2FA enabled)
git clone https://github.com/sogutemir/spring-boot-security.git
cd spring-boot-securityCREATE DATABASE securityExampleDB;spring:
datasource:
url: jdbc:postgresql://localhost:5432/securityExampleDB
username: your_username
password: your_password
mail:
username: your_email@gmail.com
password: your_app_passwordmvn clean install
mvn spring-boot:run- API Base URL:
http://localhost:8080 - Health Check:
http://localhost:8080/actuator/health
spring:
datasource:
url: jdbc:postgresql://localhost:5432/securityExampleDB
username: postgres
password: 123456
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: truejwt:
secret: myVeryLongSecretKeyThatIsAtLeast64BytesLongForHS512Algorithm
expiration: 86400000 # 24 hoursspring:
mail:
host: smtp.gmail.com
port: 587
username: your_email@gmail.com
password: your_app_password
properties:
mail:
smtp:
auth: true
starttls:
enable: truePOST /api/auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "securePassword123",
"firstName": "John",
"lastName": "Doe"
}POST /api/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "securePassword123"
}POST /api/auth/verify-email?token=your_verification_tokenPOST /api/auth/2fa/setup
Authorization: Bearer your_jwt_tokenPOST /api/auth/2fa/verify-setup
Authorization: Bearer your_jwt_token
Content-Type: application/json
{
"code": "123456"
}POST /api/auth/2fa/verify
Content-Type: application/json
{
"email": "user@example.com",
"code": "123456"
}src/main/java/com/babili/springbootsecurity/
├── 🚀 SpringBootSecurityApplication.java
├── ⚙️ config/
│ └── SecurityConfig.java
├── 🎮 controller/
│ ├── AuthController.java
│ └── TwoFactorAuthController.java
├── 📦 dto/
│ ├── AuthResponse.java
│ ├── LoginRequest.java
│ ├── RegisterRequest.java
│ ├── MessageResponse.java
│ ├── TwoFactorSetupResponse.java
│ └── TwoFactorVerificationRequest.java
├── 🗃️ entity/
│ ├── User.java
│ ├── Role.java
│ └── EmailVerificationToken.java
├── ❌ exception/
│ ├── GlobalExceptionHandler.java
│ ├── InvalidTokenException.java
│ ├── TokenExpiredException.java
│ └── UserAlreadyExistsException.java
├── 🗄️ repository/
│ ├── UserRepository.java
│ ├── EmailVerificationTokenRepository.java
│ └── CustomCredentialRepository.java
├── 🔒 security/
│ ├── AuthTokenFilter.java
│ ├── UserDetailsServiceImpl.java
│ └── UserPrincipal.java
├── ⚙️ service/
│ ├── AuthService.java
│ ├── UserService.java
│ ├── EmailService.java
│ ├── EmailVerificationService.java
│ ├── RegistrationService.java
│ └── TwoFactorAuthService.java
└── 🛠️ util/
└── JwtUtils.java
graph TD
A[User Registration] --> B[Validate Input]
B --> C[Hash Password]
C --> D[Save User to DB]
D --> E[Generate Verification Token]
E --> F[Send Verification Email]
F --> G[User Clicks Email Link]
G --> H[Verify Token]
H --> I[Activate Account]
graph TD
A[Login Request] --> B[Validate Credentials]
B --> C{2FA Enabled?}
C -->|No| D[Generate JWT]
C -->|Yes| E[Request 2FA Code]
E --> F[Verify 2FA Code]
F --> D[Generate JWT]
D --> G[Return Auth Response]
The SecurityConfig.java file contains the application's security configuration:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.disable())
.csrf(csrf -> csrf.disable())
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated())
.addFilterBefore(authenticationJwtTokenFilter(),
UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}The JwtUtils.java file manages JWT token operations:
@Component
public class JwtUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
@Value("${jwt.secret}")
private String jwtSecret;
@Value("${jwt.expiration}")
private int jwtExpirationMs;
public String generateJwtToken(Authentication authentication) {
UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal();
return Jwts.builder()
.setSubject(userPrincipal.getEmail())
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
}The EmailService.java file handles email sending operations:
@Service
public class EmailService {
private final JavaMailSender mailSender;
public void sendVerificationEmail(String to, String token) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(to);
helper.setSubject("Email Verification - Security Example App");
String verificationUrl = frontendUrl + "/verify-email?token=" + token;
String htmlContent = buildVerificationEmailContent(verificationUrl);
helper.setText(htmlContent, true);
mailSender.send(message);
} catch (MessagingException e) {
throw new RuntimeException("Failed to send verification email", e);
}
}
}The TwoFactorAuthService.java file manages 2FA operations:
@Service
public class TwoFactorAuthService {
private static final String ISSUER = "SecurityExampleApp";
private final GoogleAuthenticator gAuth;
public TwoFactorSetupResponse setupTwoFactor(String email) {
User user = userService.findByEmail(email);
GoogleAuthenticatorKey key = gAuth.createCredentials();
String secret = key.getKey();
// QR Code generation
String qrCodeUrl = GoogleAuthenticatorQRGenerator.getOtpAuthURL(
ISSUER, email, key);
return TwoFactorSetupResponse.builder()
.secret(secret)
.qrCodeUrl(qrCodeUrl)
.qrCodeImage(generateQRCodeImage(qrCodeUrl))
.build();
}
}The project includes a Spring_Boot_Security_API_Collection.postman_collection.json file. This collection contains the following tests:
- User Registration - New user registration
- Email Verification - Email verification
- User Login - User login
- 2FA Setup - Two-factor authentication setup
- 2FA Verification - Two-factor authentication verification
- Protected Endpoints - Protected endpoint tests
- Open Postman
- Click the Import button
- Select Upload Files option
- Choose the
Spring_Boot_Security_API_Collection.postman_collection.jsonfile - Click Import
mvn testmvn verify-
User Registration
- Use the
/api/auth/registerendpoint - Check your email
- Use the
-
Email Verification
- Click the link in the email or manually send the token
-
Login
- Use the
/api/auth/loginendpoint - Get the JWT token
- Use the
-
2FA Setup
- Use the
/api/auth/2fa/setupendpoint - Add the QR code to Google Authenticator
- Use the
-
2FA Login
- Try to login with a 2FA-enabled account
- Get the code from Google Authenticator
- JWT.io - JWT debugger and libraries
- RFC 7519 - JWT Specification
This is an open-source educational project. We welcome your contributions!
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- 🐛 Bug fixes
- ✨ New features
- 📚 Documentation improvements
- 🧪 Test coverage
- 🔧 Performance optimizations
- 🌐 Internationalization
This project is licensed under the MIT License. See the LICENSE file for details.
If this project helped you, please support it by giving it a ⭐!
- GitHub: @sogutemir
- LinkedIn: Sogut Emir
- Mail: muhammet.sogut@tubitak.gov.tr
For questions, you can open an issue or contact me via email: muhammet.sogut@tubitak.gov.tr
Happy Coding! 🚀
Enter the world of Spring Boot Security with this comprehensive project and become an expert in security topics for modern web applications!