Testing Spring Security Auth with JUnit
Last Updated :
20 Apr, 2022
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
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<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"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
<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:
Similar Reads
Spring Security Integration with Spring Boot Spring Security is a powerful and customizable authentication and access control framework for Java applications. It provides comprehensive security services for Java EE-based enterprise software applications. This article will integrate Spring Security with a Spring Boot application, covering confi
5 min read
Spring Security with Maven Spring Security is a powerful and highly customizable authentication access management system. This is standard for protecting Spring-based applications. Spring Security is a framework that focuses on authentication and authorization for Java applications. Spring Security is a robust framework with
5 min read
Security with Spring Security and Spring Webflux Spring WebFlux is a part of the Spring Framework that supports reactive programming, enabling non-blocking asynchronous request handling. When developing web applications with Spring WebFlux, securing the application is a crucial aspect to ensure unauthorized access is prevented. This article provid
3 min read
Spring Security with LDAP Authentication LDAP (Lightweight Directory Access Protocol) is widely used for identity and access management. It organizes data in a hierarchical structure, optimized for read-heavy operations. LDAP is advantageous due to its scalability and interoperability. In this article, we will create a simple authenticatio
7 min read
Securing a Spring MVC Application with Spring Security Securing web applications is crucial in today's world, where security threats are prevalent. Spring Security is a powerful, customizable authentication and access-control framework that is part of the larger Spring ecosystem. It helps secure Spring MVC applications by managing authentication, author
6 min read
JUnit 5 - Test Suites with Example JUnit 5 encourages a modular approach to test creation with its test suites. These suites function as containers, bundling multiple test classes for easier management and collective execution within a single run. In this article, we will learn about JUnit 5 - Test Suites. Test SuiteIn JUnit 5, a tes
2 min read
Spring Security - Two Factor Authentication Two-factor authentication (2FA) is a security method that requires users to provide two forms of authentication to access their accounts. These forms of authentication typically include something the user knows (such as a password or PIN) and something the user has (such as a mobile device or hardwa
10 min read
Authentication in Spring Security In Spring Security, âauthenticationâ is the process of confirming that a user is who they say they are and that they have the right credentials to log in to a protected resource or to perform a privileged action in an application. Spring Security helps you set up different authentication methods, li
13 min read
Implementing OAuth2 with Spring Security: A Step-by-Step Guide OAuth is an authorization framework that creates a permissions policy and enables applications to have limited access to user accounts on HTTP services such as Facebook, GitHub, and Google. It works by allowing the users to authorize third-party applications to access their data without sharing thei
8 min read
Data Driven Testing With TestNG Data-Driven Testing with TestNG is a powerful approach that allows you to run the same test case with multiple sets of data. This methodology helps in achieving comprehensive test coverage and ensures that your application works correctly with various input values. By using external data sources lik
4 min read