HowToDoInJava

  • Python
  • Java
  • Spring Boot
  • Dark Mode
Home / Junit / Test Spring Security Auth with JUnit

Test Spring Security Auth with JUnit

Learn to test Spring security authentication using JUnit testcase using InMemoryDaoImpl. Also learn to build fully populated authentication object programmatically and then use it in application.

SecurityContextHolder

Spring security is based on security context, which is kind of static in nature. This essentially means that your do not need to inject its reference into your beans or classes in spring container. You can access the spring context anytime simply using SecurityContextHolder.getContext() method.

This context has the reference of actual principal or user which we have to validate for its access permissions.

Unit test Spring Security

I am creating a very simple maven project and will write minimal code so that I can focus on testing only what is in scope of this post i.e. authentication. Then I will write a demo service class with a single method which required “ROLE_USER” to access it. If you try to access this method and you do not have “ROLE_USER“, you will get the expected AccessDeniedException. Simple enough, isn’t it?

Step 1) Project setup

Lets create the java project using below command:

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

Now update the pom.xml with below dependencies and run command mvn:eclipse:eclipse to make project eclipse supported.

<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.howtodoinjava</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) Create security configuration file

I have create application-security.xml file and put the security configuration inside it.

<?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="lokesh" password="password1" authorities="ROLE_USER" />
                <user name="admin" password="password2" authorities="ROLE_ADMIN" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
    
    <beans:bean id="demoService" class="com.howtodoinjava.DemoService"/>
    
</beans:beans>

Step 3) Create secured method

package com.howtodoinjava;

import org.springframework.security.access.annotation.Secured;

public class DemoService
{
	@Secured("ROLE_USER")
	public void method()
	{
		System.out.println("Method called");
	}
}

Step 4) Test the authentication with JUnit test

In junit tests, we will configure the spring context programmatically and then will access the users by username from default user details service. In out case, it is in-memory implementation which in your case might differ to some jdbc based user details service or some other custom user detail service also. So, please modify the look up accordingly.

We will test various scenarios like valid user, invalid user, invalid role etc. You can add/ remove scenarios based on your choice.

package com.howtodoinjava;

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;

public class TestDemoService {
	
	static ApplicationContext applicationContext = null;
	static InMemoryDaoImpl userDetailsService = null;
	
	/**
	 * Initialize the application context to re-use in all test cases
	 * */
	@BeforeClass
	public static void setup()
	{
		//Create application context instance
		applicationContext = new ClassPathXmlApplicationContext("application-security.xml");
		//Get user details service configured in configuration 
		userDetailsService = applicationContext.getBean(InMemoryDaoImpl.class);
	}
	
	/**
	 * Test the valid user with valid role
	 * */
	@Test 
	public void testValidRole()
	{
		//Get the user by username from configured user details service
		UserDetails userDetails = userDetailsService.loadUserByUsername ("lokesh");
		Authentication authToken = new UsernamePasswordAuthenticationToken (userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
		SecurityContextHolder.getContext().setAuthentication(authToken);
		DemoService service = (DemoService) applicationContext.getBean("demoService");
		service.method();
	}
	
	/**
	 * Test the valid user with INVALID role
	 * */
	@Test (expected = AccessDeniedException.class)
	public void testInvalidRole()
	{
		UserDetails userDetails = userDetailsService.loadUserByUsername ("lokesh");
		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();
	}
	
	/**
	 * Test the INVALID user 
	 * */
	@Test (expected = AccessDeniedException.class)
	public void testInvalidUser()
	{
		UserDetails userDetails = userDetailsService.loadUserByUsername ("admin");
		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();
	}
	
}

As you can see that all the test cases are passing as expected.

Happy Leaning !!

Source code download

Was this post helpful?

Let us know if you liked the post. That’s the only way we can improve.

Share this:

  • Twitter
  • Facebook
  • LinkedIn
  • Reddit

About Lokesh Gupta

A family guy with fun loving nature. Love computers, programming and solving everyday problems. Find me on Facebook and Twitter.

Feedback, Discussion and Comments

  1. riyaz

    October 30, 2015

    Excellent sir …. very helpful blog and got a lot and lot of useful information.. Thanks alot

  2. Johne

    September 23, 2015

    can you show how to achieve this using annotation based Security Config?

  3. Leena

    April 14, 2015

    Hi Lokesh – Do you know how we can set the spring user context or principal?

    • Lokesh Gupta

      April 14, 2015

      Is there anything else, you are looking for and that is not given in article?

      • Leena

        April 14, 2015

        Yes, its not related to this article, basically I am looking for the way to set spring user context or principal into the SecurityContext without the use of AuthenticationManager set in XML file. Could you please help ?

        Authentication authToken = new UsernamePasswordAuthenticationToken(username, password,authorities);
        SecurityContextHolder.getContext().setAuthentication(authToken);
        Not sure how we can checked if its correctly set

  4. Ibai

    February 10, 2015

    Great article about spring SecurityContext. Thanks.

  5. Guillaume

    November 20, 2013

    Nice article, exactly what i was looking for !

    • Ramakrishna Punjal

      October 23, 2014

      A very good article … Thank you very much

Comments are closed on this article!

Search Tutorials

JUnit 5 Tutorial

  • JUnit 5 – Introduction
  • JUnit 5 – Test LifeCycle
  • JUnit 5 – @BeforeAll
  • JUnit 5 – @BeforeEach
  • JUnit 5 – @AfterEach
  • JUnit 5 – @AfterAll
  • JUnit 5 – @RepeatedTest
  • JUnit 5 – @Disabled
  • JUnit 5 – @Tag
  • JUnit 5 – Expected Exception
  • JUnit 5 – Assertions Examples
  • JUnit 5 – Assumptions
  • JUnit 5 – Test Suites
  • JUnit 5 – Gradle Dependency
  • JUnit 5 – Maven Dependency
  • JUnit 5 – Execute Test in Eclipse
  • JUnit 5 – Eclipse Test Templates
  • JUnit 5 vs JUnit 4

JUnit 4 Tutorial

  • JUnit – Introduction
  • JUnit – Test Suite
  • JUnit – Execute with JUnitCore
  • JUnit – Execute with Maven
  • JUnit – org.junit.Assume
  • JUnit – Expected Exceptions
  • JUnit – Listeners
  • JUnit – Force Timeout
  • JUnit – Ordered Tests
  • JUnit – Parameterized Tests
  • Junit – @Theory And @DataPoints
  • JUnit – TemporaryFolder @Rule

Meta Links

  • About Me
  • Contact Us
  • Privacy policy
  • Advertise
  • Guest and Sponsored Posts

Recommended Reading

  • 10 Life Lessons
  • Secure Hash Algorithms
  • How Web Servers work?
  • How Java I/O Works Internally?
  • Best Way to Learn Java
  • Java Best Practices Guide
  • Microservices Tutorial
  • REST API Tutorial
  • How to Start New Blog

Copyright © 2020 · HowToDoInjava.com · All Rights Reserved. | Sitemap

  • Java 15 New Features
  • Sealed Classes and Interfaces
  • EdDSA (Ed25519 / Ed448)