Implementing Database Authentication and Authorization with Spring Security 6
Last Updated :
06 Aug, 2024
Spring Security 6 has made setting up security in Spring applications easier and more straightforward by moving away from the older WebSecurityConfigurerAdapter
method. This new approach helps you configure security in a clearer and more flexible way. In this article, we will learn how to set up user login (authentication) and permissions (authorization) in a Spring Boot 3.0 app using this updated framework. We will focus on how to use a database to handle user information, which helps in managing security more effectively.
With this new method, managing user security becomes simpler and more scalable. It makes it easier to set up and adjust security features as your application grows, keeping your authentication and authorization processes secure and up-to-date.
Authentication Methods
This article will focus on database authentication for Spring Security 6.
This diagram shows the basic authentication flow.
- An unauthenticated object requests access.
- The Authentication Provider processes the request.
- If successful, it produces an authenticated object.
- The arrows show the transformation from unauthenticated to authenticated state.
This represents how a system verifies and grants access to users or services.
Implementation Steps for Database Authentication and Authorization with Spring Security 6
Step 1: Create a New Spring Boot Project
Use Spring Initializr to generate a new Spring Boot project with the following configurations:
- Project: Maven
- Language: Java
- Packaging: Jar
- Java Version: 17
Include the following dependencies:
- Spring Web
- Spring Security
- Spring Data JPA
- MySQL Connector
- Lombok (optional)
For the complete configuration, you can refer to the Maven Repository to find the exact versions and additional details.
Step 2: Set up Application.properties
Configure your application.properties
file with necessary settings for your database and Spring Security.
Step 3: Create the User Model
In this step, we will define the User model that represents the user entity in your database and implements the UserDetails interface from Spring Security. This model is crucial for integrating database-driven authentication with Spring Security.
Java
import lombok.*; // Import Lombok annotations
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* Represents a user in the system with security details.
*/
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class User implements UserDetails {
// Delimiter used to split authorities string
private static final String AUTHORITIES_DELIMITER = "::";
// Unique identifier for the user
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
// Username of the user
private String username;
// Password of the user
private String password;
// Authorities granted to the user, stored as a single string
private String authorities;
/**
* Returns the authorities granted to the user.
* @return a collection of GrantedAuthority objects
*/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// Split the authorities string and convert to a list of SimpleGrantedAuthority objects
return Arrays.stream(this.authorities.split(AUTHORITIES_DELIMITER))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
}
/**
* Returns the password used to authenticate the user.
* @return the password
*/
@Override
public String getPassword() {
return password;
}
/**
* Returns the username used to authenticate the user.
* @return the username
*/
@Override
public String getUsername() {
return username;
}
/**
* Indicates whether the user's account has expired.
* @return true if the account is non-expired, false otherwise
*/
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* Indicates whether the user is locked or unlocked.
* @return true if the account is non-locked, false otherwise
*/
@Override
public boolean isAccountNonLocked() {
return true;
}
/**
* Indicates whether the user's credentials have expired.
* @return true if the credentials are non-expired, false otherwise
*/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* Indicates whether the user is enabled.
* @return true if the user is enabled, false otherwise
*/
@Override
public boolean isEnabled() {
return true;
}
}
The User
class represents a user entity in a Spring Security context, implementing the UserDetails
interface. It provides user information such as username, password, and authorities. The getAuthorities
method converts a delimited string of authorities into a collection of GrantedAuthority
objects for security roles.
What is UserDetails Interface?
The UserDetails interface is a core part of Spring Security. It provides a way to retrieve user information necessary for authentication and authorization. When you implement this interface, you tell Spring Security how to get details about a user from your data source (e.g., a database).
Importance:
- Authentication: Verifies user credentials.
- Authorization: Provides user roles and permissions.
Key Methods
- getAuthorities(): Returns user roles/permissions.
- getPassword(): Returns the user’s password.
- getUsername(): Returns the username.
- isAccountNonExpired(): Indicates if the account is expired (defaults to true).
- isAccountNonLocked(): Indicates if the account is locked (defaults to true).
- isCredentialsNonExpired(): Indicates if credentials are expired (defaults to true).
- isEnabled(): Indicates if the user is enabled.
In Spring Security 6, methods like isAccountNonExpired()
, isAccountNonLocked()
, and isCredentialsNonExpired()
return true by default unless overridden.
Step 4: Define the User Service
Create a service to handle user details and authentication. This service implements the UserDetailsService
interface, essential for fetching user information during authentication.
Java
import com.example.SpringSecurity.Spring.Demo.Project.Model.User;
import com.example.SpringSecurity.Spring.Demo.Project.Repository.UserRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
@Service // Marks this class as a service component for dependency injection
public class UserService implements UserDetailsService {
@Autowired
private UserRepo userRepo; // Injects the UserRepo for accessing user data
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// Retrieves user details by username from the database
return userRepo.findByUsername(username);
}
public String create(String username, String password) {
// Encodes the password and creates a new User object
User user = User.builder()
.username(username)
.password(new BCryptPasswordEncoder().encode(password)) // Encrypts the password
.authorities("student") // Assigns default authority
.build();
// Saves the new user to the database
userRepo.save(user);
return "Create Successfully !"; // Returns a success message
}
}
Why this Service is Implemented?
- Loading User Details:
- Method: loadUserByUsername(String username)
- Purpose: This method fetches user information from the database using their username. Spring Security calls this method to retrieve the user's details when they attempt to log in.
- Creating Users:
- Method: create(String username, String password)
- Purpose: This method creates a new user and saves their information to the database. It uses BCryptPasswordEncoder to securely encode the user's password before storing it.
Explanation:
- UserRepo: This is the database repository used to get and save user information.
- UserDetailsService: This is an interface from Spring Security that helps load user data for authentication.
- BCryptPasswordEncoder: This tool encrypts passwords to keep them safe when stored in the database.
In essence, this service is crucial because it bridges the gap between your application's user data and Spring Security, ensuring secure and smooth authentication processes.
Step 5: Define the User Repository
In this step, we create a repository interface for accessing user data in the database.
Java
import com.example.SpringSecurity.Spring.Demo.Project.Model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.security.core.userdetails.UserDetails;
public interface UserRepo extends JpaRepository<User, Integer> {
UserDetails findByUsername(String username);
}
The UserRepo interface simplifies database interactions for user data and provides a way to retrieve user details by username, which is essential for authenticating users in your application
Step 6: Create the Security Controller
In this step, we define a controller to handle HTTP requests and interact with the UserService.
Java
import com.example.SpringSecurity.Spring.Demo.Project.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/test")
public class SecurityController {
@Autowired
UserService userService;
@GetMapping("/home")
public String home(){
return "This is Home";
}
@GetMapping("/student")
public String student(){
return "This is Student";
}
@GetMapping("/admin")
public String admin(){
return "This is Admin";
}
@PostMapping("/create")
public String create(@RequestParam("username") String username, @RequestParam("password") String password){
return userService.create(username, password);
}
}
Controller Overview:
- Endpoints:
/home
: Accessible by everyone./student
: Restricted to users with the "STUDENT" authority./admin
: Restricted to users with the "ADMIN" authority./create
: Allows creation of new users by accepting username and password.
- Purpose: Handles user-related requests, returns simple messages, and allows user creation.
Final and Important Step: Configure Spring Security
In this step, we set up the security configuration for our Spring Boot application. This involves defining how authentication and authorization are handled, and securing our endpoints.
Java
import com.example.SpringSecurity.Spring.Demo.Project.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private UserService userService;
@Bean
public AuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf(httpSecurityCsrfConfigurer -> httpSecurityCsrfConfigurer.disable())
.httpBasic(Customizer.withDefaults())
.authorizeHttpRequests(
authorizeRequest -> authorizeRequest
.requestMatchers("/test/student").hasAuthority("student")
.requestMatchers("/test/admin").hasAuthority("admin")
.anyRequest().permitAll()
).formLogin(Customizer.withDefaults());
return httpSecurity.build();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
Configuration Breakdown:
- Enable Web Security:
@Configuration
and @EnableWebSecurity
enable Spring Security in the application. - Authentication Provider:
authenticationProvider()
sets up the provider using DaoAuthenticationProvider
to handle user details and password encoding. - Security Filter Chain:
securityFilterChain(HttpSecurity httpSecurity)
configures HTTP security, including CSRF protection, basic authentication, and request authorization. - Password Encoder:
passwordEncoder()
provides a bean for encoding passwords with BCrypt.
Authentication and Authorization Results
Step 1: Start The Server
Step 2: Check First Public endpoint it's working or not
Step 3: Check All secured Endpoints working or not
When we try to access any secured endpoint it's redirect to login page.
Let's try to access with Any Username & password:
When We are trying to give wrong usename & password it'll fetch the error.
Let's See the what is username & password are stored in our MySQL tables.
Create a new User.
This user is always have student authority int our case because ewhen we creating the new user this always student authorites our service logic because we want to secure application so we can't give access any user to define it's authority for admin we create admin from database layer or you can define seprate admin for your controller according to you need.
Now let's again check the Database,
We Create Admin manually for security purpose now let's check using this data can we login the endpoints.
Output:
Booom ! we Successfully Loged In
If we try to login with who has admin authority, is it login? let's check,
Output:
It returns 403 as status with type Forbidden.
And we are also expecting this because it's unauthorized for user so we cannot access with wrong credential, now let's try to login admin page with admin credential.
Output:
Conclusion
In this article, we covered how to implement authentication and authorization in a Spring Boot 3.0 application using Spring Security 6. We moved from the old WebSecurityConfigurerAdapter approach to a more modern, component-based setup. Key steps included:
- Creating a User entity and configuring it with UserDetails for user data.
- Setting up a UserService to handle user management and authentication.
- Defining a UserRepo for database interactions.
- Building a SecurityController with endpoints that are secured based on user roles.
- Configuring SecurityConfig to manage authentication, authorization, and password encoding.
This setup ensures that your application is both secure and scalable, with proper management of user roles and credentials.
Similar Reads
Authentication and Authorization in Spring Boot 3.0 with Spring Security
In Spring Security 5.7.0, the spring team deprecated the WebSecurityConfigurerAdapter, as they encourage users to move towards a component-based security configuration. Spring Boot 3.0 has come with many changes in Spring Security. So in this article, we will understand how to perform spring securit
4 min read
Spring Security - Custom Form Login with Database Authentication
In this article, Spring Security Basic Authentication, we have demonstrated the Basic Authentication using In-Memory Authentication. But what if we are required to authenticate the user from the database? And also what if we are required to login with the custom form? In this article, we will explai
8 min read
Spring Boot - OAuth2 Authentication and Authorization
OAuth2 is a widely-used protocol for authorization that enables applications to securely access resources on behalf of users. When combined with Spring Boot, OAuth2 facilitates authentication and authorization for both REST APIs and web applications. This article will walk you through setting up OAu
7 min read
Prevent Brute Force Authentication Attempts with Spring Security
Brute force attacks are a common threat where an attacker tries multiple combinations of usernames and passwords to gain authorized access to the system. To protect against such attacks, it is crucial to implement mechanisms that can detect and block repeated failed login attempts. Spring Security c
10 min read
Spring Boot 3.0 - JWT Authentication with Spring Security using MySQL Database
In Spring Security 5.7.0, the spring team deprecated the WebSecurityConfigurerAdapter, as they encourage users to move towards a component-based security configuration. Spring Boot 3.0 has come with many changes in Spring Security. In this article, we'll learn how to implement JWT authentication and
8 min read
API Gateway Authentication and Authorization in Spring Boot
In modern web applications, securing the communication between the clients and backend services is crucial. The API Gateway can serves as the reverse proxy and managing the client requests, and routing them to the appropriate the backend services. It enhance the security, we can implement the authen
12 min read
How to Implement Simple Authentication in Spring Boot?
In this article, we will learn how to set up and configure Basic Authentication with Spring. Authentication is one of the major steps in any kind of security. Spring provides dependencies i.e. Spring Security that helps to establish the Authentication on the API. There are so many ways to add Authen
4 min read
Spring Security - Role Based Authentication
Authentication is when anyone wants to access your Rest API they need some Authorization like a Username, Password, and token kind of. So Spring Boot Security has a Spring Boot 6.2.0 version. In the lower version Some Methods are deprecated in spring Security that's why a new thing comes into the pi
4 min read
Spring Security - Form-Based Authentication
Form-Based Authentication in Spring Security provides a secure way to authenticate users using a custom login form instead of the default security prompt. It allows better control over authentication flow, user experience, and security configurations. Key Features: Customizable login and logout mech
5 min read
Spring Security - In-Memory Authentication
Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications. Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring
4 min read