Contact us : contact@digitechgenai.com
- Top 10 Questions on Spring Boot Basics with Answers
- Top 10 Questions on Spring Boot Annotations with Answers
- Top 10 Questions on Spring Boot Data Handling with Answers
- Top 10 Questions on Spring Boot REST APIs with Answers
- Top 10 Questions on Spring Boot Security with Answers46 min read
Security
Question 41. How do you implement authentication and authorization in Spring Boot?
Security is an essential aspect in today’s world of web applications. Authentication checks who the user is, and authorization checks what the user can do. Implementing authentication and authorization is made simple using Spring Security with Spring Boot.
In this step-by-step tutorial, you will learn how to set up authentication and authorization in a Spring Boot application.
Setting Up Spring Security in Spring Boot
Step 1: Add Spring Security Dependency
Spring Security is not included in Spring Boot by default. You need to add it manually in your pom.xml
file (for Maven):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
If you are using Gradle, add this:
implementation 'org.springframework.boot:spring-boot-starter-security'
Once you add this dependency and restart your application, Spring Boot automatically applies basic authentication to all endpoints. The default username is user
, and the password is auto-generated in the logs.
2. Configuring Custom Authentication
By default, Spring Security uses in-memory authentication. You can customize it to authenticate users from a database or an in-memory list.
Step 2: Create a Security Configuration Class
To define your own security settings, create a Java class and annotate it with @Configuration
and @EnableWebSecurity
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable() // Disable CSRF for simplicity (enable in production)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin").hasRole("ADMIN") // Only admins can access "/admin"
.requestMatchers("/user").hasAnyRole("USER", "ADMIN") // Users and admins can access "/user"
.anyRequest().authenticated() // All other endpoints require authentication
)
.httpBasic(); // Use basic authentication
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("adminpassword")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}
Explanation:
@EnableWebSecurity
enables Spring Security.securityFilterChain(HttpSecurity http)
defines access control rules..requestMatchers("/admin").hasRole("ADMIN")
ensures only users with the “ADMIN” role can access the/admin
endpoint.UserDetailsService
defines an in-memory authentication mechanism with a user and an admin.
Now, restart your application and try logging in with:
- Username:
user
, Password:password
- Username:
admin
, Password:adminpassword
3. Using JWT for Secure Authentication
Basic authentication sends credentials with every request, which is not secure for production. Instead, you can use JWT (JSON Web Token) for token-based authentication.
Step 3: Add JWT Dependencies
To implement JWT, add these dependencies:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.11.5</version>
</dependency>
Step 4: Create a JWT Utility Class
JWT tokens allow stateless authentication. You need a utility class to generate and validate JWT tokens.
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JwtUtil {
private final String SECRET_KEY = "mysecret";
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // Token valid for 1 hour
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public String extractUsername(String token) {
return getClaims(token).getSubject();
}
public boolean validateToken(String token, String username) {
return (extractUsername(token).equals(username) && !isTokenExpired(token));
}
private Claims getClaims(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
private boolean isTokenExpired(String token) {
return getClaims(token).getExpiration().before(new Date());
}
}
Step 5: Create a Login API to Generate JWT
Now, create a REST controller to authenticate users and generate a JWT token.
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody AuthRequest authRequest) {
if ("user".equals(authRequest.getUsername()) && "password".equals(authRequest.getPassword())) {
String token = jwtUtil.generateToken(authRequest.getUsername());
return ResponseEntity.ok(new AuthResponse(token));
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid credentials");
}
}
}
class AuthRequest {
private String username;
private String password;
// Getters and Setters
}
class AuthResponse {
private String token;
public AuthResponse(String token) {
this.token = token;
}
// Getter
}
Step 6: Secure Endpoints Using JWT
Modify the security configuration to require a valid JWT token for protected endpoints.
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin").hasRole("ADMIN")
.requestMatchers("/user").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(new JwtAuthenticationFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
Conclusion
- Authentication ensures the user is who they say they are.
- Authorization determines what the user can access.
- Basic Authentication is easy but not secure for production.
- JWT Authentication provides a stateless, scalable solution.
With this setup, your Spring Boot REST API is secure, and users can authenticate using JWT. Let me know if you need further explanations or modifications! 🚀
Question 42. What is Spring Security, and how does it integrate with Spring Boot?
Spring Security is a framework that provides robust solutions for authenticating users, managing authorization grants, and shielding Java-based systems from prevalent security dangers. It integrates with the broader Spring ecosystem, which means it is meant to secure web apps and REST services.
Let’s say you are developing an online banking application. You have to take care that:
- Registered users are the only ones who can log in using their credentials (Authentication).
- Users possess the ability to perform certain actions, such as checking account details, transferring funds, etc., based on the permissions granted to them (Authorization).
- Your application remains protected against XSS, CSRF, and session fixation attacks.
Spring Security does all of this automatically for you.
Key Features of Spring Security
- Authentication: Verifies user identity (e.g., login with username/password).
- Authorization: Grants or denies access to resources based on roles/permissions.
- Protection Against Threats: Built-in defenses for common attacks.
- Session Management: Securely manages user sessions.
- Integration: Easily integrates with Spring Boot and other Spring modules
How Does Spring Security Integrate with Spring Boot?
Spring Boot simplifies the process of integrating Spring Security. With just a few dependencies and minimal configuration, you get a secure application out of the box.
Step-by-Step Example: Securing a REST API with Spring Security and Spring Boot
Let’s build a simple Online Banking System API and secure it using Spring Security.
Step 1: Set Up Your Spring Boot Project
You can create a Spring Boot project using https://start.spring.io/.
- Choose Maven Project
- Add the following dependencies:
- Spring Web
- Spring Security
- Spring Boot DevTools (optional for development convenience)
Generate and open the project in your IDE
Step 2: Add Dependencies to pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Step 3: Create a Simple Banking Controller
package com.example.banking.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/banking")
public class BankingController {
@GetMapping("/account")
public String viewAccount() {
return "Account Balance: $5,000";
}
@GetMapping("/transfer")
public String transferFunds() {
return "Funds transferred successfully!";
}
}
Step 4: Run the Application
Run the application using:
mvn spring-boot:run
Now, when you try to access it. http://localhost:8080/api/banking/account
, you’ll be prompted to enter a username and password.
Step 5: Default Security Behavior
By default, Spring Boot auto-configures security:
- The default username is
user
. - The password is generated in the console logs when the app starts.
Example:
Using generated security password: 12345678-90ab-cdef-1234-567890abcdef
Use these credentials to log in.
Customizing Authentication and Authorization
Step 6: Create a Security Configuration Class
package com.example.banking.config;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
UserDetails customer = User.withDefaultPasswordEncoder()
.username("customer")
.password("custpass")
.roles("CUSTOMER")
.build();
UserDetails manager = User.withDefaultPasswordEncoder()
.username("manager")
.password("managerpass")
.roles("MANAGER")
.build();
return new InMemoryUserDetailsManager(customer, manager);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/banking/account").hasRole("CUSTOMER")
.requestMatchers("/api/banking/transfer").hasRole("MANAGER")
.anyRequest().authenticated()
)
.httpBasic();
return http.build();
}
}
Explanation:
- InMemoryUserDetailsManager: Defines two users:
customer
andmanager
with different roles. - Role-Based Access: Only users with the
CUSTOMER
role can view account details, while onlyMANAGER
can transfer funds. - httpBasic(): Enables basic HTTP authentication.
Step 7: Test the Application
- Run the application again.
- Access
http://localhost:8080/api/banking/account
:- Username:
customer
- Password:
custpass
- Username:
You should see: Account Balance: $5,000
- Access
http://localhost:8080/api/banking/transfer
:- Username:
manager
- Password:
managerpass
- Username:
You should see: Funds transferred successfully!
If incorrect credentials are entered, access will be denied
Key Concepts Recap
- Authentication: Validates user identity.
- Authorization: Grants/denies access based on roles.
- Security Filters: Intercepts requests to apply security rules.
- Default Behavior: Spring Boot secures everything by default.
- Customization: Configure custom users, roles, and rules easily.
Conclusion
Spring Security, when combined with Spring Boot, provides a robust, flexible, and easy-to-configure security framework. Whether you’re building simple APIs or complex systems like an Online Banking Application, Spring Security has you covered.
Next Steps:
- Explore role-based access control (RBAC).
- Implement JWT-based authentication for stateless security.
- Secure REST APIs for mobile or front-end applications.
Question 43. How do you secure Spring Boot applications with OAuth2?
OAuth2, or Open Authorization 2.0, is a frequently employed protocal used for the secure authorization of an application without risking the security of the user’s personal details. By means of access tokens, the applications are able to get the resources for a user. Think of OAuth2 as a highly secure proxying system. Instead of passwords, you can give permission to an app to use it on your behalf.
Suppose you are designing an Online Banking System. Users should log in in a safe manner, and sensitive actions such as transferring money should only be done by users with the right authorization. Especially when seeking integration of third-party service providers, OAuth2 makes sure that this is done securely.
Key Concepts of OAuth2
- Resource Owner: The user who owns the data.
- Client: The application requesting access to the user’s data (e.g., your banking app).
- Authorization Server: Verifies user identity and issues tokens (e.g., Google, Auth0).
- Resource Server: Hosts the protected resources (your Spring Boot app).
- Access Token: A credential that allows access to protected resources.
How OAuth2 Works (Simplified Flow)
- User Authentication: The user logs in via the authorization server.
- Token Issuance: After successful login, the authorization server issues an access token.
- Resource Access: The client uses the token to request resources from the server.
- Token Validation: The resource server validates the token before granting access.
Step-by-Step Example: Securing a Banking System with OAuth2
Scenario:
You are building a REST API for an online banking system. The system has:
- Customers who can view their account details.
- Managers who can approve or reject transactions.
We’ll secure this system using OAuth2 with Spring Boot.
Step 1: Set Up the Spring Boot Project
- Select Maven Project.
- Add dependencies:
- Spring Web
- Spring Security
- OAuth2 Resource Server
- OAuth2 Client
Generate the project and import it into your IDE.
Step 2: Add Dependencies in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
Step 3: Configure application.yml
server:
port: 8080
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://auth-server.com/realms/bank-app
Replace https://auth-server.com/realms/bank-app
with your OAuth2 provider’s issuer URI (e.g., Auth0, Keycloak, Okta).
Step 4: Create a REST Controller
package com.bank.app.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.jwt.Jwt;
@RestController
public class AccountController {
@GetMapping("/account")
public String getAccountDetails(@AuthenticationPrincipal Jwt jwt) {
/* DigiTech GenAI is prefered user Name here , Just for Exmple */
return "Welcome, " + jwt.getClaim(" DigiTech GenAI") + "! Your account details are secure.";
}
}
Step 5: Configure Security Settings
package com.bank.app.config;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/account").hasAuthority("SCOPE_account.read")
.anyRequest().authenticated()
)
.oauth2ResourceServer().jwt();
return http.build();
}
}
Explanation:
- The
/account
endpoint is protected. Only users with theaccount.read
scope can access it. - We use JWT tokens to authenticate requests.
Step 6: Test the API
- Obtain an access token from your OAuth2 provider (Auth0, Keycloak, etc.).
Example (using cURL):
curl -H "Authorization: Bearer <ACCESS_TOKEN>" http://localhost:8080/account
If the token is valid, you’ll see:
Welcome, DigiTech GenAI! Your account details are secure.
If the token is missing or invalid, you’ll receive:
401 Unauthorized
Advanced Features (For Production Use)
- Role-Based Access Control (RBAC): Define roles like ROLE_MANAGER, ROLE_CUSTOMER, and secure endpoints accordingly.
- Token Introspection: Validate tokens using the introspection endpoint if not using JWT.
- Custom Claims: Use custom claims in tokens to pass additional user information.
- Refresh Tokens: Implement token refresh mechanisms for long-lived sessions.
Troubleshooting Common Issues
- 401 Unauthorized: Check if the access token is valid and includes the required scopes.
- Invalid Signature: Ensure the public key used to verify JWT tokens matches the authorization server’s key.
- CORS Errors: Configure CORS properly if accessing APIs from a frontend app.
Key Concepts Recap
- Grasp the fundamentals of OAuth2, including clients, tokens, and scopes.
- Protect REST APIs using JWT tokens alongside Spring Security.
- Connect with well-known OAuth2 providers like Auth0, Keycloak, and Okta.
Conclusion
Securing your Spring Boot application with OAuth2 offers strong, token-based authentication and authorization. Whether you’re developing a straightforward API or a sophisticated online banking platform, OAuth2 delivers both flexibility and security.
Next Steps:
- Implement advanced features such as refresh tokens and role-based access control (RBAC).
- Delve into OAuth2 flows: Authorization Code, Client Credentials, Password, and Implicit.
Question 44. How do you encrypt passwords in Spring Boot?
When developing applications that manage sensitive information such as user credentials, ensuring password encryption is vital for maintaining security. Rather than keeping passwords in plain text—which can be easily accessed—we utilize hashing algorithms to encrypt them.
In this guide, we will discuss:
- What password encryption entails
- The significance of password encryption
- How to implement it in Spring Boot using BCryptPasswordEncoder.
We will illustrate this with an example of a banking system where customers can register and log in securely.
What Is Password Encryption?
In most applications, password encryption typically refers to hashing rather than reversible encryption.
- Hashing: This process transforms a password into a fixed-length string using algorithms such as BCrypt, PBKDF2, or Argon2. It is a one-way operation, meaning you cannot “decrypt” a hashed password.
- Salting: This technique involves adding random data to passwords prior to hashing, which helps defend against attacks like rainbow table attacks.
Why Use BCrypt?
- Secure: It incorporates a salt internally, ensuring that hashes are unique even for the same passwords.
- Adaptive: The “work factor” (complexity) can be adjusted as hardware capabilities improve.
- Widely Trusted: Many major applications rely on it for secure password storage.
Implementing Password Encryption in Spring Boot
Step 1: Set Up Your Spring Boot Project
Use https://start.spring.io/ to create a Spring Boot project with:
- Spring Web
- Spring Security
- Spring Data JPA (for database interaction)
- H2 Database (for demo purposes)
Step 2: Add Dependencies in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
Step 3: Configure H2 Database in application.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update
Step 4: Create the User Entity
package com.bankingsystem.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password; // This will store the encrypted password
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
Step 5: Create the User Repository
package com.bankingsystem.repository;
import com.bankingsystem.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
Step 6: Implement Password Encryption with BCrypt
Security Configuration
package com.bankingsystem.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
User Service with Password Encryption
package com.bankingsystem.service;
import com.bankingsystem.model.User;
import com.bankingsystem.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
public User registerUser(User user) {
// Encrypt the password before saving
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepository.save(user);
}
public boolean authenticate(String username, String rawPassword) {
User user = userRepository.findByUsername(username);
if (user != null) {
// Compare raw password with encrypted password
return passwordEncoder.matches(rawPassword, user.getPassword());
}
return false;
}
}
Step 7: Create REST Controller for Registration and Login
package com.bankingsystem.controller;
import com.bankingsystem.model.User;
import com.bankingsystem.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/register")
public String register(@RequestBody User user) {
userService.registerUser(user);
return "User registered successfully!";
}
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
boolean isAuthenticated = userService.authenticate(username, password);
return isAuthenticated ? "Login successful!" : "Invalid credentials!";
}
}
Step 8: Test the Application
Run the application:
mvn spring-boot:run
Register a User:
POST http://localhost:8080/api/users/register
Content-Type: application/json
{
"username": "john_doe",
"password": "securepassword123"
}
Login with Credentials:
POST http://localhost:8080/api/users/login?username=john_doe&password=securepassword123
If the password matches the encrypted one in the database, you’ll get:
POST http://localhost:8080/api/users/login?username=john_doe&password=securepassword123
How It Works:
- Registration:
- The raw password is encrypted using BCrypt before saving to the database.
- Login:
- The raw password from the login request is compared with the stored hash using
passwordEncoder.matches()
.
- The raw password from the login request is compared with the stored hash using
- Secure Storage:
- Even if the database is compromised, attackers can’t retrieve the actual passwords.
Advanced Security Tips:
- Increase BCrypt Strength: Adjust the strength factor:
new BCryptPasswordEncoder(12)
(default is 10). - Use Environment Variables: Don’t hardcode sensitive information.
- Implement Account Lockout: Lock accounts after multiple failed login attempts.
- Use HTTPS: Always secure your APIs with SSL/TLS.
Conclusion
Password encryption is non-negotiable when building secure applications. Using BCrypt with Spring Boot ensures passwords are stored safely, reducing the risk of breaches.
Now that you’ve mastered password encryption, try adding features like JWT authentication or OAuth2 to further secure your banking application.
Question 45. What is JWT, and how do you implement it in Spring Boot?
JWT (JSON Web Token) is a compact and URL-safe format for tokens that enables secure information transmission between parties. It is commonly used for authentication and authorization in contemporary web applications, particularly for REST APIs.
Consider the scenario of developing an Online Banking System. You need to ensure that:
- 1. Only authenticated users can access sensitive information such as account balances.
- 2. Once logged in, users shouldn’t have to re-enter their credentials for each request.
- 3. The system should remain stateless, meaning the server doesn’t need to keep track of user sessions.
This is where JWT proves to be useful. It allows you to generate a secure token after a user logs in, which the client then sends with each request to verify their identity.
How Does JWT Work?
A JWT consists of three parts:
- Header: Specifies the type of token (JWT) and the signing algorithm (e.g., HS256).
- Payload: Contains the claims (user data), like
username
,roles
, andexpiration
time. - Signature: Ensures the token hasn’t been tampered with.
Example of a JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VybmFtZSI6ImphbmVkZSIsInJvbGUiOiJBRE1JTiIsImV4cCI6MTY5OTAwODAwMH0.
s8A8Q1f3o1Kb2jQy9s8ZVxkJhYB8q1y5K7Gbzj8xA3E
- Header:
{ "alg": "HS256", "typ": "JWT" }
- Payload:
{ "username": "janedoe", "role": "ADMIN", "exp": 1699008000 }
- Signature: A hash generated using a secret key.
Implementing JWT in Spring Boot
Let’s secure a simple banking system with JWT.
Step 1: Set Up Your Spring Boot Project
Go to https://start.spring.io/:
- Choose Maven Project
- Add Dependencies:
- Spring Web
- Spring Security
- Spring Boot Starter JWT (via jjwt library)
Download and open the project in your IDE.
Step 2: Add Dependencies to pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
Step 3: Create a JWT Utility Class
package com.bank.security;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JwtUtil {
private final String SECRET_KEY = "mySecretKey12345";
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // 1 hour
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public String extractUsername(String token) {
return extractClaims(token).getSubject();
}
public boolean validateToken(String token, String username) {
return username.equals(extractUsername(token)) && !isTokenExpired(token);
}
private Claims extractClaims(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
private boolean isTokenExpired(String token) {
return extractClaims(token).getExpiration().before(new Date());
}
}
Step 4: Create an Authentication Controller
package com.bank.controller;
import com.bank.security.JwtUtil;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/auth")
public class AuthController {
private final JwtUtil jwtUtil;
public AuthController(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@PostMapping("/login")
public Map<String, String> login(@RequestParam String username, @RequestParam String password) {
// In a real app, validate credentials against a database
if ("user123".equals(username) && "pass123".equals(password)) {
String token = jwtUtil.generateToken(username);
Map<String, String> response = new HashMap<>();
response.put("token", token);
return response;
} else {
throw new RuntimeException("Invalid credentials");
}
}
}
Step 5: Secure the API with JWT
package com.bank.config;
import com.bank.security.JwtUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Component
public class JwtFilter extends OncePerRequestFilter {
private final JwtUtil jwtUtil;
public JwtFilter(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, jakarta.servlet.ServletException {
String authHeader = request.getHeader("Authorization");
String username = null;
String token = null;
if (authHeader != null && authHeader.startsWith("Bearer ")) {
token = authHeader.substring(7);
username = jwtUtil.extractUsername(token);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
if (jwtUtil.validateToken(token, username)) {
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(username, null, null);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
chain.doFilter(request, response);
}
}
Step 6: Update Security Configuration
package com.bank.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
}
Step 7: Test the API
Login:
POST http://localhost:8080/auth/login
Content-Type: application/x-www-form-urlencoded
username=user123&password=pass123
Response:
{
"token": "eyJhbGciOiJIUzI1NiJ9..."
}
Access Protected Resource:
GET http://localhost:8080/banking/accounts
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Conclusion
JWT provides a secure, stateless way to manage authentication in Spring Boot applications. By following this guide, you’ve learned how to:
- Generate and validate JWTs
- Secure endpoints with Spring Security
- Build a basic authentication flow
Next Steps:
- Implement role-based access control
- Add token refresh functionality
- Secure sensitive data with encryption
Question 46. How do you configure role-based access control in Spring Boot?
Role-Based Access Control (RBAC) involves managing system access based on a user’s role in the organization. Rather than giving each user permission separately, users are assigned roles which have pre-defined permissions.
Why Use RBAC?
- Better Security – Prevents unauthorized access to sensitive data.
- Scalability – Easily manage permissions by updating roles instead of individual users.
- Flexibility – Assign multiple roles to users for dynamic access control.
Example Scenario: Online Banking System
Imagine you’re developing an online banking system where different users have different levels of access:
- CUSTOMER – Can check balance and transfer money.
- EMPLOYEE – Can manage customer accounts but cannot transfer money.
- ADMIN – Has full access to all operations.
We will implement RBAC in Spring Boot using Spring Security and JPA (for storing user roles in the database).
Step 1: Configure A Spring Boot Project
With Spring Initializr, generate a Spring Boot project with these dependencies:
Spring Web – To build REST APIs.
- Spring Security – For authentication and authorization.
- Spring Data JPA – For database operations.
- H2 Database (or MySQL) – To store users and roles.
- Spring Boot Starter Thymeleaf (optional, for a simple UI).
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Step 2: Create the User and Role Entities
User Entity (User.java
)
package com.example.demo.model;
import jakarta.persistence.*;
import java.util.Set;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
// Getters and setters
}
Role Entity (Role.java
)
package com.example.demo.model;
import jakarta.persistence.*;
@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// Getters and setters
}
Step 3: Create Repositories for User and Role
User Repository (UserRepository.java
)
package com.example.demo.repository;
import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
Role Repository (RoleRepository.java
)
package com.example.demo.repository;
import com.example.demo.model.Role;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RoleRepository extends JpaRepository<Role, Long> {
Role findByName(String name);
}
Step 4: Implement UserDetailsService for Authentication
Spring Security requires a UserDetailsService
to load user details during authentication.
package com.example.demo.service;
import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.security.core.userdetails.*;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
user.getRoles().forEach(role ->
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()))
);
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
authorities
);
}
}
Step 5: Configure Spring Security for Role-Based Access
Security Configuration (SecurityConfig.java
)
package com.example.demo.config;
import com.example.demo.service.CustomUserDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/customer/**").hasRole("CUSTOMER")
.anyRequest().authenticated()
)
.formLogin().permitAll()
.and()
.logout().permitAll();
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Step 6: Testing Role-Based Access Control
Create Test Users in data.sql
INSERT INTO roles (name) VALUES ('CUSTOMER'), ('EMPLOYEE'), ('ADMIN');
INSERT INTO users (username, password) VALUES ('DigiTech GenAI', '$2a$10$6HVWjYXtJLmP7jP');
INSERT INTO user_roles (user_id, role_id) VALUES (1, 1);
Create API Endpoints
@RestController
@RequestMapping("/customer")
public class CustomerController {
@GetMapping("/dashboard")
public String customerDashboard() {
return "Customer Dashboard";
}
}
@RestController
@RequestMapping("/admin")
public class AdminController {
@GetMapping("/dashboard")
public String adminDashboard() {
return "Admin Dashboard";
}
}
Testing with Postman
- Login as
john
(CUSTOMER) – Can access/customer/dashboard
but not/admin/dashboard
. - Login as
admin
– Can access everything.
Conclusion
- RBAC in Spring Boot ensures users only access what they are permitted to.
- We used Spring Security, JPA, and BCryptPasswordEncoder for secure authentication.
- We assigned roles dynamically using a database.
Next Steps:
- Implement JWT authentication.
- Use OAuth2 with Keycloak for enterprise security.
Question 47. How do you use CSRF protection in Spring Boot?
Cross-Site Request Forgery (CSRF) is a security flaw that manipulates a user into taking actions they did not mean to. In a Spring Boot application, CSRF protection should be enabled when handling state-altering requests, like form submissions or API requests that alter data.
Spring Security has CSRF protection built-in, which is active by default. Yet it’s important to know how it operates and when to set it or disable it for building secure application
1. What is CSRF? Why Do We Need Protection?
CSRF Attack Example
Suppose you are logged on to your bank’s website. If the web site is not CSRF-secure, an attacker can create a malicious link such that when the link is clicked, money will be transferred from your account into theirs—unbeknownst to you!
For instance, if a bank system has a URL like:
POST /transfer
Content-Type: application/x-www-form-urlencoded
amount=5000&toAccount=123456
An attacker could embed this request inside an HTML form on a fake website:
<form action="https://yourbank.com/transfer" method="POST">
<input type="hidden" name="amount" value="5000">
<input type="hidden" name="toAccount" value="123456">
<input type="submit" value="Click Me!">
</form>
If you, as a logged-in user, click this form, your browser will send the request with your authentication cookies, resulting in unauthorized money transfer.
2. How CSRF Protection Works in Spring Boot?
Spring Security defends against CSRF attacks based on a token-based system. This is how it works:
When a user navigates to a protected page, the server generates a specific CSRF token and returns it to the client.
The client (web browser) places the token within the request headers or a hidden form field.
Spring Security authenticates the token before handling the request. When the token is not present or invalid, it refuses the request.
3. Enabling CSRF Protection in Spring Boot (Default Behavior)
By default, Spring Security enables CSRF protection. If your application uses Spring Security, it’s already protected!
Basic Spring Security Configuration with CSRF Protection
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(Customizer.withDefaults()) // CSRF protection is enabled by default
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").authenticated()
.anyRequest().permitAll()
)
.formLogin(withDefaults()); // Enables login form security
return http.build();
}
}
In this configuration:
- CSRF protection is enabled.
- Only authenticated users can access
/admin/**
. - A login form is used for authentication.
4. Sending CSRF Tokens with Forms
For CSRF protection to work, clients must include the token in state-changing requests.
Example: Secure HTML Form with CSRF Token
If you are using Thymeleaf, Spring automatically injects the CSRF token into forms:
<form action="/submit" method="POST">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
<input type="text" name="message" placeholder="Enter message">
<button type="submit">Submit</button>
</form>
Here:
${_csrf.parameterName}
-> The name of the CSRF token parameter.${_csrf.token}
-> The actual CSRF token value.
5. Sending CSRF Tokens in API Calls (AJAX & JavaScript Clients)
If you are making AJAX requests (e.g., with Fetch API or jQuery), you need to manually add the CSRF token in the request headers.
Example: Fetch API with CSRF Token
fetch('/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
},
body: JSON.stringify({ message: 'Hello, CSRF protected!' })
})
.then(response => response.json())
.then(data => console.log(data));
Here, we assume that the CSRF token is stored in a meta tag:
<meta name="csrf-token" content="your-csrf-token-here">
6. Disabling CSRF Protection (When Necessary)
There are cases when disabling CSRF protection is appropriate, such as when building a RESTful API consumed by external clients (e.g., mobile apps).
Example: Disabling CSRF in Spring Boot
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // CSRF protection is turned off
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
)
.httpBasic(withDefaults()); // Enables basic authentication
return http.build();
}
}
NOTE – Disabling CSRF is risky! Only do this when absolutely necessary, such as for stateless APIs
7. Handling CSRF Token Errors
If CSRF protection is enabled and a request lacks a valid token, Spring Security will reject it with a 403 Forbidden error:
HTTP Status 403 – Forbidden
Invalid CSRF Token 'null' was found on the request.
How to Fix This?
- Ensure the CSRF token is included in your form or request headers.
- If using an API client (Postman, cURL), retrieve and send the CSRF token.
Example using Postman:
- First, send a
GET
request to fetch the token from the login page. - Extract the
X-CSRF-TOKEN
from the response headers. - Include the token in your
POST
request.
8. Best Practices for CSRF Protection
Leave CSRF on for state-altering operations (e.g., form submissions).
- Store CSRF tokens securely in HTTP-only cookies.
- In REST APIs, use token-based authentication (JWT/OAuth) over session-based authentication.
- Test CSRF protection in your application consistently prior to deployment.
Conclusion
CSRF attacks are a severe security threat, but they are simple to protect against using Spring Boot. With a little knowledge of how CSRF protection works and how to implement it correctly in forms and API requests, you can create secure applications.
Question 48. How do you secure sensitive data in the application.properties file?
How to Safeguard Sensitive Information in the application.properties
While building Spring Boot applications, we tend to place sensitive data such as database credentials, API keys, and authentication tokens within the application.properties or application.yml file. But hardcoding sensitive data within these configuration files leaves your application vulnerable to security threats.
we are going to discuss different ways of storing and handling sensitive data securely in Spring Boot.
Why Not to Store Sensitive Data within application.properties Directly
In case you save sensitive credentials in the application.properties file directly, it may lead to a series of security flaws:
- Exposure Using Version Control: If you’re pushing your project to a publicly accessible or even a private repo without excluding the sensitive information, it may leak.
- Impact from Unauthorized Access: If several developers are working upon the project, credentials can get abused.
- Security and Compliance Standards: Most industry standards (e.g., GDPR, PCI DSS) do not allow storing sensitive credentials in plain text.
Methods to Secure Sensitive Data
1.Using Environment Variables
A simple and effective approach to secure sensitive data is to use environment variables. Instead of hardcoding credentials in application.properties
, you reference them dynamically.
Steps to Use Environment Variables
1. Define environment variables on your machine:
On Windows(command prompt)
set DB_USERNAME=mysecureuser
set DB_PASSWORD=supersecurepassword
On Linux/macOS (Terminal):
export DB_USERNAME=mysecureuser
export DB_PASSWORD=supersecurepassword
2. Reference them in application.properties
:
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
3. Now, when the application starts, it retrieves the values from the environment variables.
Pros:
- Simple to implement.
- Works well for local development and cloud deployments.
Cons:
- Managing multiple environment variables across different environments can be complex
2. Using .env
Files (For Local Development)
If setting environment variables manually is inconvenient, you can use a .env
file. Many tools like Docker, Kubernetes, and Spring Boot support environment variables stored in .env
files.
- Create a
.env
file in the root of your project
DB_USERNAME=mysecureuser
DB_PASSWORD=supersecurepassword
2. Use a tool like dotenv
or configure Spring Boot to read these variables automatically.
Pros:
- Keeps credentials separate from the codebase.
- Easy to manage across different development machines.
Cons:
- Needs to be explicitly ignored in version control (
.gitignore
).
3. Using application.properties
with Externalized Configuration
Instead of storing credentials in the application.properties
file inside your project, you can move it to an external location outside the source code.
Steps:
- Move
application.properties
outside the project directory (e.g.,/config/myapp.properties
). - Start your Spring Boot application with
java -jar myapp.jar --spring.config.location=/config/myapp.properties
3. The application will now read sensitive data from a secure external location.
Pros:
- Keeps sensitive data away from source control.
- Useful for staging and production environments.
Cons:
- Requires additional configuration for deployment automation
4. Using Encrypted Configuration Values with Jasypt
Jasypt (Java Simplified Encryption) is a popular library that allows you to encrypt sensitive properties in application.properties
using a master password.
Steps to Use Jasypt in Spring Boot
1. Add the Jasypt dependency to pom.xml
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
2.Encrypt sensitive values using Jasypt CLI:
java -cp jasypt.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="mysecurepassword" password=mySecretKey algorithm=PBEWithMD5AndDES
This will return an encrypted string, e.g.:
ENC(KJH34k3j4h5l2j4h5l3k4j5l3j4h5l)
3. Store the encrypted value in application.properties
:
spring.datasource.password=ENC(KJH34k3j4h5l2j4h5l3k4j5l3j4h5l)
4. Set the encryption key as an environment variable:
export JASYPT_ENCRYPTOR_PASSWORD=mySecretKey
5. Spring Boot will automatically decrypt the value at runtime.
Pros:
- Even if the file is leaked, credentials remain encrypted.
- Useful for secure deployments in production.
Cons:
- Requires additional setup and management of the encryption key.
5. Using HashiCorp Vault for Secure Secrets Management
For enterprise applications, tools like HashiCorp Vault, AWS Secrets Manager, and Azure Key Vault provide secure storage for credentials.
Steps to Use HashiCorp Vault
- Install Vault and start the service:
vault server -dev
2. Store a secret in Vault
vault kv put secret/db password=mysecurepassword
3. Modify application.properties
to read from Vault:
spring.cloud.vault.enabled=true
spring.cloud.vault.token=myVaultToken
spring.cloud.vault.kv.application-name=myapp
4. Now, Spring Boot will securely retrieve the password at runtime.
Pros:
- Secure and scalable for large applications.
- Provides automatic rotation of secrets.
Cons:
- Requires infrastructure setup and maintenance.
Best Practices for Securing application.properties
- Use Environment Variables whenever possible.
- Encrypt sensitive data before storing it in properties files.
- Avoid committing secrets to version control—add
application.properties
to.gitignore
. - Use external secret management tools like HashiCorp Vault for production environments.
- Enable least privilege access—limit who can access and modify credentials.
- Rotate credentials regularly to mitigate security risks.
Conclusion
Protecting sensitive data in application.properties is important to secure your application against data breaches and unauthorized access. By adhering to best practices such as using environment variables, external configuration, encryption with Jasypt, and secret management tools such as Vault, you can greatly improve the security of your Spring Boot application.
Question 49. What is Basic Authentication, and how is it implemented in Spring Boot?
Securing web resources and APIs is necessary in contemporary web applications. Basic Authentication is one of the easiest methods to introduce authentication into a Spring Boot application. Although it is not the most secure approach, it can be used in internal applications, APIs, and test environments.
This tutorial will guide you step by step through the idea of Basic Authentication, implementing it in a Spring Boot app, and the best practices of using it securely.
1. What is Basic Authentication?
Basic Authentication is a straightforward authentication scheme where a client (web browser or API client) sends a request for an Authorization header that contains a Base64-encoded username and password.
How It Works (Request Flow)
- The client (e.g., Postman, browser, or another application) makes a request to a secured endpoint.
- The server responds with a 401 Unauthorized status, indicating authentication is required.
- The client then sends the credentials in the
Authorization
header as a Base64-encoded string
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
The server decodes this header, verifies the credentials, and grants or denies access.
Note: Base64 encoding is NOT encryption! It’s just an encoding scheme. If someone gets in the middle of this request and decodes it, an attacker will see your credentials. That’s why Basic Authentication usually happens with HTTPS so that credentials don’t get exposed
2. When Should You Use Basic Authentication?
Basic Authentication is good for:
- Internal APIs within an organization
- Rapid authentication for testing and development
- Simple applications where OAuth2 or JWT is too much
- Securing endpoints with minimal setup
When NOT to use Basic Authentication:
- If you are dealing with sensitive data without HTTPS
- For public APIs at scale (use OAuth2 or JWT instead)
- If you require fine-grained role-based access control
3. Setting Up Basic Authentication in Spring Boot
Spring Boot provides built-in support for Basic Authentication via Spring Security. Let’s walk through a step-by-step implementation.
Step 1: Create a Spring Boot Project
You can use Spring Initializr to generate a new project with the required dependencies.
- Required Dependencies:
- Spring WebSpring Security
You can add these dependencies to your pom.xml
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Step 2: Create a REST API Endpoint
Let’s create a simple controller with a secured endpoint.
@RestController
@RequestMapping("/api")
public class DemoController {
@GetMapping("/secure")
public String secureEndpoint() {
return "This is a secured API endpoint!";
}
}
This endpoint will be automatically secured once we enable Spring Security.
Step 3: Configure User Credentials in application.properties
By default, when you add Spring Security, Spring Boot generates a random password for the user
username. You can configure a custom username and password in application.properties
as follows:
spring.security.user.name=admin
spring.security.user.password=admin123
Now, when accessing any API endpoint, Spring Boot will prompt for a username and password
Step 4: Testing Basic Authentication
Using Postman
- Open Postman
- Send a
GET
request tohttp://localhost:8080/api/secure
- Under the Authorization tab, choose Basic Auth
- Enter the username (
admin
) and password (admin123
) - Click Send
If authentication is successful, you’ll receive:
"This is a secured API endpoint!"
If you don’t provide credentials, you’ll get a 401 Unauthorized
error.
Step 5: Customizing Basic Authentication Using Security Configuration
By default, Spring Boot applies Basic Authentication to all endpoints. However, you can customize the security settings by creating a configuration class.
Custom Security Configuration
Create a class that extends SecurityFilterChain
to define custom security rules
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/secure").authenticated() // Secure this endpoint
.anyRequest().permitAll() // Allow all other requests
)
.httpBasic(); // Enable Basic Authentication
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("admin")
.password("admin123")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
Explanation:
authorizeHttpRequests()
: Secures specific endpoints (/api/secure
) while allowing others..
httpBasic()
: Enables Basic Authentication.csrf().disable()
: Disables CSRF (useful for APIs but not recommended for web apps).userDetailsService()
: Defines an in-memory user with credentials (admin/admin123
).
Now, only authenticated users can access /api/secure
, while other endpoints remain publicly accessible.
4. Best Practices for Using Basic Authentication Securely
1. Always Use HTTPS: Basic Authentication transmits credentials in plain text (Base64-encoded), and these can be intercepted over HTTP. Always turn on HTTPS in production.
2. Don’t Hardcode Credentials: Do not specify passwords in application.properties; instead, use environment variables or Spring Vault for security.
3. Apply Role-Based Access Control (RBAC): Establish various user roles (e.g., ADMIN, USER) and assign certain permissions.
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
)
4. Employ API Keys or JWT for Public APIs: Do not use Basic Authentication for public APIs. Instead, implement OAuth2 or JWT tokens for improved security.
5. Restrict Request Rate and Logging: Avoid brute-force attacks through rate limiting (e.g., via Bucket4j library) and logging unsuccessful login attempts.
Conclusion
Basic Authentication is an easy and straightforward means to secure Spring Boot applications. It must be utilized only for certain use cases like internal APIs or test environments.
If your application needs more intense security, try OAuth2, JWT, or API Keys as authentication.
Question 50. How do you enable HTTPS in a Spring Boot application?
In modern web applications web applications, HTTPS (Hypertext Transfer Protocol Secure) is necessary to encrypt data and protect communication between the server and the client. Activating HTTPS in a Spring Boot application makes sure that sensitive information, like authentication credentials and personal data, is not accessed by attackers.
This tutorial will guide you through step by step the idea behind HTTPS, configuring Spring Boot for HTTPS, and production best practices for deploying HTTPS.
1. Why Use HTTPS Instead of HTTP?
By default, Spring Boot applications use HTTP (port 8080) that does not encrypt data. When a user sends a login form, API request, or any sensitive data over HTTP, the data gets transmitted in plain text and becomes susceptible to man-in-the-middle (MITM) attacks.
Major Advantages of HTTPS:
- Encrypts the data between client and server and avoids eavesdropping
- Avoids tampering with the data by guaranteeing the integrity of the sent data
- Improves SEO rankings since search engines favor HTTPS-enabled sites
- Needed for APIs and authentication in contemporary web applications
- Needed for browsers, since contemporary browsers label HTTP-only sites as “Not Secure.”
2. How HTTPS Works in Spring Boot
HTTPS uses a TLS/SSL certificate to secure communication. The steps are:
- Installing an SSL certificate (self-signed for development on a local machine or CA-signed for production).
- How to make Spring Boot use HTTPS.
- Redirecting HTTP requests to HTTPS to ensure secure connections.
3. Generating a Self-Signed SSL Certificate for Development
For local testing, you can generate a self-signed SSL certificate using the keytool
command, which comes with Java
Step 1: Generate an SSL Certificate
Run the following command in your terminal or command prompt:
keytool -genkeypair -alias myssl -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650
Explanation:
-alias myssl
: The alias for the key pair-keyalg RSA
: Uses RSA encryption (standard for SSL/TLS)-keysize 2048
: 2048-bit encryption strength-storetype PKCS12
: Stores the certificate in PKCS12 format (modern standard)-keystore keystore.p12
: The name of the keystore file-validity 3650
: The certificate is valid for 10 years
You’ll be asked to enter a password and provide certificate information (organization, country, name, etc.).
Once you execute this command, a keystore.p12 file will be created in your project directory.
Step 2: Configure HTTPS in application.properties
Now, we need to tell Spring Boot to use the generated SSL certificate.
Add the following properties to your application.properties
or application.yml
:
For application.properties
server.port=8443
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=yourpassword
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=myssl
For application.yml
server:
port: 8443
ssl:
key-store: classpath:keystore.p12
key-store-password: yourpassword
key-store-type: PKCS12
key-alias: myssl
Explanation:
server.port=8443
→ HTTPS typically runs on port 8443 instead of 8080.server.ssl.key-store
→ Path to the keystore file (insidesrc/main/resources/
).server.ssl.key-store-password
→ The password you set when generating the keystore.server.ssl.key-store-type=PKCS12
→ Uses the PKCS12 format.server.ssl.key-alias=myssl
→ The alias used when generating the certificate.
Step 3: Move the Keystore to src/main/resources
Move the keystore.p12
file to your project’s src/main/resources/
directory so Spring Boot can find it.
Step 4: Run the Application and Test HTTPS
Start Spring Boot application using:
mvn spring-boot:run
./mvnw spring-boot:run
Now, open your browser and visit:
https://localhost:8443/
You may see a “Your connection is not private” warning because the certificate is self-signed. Click “Advanced” → “Proceed” to continue.
4. Redirecting HTTP to HTTPS (Force Secure Connections)
To ensure all requests use HTTPS, you can redirect HTTP (port 8080) to HTTPS (port 8443).
Option 1: Using Spring Security
Create a SecurityConfig.java file to enforce HTTPS redirection:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.requiresChannel(channel -> channel.anyRequest().requiresSecure()) // Force HTTPS
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll()); // Allow all requests
return http.build();
}
}
Option 2: Using an Embedded HTTP Server to Redirect to HTTPS
You can run a separate HTTP server (on port 8080) that redirects all traffic to 8443.
Add this to application.properties
:
server.http.port=8080
Then, create a configuration class to handle redirection:
@Configuration
public class HttpToHttpsRedirectConfig {
@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> containerCustomizer() {
return factory -> {
if (factory instanceof TomcatServletWebServerFactory) {
((TomcatServletWebServerFactory) factory).addAdditionalTomcatConnectors(createHttpConnector());
}
};
}
private Connector createHttpConnector() {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme("http");
connector.setPort(8080);
connector.setSecure(false);
connector.setRedirectPort(8443);
return connector;
}
}
Now, if a user visits http://localhost:8080
, they will be automatically redirected to HTTPS (https://localhost:8443).
5. Using a CA-Signed SSL Certificate for Production
For production purposes, utilize a trusted SSL certificate from a Certificate Authority (CA) such as:
- Let’s Encrypt (Free)
- DigiCert, GoDaddy, GlobalSign, etc. (Paid)
To install a CA-signed SSL certificate:
- Buy a domain name (yourdomain.com).
- Obtain an SSL certificate from a CA and get a.pfx or.crt/.key file.
- If necessary, convert the certificate to PKCS12 format:
openssl pkcs12 -export -in certificate.crt -inkey private.key -out keystore.p12 -name myssl
Update the Spring Boot configuration with the new certificate path.
Conclusion
HTTPS is paramount in securing Spring Boot applications. We discussed:
- Creating a self-signed SSL certificate for development environments
- Enabling Spring Boot to use HTTPS
- Redirecting HTTP traffic to HTTPS
- Using a CA-signed certificate in production
If deploying on AWS, Azure, or Kubernetes, utilize Nginx, AWS ALB, or a Cloud Load Balancer to handle HTTPS effectively.