Open In App

Spring Security – Role Based Authentication

Last Updated : 21 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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 picture when you build your API Secure. You need to create a bean and then make anything with lambda Functionalities Used. and also there is some role for accessing resources. In this article, we wanna see role-based authentication. We will define some Roles and only those people access Our Rest API. For Example Admin role access All Resources(Rest API), User only Access Public API. Let’s See a Spring Security Example project.

Benefits

  1. Make the application Secure
  2. Ensures privacy
  3. Prevents fraud
  4. Building user trust

Example Project

This is the Endpoint that accesses only the admin and user. User can access only get resource and the admin can access both resources.

Java
package org.technous.batchPrac3.controller;

import jdk.jfr.Description;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.technous.batchPrac3.dto.BookDTO;
import org.technous.batchPrac3.model.Book;
import org.technous.batchPrac3.service.BookService;

import java.util.List;

@RestController
@RequestMapping("/api")
public class BookController {

    @Autowired
    private BookService bookService;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/book/get")
    public String getAll(){
        return "get all employee";
    }

    @GetMapping("/getAll")
    public String getOne(){
        return "Get only one Employee ";
    }

    @GetMapping("/getApi")
    public String getAip(){
       return restTemplate.getForObject("https://dummyjson.com/products/1",String.class);
    }


    @PostMapping("/saveBook")
    public ResponseEntity<BookDTO> saveBook(@RequestBody BookDTO bookDTO){
        BookDTO mybookDTO = bookService.createBook(bookDTO);
        return new ResponseEntity<>(mybookDTO, HttpStatus.OK);
    }

}

Now, let’s implement this one, First of all, you need to add security dependency here.(POM.XML)

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.technous</groupId>
    <artifactId>batchPrac3</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>batchPrac3</name>
    <description>Batch Processing project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.4.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

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

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <parameters>true</parameters>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>


Java
package org.technous.batchPrac3.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.client.RestTemplate;


@Configuration
public class MyConfig {
    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .cors(cors -> cors.disable())
                .authorizeHttpRequests(req -> req
                        
                        .requestMatchers("/api/getApi").hasRole("ADMIN").anyRequest().authenticated()
                       ).httpBasic(Customizer.withDefaults());
        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.builder()
                .username("user")
                .password(passwordEncoder().encode("user123"))
                .roles("USER")
                .build();
        UserDetails admin = User.builder()
                .username("admin")
                .password(passwordEncoder().encode("admin123"))
                .roles("ADMIN")
                .build();
        return new InMemoryUserDetailsManager(user,admin);
    }

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

Now, you need to make one Configuration class. here your configure multiple request mapper and also configure role in this there one method hasAnyRole(“USER”,”ADMIN”). This way multiple role we defined. then your also define permission all to all general public without any role. this configuration like this.

Java
 @Bean
 public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .cors(cors -> cors.disable())
                .authorizeHttpRequests(req -> req
                        .requestMatchers("/public/api/*").permitAll()
                        .requestMatchers("/api/getApi").hasRole("ADMIN").anyRequest().authenticated()
                        .requestMatchers("api/getAll").hasAnyRole("ADMIN","USER").anyRequest().authenticated()
                       ).httpBasic(Customizer.withDefaults());
        return http.build();
    }

Output:

If you don’t have a role or credential you do not access any resources.

2

Now, the admin and user can access this API.

3

Now in the authorization tab you set basic authentication provide valid credentials and access those resources. In This Code @Configuration Annotation make your class as Configuration and declare your class as bean. and SecurityChain Method Chaining Filteration. and now “/get” this one resource access only user and rest of all resource access admin. This is the Way you Secure your Application Restapi. This is the Role-based Authentication which that you can provide roles with valid credentials and access to Rest API.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads