Open In App

Testing Spring Security Auth with JUnit

Last Updated : 20 Apr, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Here we are going to learn how to use InMemoryDaoImpl to verify Spring security authentication using a JUnit test case and how to programmatically create a fully complete authentication object and then utilize it in an application.

SecurityContextHolder: Spring security is built on the concept of a security context, which is somewhat static. This simply implies that you don’t have to inject its reference into your spring container beans or classes. The SecurityContextHolder.getContext() function may be used to get the spring context at any moment.

This context contains a reference to the real principal or user, whose access permissions we must verify.

Unit test Spring Security: We will be creating a Maven project and writing very little code so one can focus on testing only the aspects of authentication that are relevant to this topic. Then I’ll construct a simple sample service class with only one method that requires “ROLE USER” to access. If you try to use this function without having “ROLE USER,” you’ll get an AccessDeniedException as predicted. Isn’t it straightforward?

The project structure is as follows: 

Let’s make a Java project with the following command:

Console

$ mvn archetype:generate -DgroupId=com.geeksforgeeks
             -DartifactId=SpringPasswordHashingDemo
             -DarchetypeArtifactId=maven-archetype-quickstart 
             -DinteractiveMode=false

 

To make project eclipse supported, edit the pom.xml with the following dependencies and run the command mvn:eclipse:eclipse.

File: pom.xml

XML




  <modelVersion>4.0.0</modelVersion>
  <groupId>com.geeksforgeeks</groupId>
  <artifactId>SpringPasswordHashingDemo</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>SpringPasswordHashingDemo</name>
  <url>http://maven.apache.org</url>
  <properties>
    <org.springframework.version>3.0.5.RELEASE</org.springframework.version>
  </properties>
  <dependencies>
       <!-- Spring Core -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.4</version>
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${org.springframework.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${org.springframework.version}</version>
      <scope>test</scope>
    </dependency>
      
    <!-- Spring Security -->
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
        <version>${org.springframework.version}</version>
        <type>jar</type>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>${org.springframework.version}</version>
        <type>jar</type>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>${org.springframework.version}</version>
        <type>jar</type>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-taglibs</artifactId>
        <version>${org.springframework.version}</version>
        <type>jar</type>
        <scope>compile</scope>
    </dependency>
      
  </dependencies>
</project>


Step 2: Make a file for security configuration.

By now we have created a file called application-security.xml and placed the security configuration inside.

File: application-security.xml

XML




<?xml version="1.0" encoding="UTF-8"?>
    xsi:schemaLocation="http://www.springframework.org/schema/beans
      
    <global-method-security secured-annotations="enabled" />
  
    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <user-service>
                <user name="geeksforgeeks" password="password1" authorities="ROLE_USER" />
                <user name="geeksforgeeks2" password="password2" authorities="ROLE_ADMIN" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
      
    <beans:bean id="demoService" class="com.geeksforgeeks.DemoService"/>
</beans:beans>


Step 3: Create a secured method

File: DemoService.java

Java




// Java Program to Illustrate DemoService Class
  
package com.geeksforgeeks;
  
// Importing required classes
import org.springframework.security.access.annotation.Secured;
  
// Class
public class DemoService {
    @Secured("ROLE_USER")
  
    // Method
    public void method()
    {
        // Print statement
        System.out.println("Method called");
    }
}


Step 4: Use JUnit to test the authentication

In JUnit tests, we’ll programmatically establish the spring context and then access users by username from the default user information service. In our instance, it’s an in-memory implementation, which may differ from a JDBC-based user information service or a bespoke user details service in your situation. As a result, please adjust the lookup appropriately.

We’ll test a variety of situations, including valid user, invalid user, and invalid role, among others. You have the option to add or delete situations based on your preferences.

File: TestDemoService.java

Java




// Java Program to Illustrate TestDemoService Class
  
package com.geeksforgeeks;
  
// Importing required classes
import java.util.ArrayList;
import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.memory.InMemoryDaoImpl;
  
// Class
public class TestDemoService {
  
    static ApplicationContext applicationContext = null;
    static InMemoryDaoImpl userDetailsService = null;
  
    // Initialize the application context to
    // re-use in all test cases
    @BeforeClass
  
    // Method 1
    public static void setup()
    {
        // Creating application context instance
        applicationContext
            = new ClassPathXmlApplicationContext(
                "application-security.xml");
  
        // Getting user details service configured in
        // configuration
        userDetailsService = applicationContext.getBean(
            InMemoryDaoImpl.class);
    }
  
    @Test
    // Method 2
    // To test the valid user with valid role
    public void testValidRole()
    {
        // Get the user by username from configured user
        // details service
        UserDetails userDetails
            = userDetailsService.loadUserByUsername(
                "geeksforgeeks");
        Authentication authToken
            = new UsernamePasswordAuthenticationToken(
                userDetails.getUsername(),
                userDetails.getPassword(),
                userDetails.getAuthorities());
        SecurityContextHolder.getContext()
            .setAuthentication(authToken);
        DemoService service
            = (DemoService)applicationContext.getBean(
                "demoService");
        service.method();
    }
  
    // Method 3
    // To test the valid user with INVALID role
    @Test(expected = AccessDeniedException.class)
    public void testInvalidRole()
    {
        UserDetails userDetails
            = userDetailsService.loadUserByUsername(
                "geeksforgeeks");
        List<GrantedAuthority> authorities
            = new ArrayList<GrantedAuthority>();
        authorities.add(
            new GrantedAuthorityImpl("ROLE_INVALID"));
        Authentication authToken
            = new UsernamePasswordAuthenticationToken(
                userDetails.getUsername(),
                userDetails.getPassword(), authorities);
        SecurityContextHolder.getContext()
            .setAuthentication(authToken);
        DemoService service
            = (DemoService)applicationContext.getBean(
                "demoService");
        service.method();
    }
  
    // Method 4
    // Test the INVALID user
    @Test(expected = AccessDeniedException.class)
    public void testInvalidUser()
    {
        UserDetails userDetails
            = userDetailsService.loadUserByUsername(
                "geeksforgeeks2");
        List<GrantedAuthority> authorities
            = new ArrayList<GrantedAuthority>();
  
        authorities.add(
            new GrantedAuthorityImpl("ROLE_INVALID"));
        Authentication authToken
            = new UsernamePasswordAuthenticationToken(
                userDetails.getUsername(),
                userDetails.getPassword(), authorities);
  
        SecurityContextHolder.getContext()
            .setAuthentication(authToken);
        DemoService service
            = (DemoService)applicationContext.getBean(
                "demoService");
  
        service.method();
    }
}


Output: Now we will see all test cases are running as depicted via the visual aid below shown as follows: 

 

 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads