Spring Security Test provides comprehensive testing utilities for Spring Security applications with mock authentication, security context testing, and web security testing features.
—
Comprehensive MockMvc integration providing request post-processors, configurers, and result matchers for testing web security in servlet-based Spring applications. This integration allows testing of HTTP security concerns including authentication, authorization, CSRF protection, and various authentication mechanisms.
Configure MockMvc with Spring Security support using the configurer.
/**
* Spring Security MockMvc configurers
*/
public class SecurityMockMvcConfigurers {
/**
* Auto-configure Spring Security with MockMvc using default filter chain
* @return MockMvcConfigurer for Spring Security integration
*/
public static MockMvcConfigurer springSecurity();
/**
* Configure Spring Security with MockMvc using specific filter chain
* @param springSecurityFilterChain The security filter chain to use
* @return MockMvcConfigurer for Spring Security integration
*/
public static MockMvcConfigurer springSecurity(Filter springSecurityFilterChain);
}Usage Examples:
@SpringBootTest
@AutoConfigureTestDatabase
public class SecurityIntegrationTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@BeforeEach
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity()) // Essential for security testing
.build();
}
}Core authentication setup methods for establishing security contexts in requests.
/**
* Security request post-processors for MockMvc
*/
public class SecurityMockMvcRequestPostProcessors {
/**
* Uses the SecurityContext from TestSecurityContextHolder
* @return RequestPostProcessor that applies test security context
*/
public static RequestPostProcessor testSecurityContext();
/**
* Sets a specific Authentication in the SecurityContext
* @param authentication The authentication to use
* @return RequestPostProcessor that applies the authentication
*/
public static RequestPostProcessor authentication(Authentication authentication);
/**
* Creates anonymous authentication
* @return RequestPostProcessor for anonymous authentication
*/
public static RequestPostProcessor anonymous();
/**
* Sets a specific SecurityContext
* @param securityContext The security context to use
* @return RequestPostProcessor that applies the security context
*/
public static RequestPostProcessor securityContext(SecurityContext securityContext);
}Usage Examples:
@Test
public void testWithAuthentication() throws Exception {
Authentication auth = new UsernamePasswordAuthenticationToken(
"user", "password",
Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))
);
mockMvc.perform(get("/secure")
.with(authentication(auth)))
.andExpect(status().isOk());
}
@Test
@WithMockUser(username = "testuser")
public void testWithSecurityContext() throws Exception {
mockMvc.perform(get("/user-info")
.with(testSecurityContext())) // Uses @WithMockUser context
.andExpected(status().isOk());
}Create user-based authentication with configurable roles and authorities.
/**
* Creates basic user authentication with username
* @param username The username for authentication
* @return UserRequestPostProcessor for further configuration
*/
public static UserRequestPostProcessor user(String username);
/**
* Creates user authentication from UserDetails
* @param user The UserDetails instance
* @return RequestPostProcessor with user authentication
*/
public static RequestPostProcessor user(UserDetails user);
/**
* Fluent configuration for user authentication
*/
public interface UserRequestPostProcessor extends RequestPostProcessor {
/** Set user roles (automatically prefixed with "ROLE_") */
UserRequestPostProcessor roles(String... roles);
/** Set granted authorities */
UserRequestPostProcessor authorities(GrantedAuthority... authorities);
/** Set user password */
UserRequestPostProcessor password(String password);
}Usage Examples:
@Test
public void testWithBasicUser() throws Exception {
mockMvc.perform(get("/user-endpoint")
.with(user("john")))
.andExpect(status().isOk());
}
@Test
public void testWithUserRoles() throws Exception {
mockMvc.perform(get("/admin-endpoint")
.with(user("admin").roles("ADMIN", "USER")))
.andExpect(status().isOk());
}
@Test
public void testWithUserAuthorities() throws Exception {
mockMvc.perform(get("/privileged-endpoint")
.with(user("manager")
.authorities(
new SimpleGrantedAuthority("READ_PRIVILEGES"),
new SimpleGrantedAuthority("WRITE_PRIVILEGES")
)))
.andExpect(status().isOk());
}
@Test
public void testWithUserDetails() throws Exception {
UserDetails userDetails = User.builder()
.username("alice")
.password("secret")
.roles("USER", "MANAGER")
.build();
mockMvc.perform(get("/manager-endpoint")
.with(user(userDetails)))
.andExpect(status().isOk());
}Support for HTTP Basic and Digest authentication mechanisms.
/**
* HTTP Basic authentication
* @param username The username
* @param password The password
* @return RequestPostProcessor with HTTP Basic authentication
*/
public static RequestPostProcessor httpBasic(String username, String password);
/**
* HTTP Digest authentication with default username
* @return DigestRequestPostProcessor for configuration
*/
public static DigestRequestPostProcessor digest();
/**
* HTTP Digest authentication with specific username
* @param username The username for digest authentication
* @return DigestRequestPostProcessor for configuration
*/
public static DigestRequestPostProcessor digest(String username);
/**
* Fluent configuration for HTTP Digest authentication
*/
public interface DigestRequestPostProcessor extends RequestPostProcessor {
// Additional digest-specific configuration methods
}Usage Examples:
@Test
public void testHttpBasicAuth() throws Exception {
mockMvc.perform(get("/api/data")
.with(httpBasic("apiuser", "apipass")))
.andExpect(status().isOk());
}
@Test
public void testHttpDigestAuth() throws Exception {
mockMvc.perform(get("/api/secure")
.with(digest("digestuser")))
.andExpect(status().isOk());
}X.509 certificate-based authentication support.
/**
* X.509 certificate authentication
* @param certificates The X.509 certificates to use
* @return RequestPostProcessor with certificate authentication
*/
public static RequestPostProcessor x509(X509Certificate... certificates);
/**
* X.509 certificate authentication from resource
* @param resourceName The resource name containing the certificate
* @return RequestPostProcessor with certificate authentication
*/
public static RequestPostProcessor x509(String resourceName);Usage Examples:
@Test
public void testCertificateAuth() throws Exception {
mockMvc.perform(get("/cert-required")
.with(x509("classpath:test-cert.pem")))
.andExpect(status().isOk());
}Comprehensive support for modern authentication mechanisms including JWT and OAuth2.
/**
* JWT authentication with default configuration
* @return JwtRequestPostProcessor for configuration
*/
public static JwtRequestPostProcessor jwt();
/**
* OAuth2 opaque token authentication
* @return OpaqueTokenRequestPostProcessor for configuration
*/
public static OpaqueTokenRequestPostProcessor opaqueToken();
/**
* OAuth2 login authentication
* @return OAuth2LoginRequestPostProcessor for configuration
*/
public static OAuth2LoginRequestPostProcessor oauth2Login();
/**
* OIDC login authentication
* @return OidcLoginRequestPostProcessor for configuration
*/
public static OidcLoginRequestPostProcessor oidcLogin();
/**
* OAuth2 client configuration
* @return OAuth2ClientRequestPostProcessor for configuration
*/
public static OAuth2ClientRequestPostProcessor oauth2Client();
/**
* OAuth2 client with specific registration
* @param registrationId The client registration ID
* @return OAuth2ClientRequestPostProcessor for configuration
*/
public static OAuth2ClientRequestPostProcessor oauth2Client(String registrationId);JWT Configuration Interface:
/**
* Fluent configuration for JWT authentication
*/
public interface JwtRequestPostProcessor extends RequestPostProcessor {
/**
* Configure JWT using builder consumer
* @param jwtBuilderConsumer Consumer to configure JWT builder
* @return JwtRequestPostProcessor for chaining
*/
JwtRequestPostProcessor jwt(Consumer<Jwt.Builder> jwtBuilderConsumer);
/**
* Use specific JWT instance
* @param jwt The JWT to use
* @return JwtRequestPostProcessor for chaining
*/
JwtRequestPostProcessor jwt(Jwt jwt);
/**
* Set authorities for JWT authentication
* @param authorities The granted authorities
* @return JwtRequestPostProcessor for chaining
*/
JwtRequestPostProcessor authorities(Collection<GrantedAuthority> authorities);
}Usage Examples:
@Test
public void testWithJwt() throws Exception {
mockMvc.perform(get("/api/jwt-secured")
.with(jwt()
.jwt(jwt -> jwt
.claim("sub", "user123")
.claim("scope", "read write"))
.authorities(
new SimpleGrantedAuthority("SCOPE_read"),
new SimpleGrantedAuthority("SCOPE_write")
)))
.andExpect(status().isOk());
}
@Test
public void testWithOAuth2Login() throws Exception {
mockMvc.perform(get("/oauth2/user")
.with(oauth2Login()
.attributes(attrs -> {
attrs.put("sub", "12345");
attrs.put("name", "John Doe");
})
.authorities(new SimpleGrantedAuthority("ROLE_USER"))))
.andExpected(status().isOk());
}
@Test
public void testWithOidcLogin() throws Exception {
mockMvc.perform(get("/oidc/userinfo")
.with(oidcLogin()
.idToken(token -> token
.claim("sub", "user123")
.claim("email", "user@example.com"))
.userInfo(userInfo -> userInfo
.claim("given_name", "John")
.claim("family_name", "Doe"))))
.andExpect(status().isOk());
}CSRF token support for testing CSRF-protected endpoints.
/**
* Valid CSRF token for testing
* @return CsrfRequestPostProcessor for configuration
*/
public static CsrfRequestPostProcessor csrf();
/**
* Fluent configuration for CSRF tokens
*/
public interface CsrfRequestPostProcessor extends RequestPostProcessor {
/**
* Send CSRF token as HTTP header instead of parameter
* @return CsrfRequestPostProcessor for chaining
*/
CsrfRequestPostProcessor asHeader();
/**
* Use an invalid CSRF token for testing failure scenarios
* @return CsrfRequestPostProcessor for chaining
*/
CsrfRequestPostProcessor useInvalidToken();
}Usage Examples:
@Test
public void testCsrfProtectedEndpoint() throws Exception {
mockMvc.perform(post("/form-submit")
.param("data", "test")
.with(csrf()) // Valid CSRF token
.with(user("user")))
.andExpect(status().is3xxRedirection());
}
@Test
public void testCsrfTokenAsHeader() throws Exception {
mockMvc.perform(post("/api/update")
.content("{\"data\":\"test\"}")
.contentType(MediaType.APPLICATION_JSON)
.with(csrf().asHeader()) // CSRF token in header
.with(user("user")))
.andExpect(status().isOk());
}
@Test
public void testInvalidCsrfToken() throws Exception {
mockMvc.perform(post("/protected")
.with(csrf().useInvalidToken())
.with(user("user")))
.andExpect(status().isForbidden());
}Test authentication state and user details in responses.
/**
* Security result matchers for MockMvc
*/
public class SecurityMockMvcResultMatchers {
/**
* Verify that user is authenticated
* @return AuthenticatedMatcher for further verification
*/
public static AuthenticatedMatcher authenticated();
/**
* Verify that user is not authenticated
* @return ResultMatcher for unauthenticated verification
*/
public static ResultMatcher unauthenticated();
}
/**
* Fluent matcher for authenticated user details
*/
public interface AuthenticatedMatcher extends ResultMatcher {
/** Verify the username */
AuthenticatedMatcher withUsername(String expected);
/** Verify user roles */
AuthenticatedMatcher withRoles(String... roles);
/** Verify user authorities */
AuthenticatedMatcher withAuthorities(Collection<? extends GrantedAuthority> expected);
/** Verify specific Authentication object */
AuthenticatedMatcher withAuthentication(Authentication expected);
/** Verify SecurityContext */
AuthenticatedMatcher withSecurityContext(SecurityContext expected);
}Usage Examples:
@Test
public void testAuthenticationState() throws Exception {
mockMvc.perform(get("/user-info")
.with(user("john").roles("USER", "ADMIN")))
.andExpect(status().isOk())
.andExpect(authenticated()
.withUsername("john")
.withRoles("USER", "ADMIN"));
}
@Test
public void testUnauthenticatedAccess() throws Exception {
mockMvc.perform(get("/public"))
.andExpect(status().isOk())
.andExpect(unauthenticated());
}
@Test
public void testSpecificAuthorities() throws Exception {
mockMvc.perform(get("/privileged")
.with(user("manager")
.authorities(
new SimpleGrantedAuthority("READ_PRIVILEGES"),
new SimpleGrantedAuthority("WRITE_PRIVILEGES")
)))
.andExpect(authenticated()
.withAuthorities(Arrays.asList(
new SimpleGrantedAuthority("READ_PRIVILEGES"),
new SimpleGrantedAuthority("WRITE_PRIVILEGES")
)));
}Enhanced request builders with security-specific functionality for form login and logout scenarios.
/**
* Security-enhanced request builders for form authentication flows
*/
public class SecurityMockMvcRequestBuilders {
/**
* Creates a form login request to default "/login" endpoint
* @return FormLoginRequestBuilder for configuration
*/
public static FormLoginRequestBuilder formLogin();
/**
* Creates a form login request to specified endpoint
* @param loginProcessingUrl The URL to POST the login form to
* @return FormLoginRequestBuilder for configuration
*/
public static FormLoginRequestBuilder formLogin(String loginProcessingUrl);
/**
* Creates a logout request to default "/logout" endpoint
* @return LogoutRequestBuilder for configuration
*/
public static LogoutRequestBuilder logout();
/**
* Creates a logout request to specified endpoint
* @param logoutUrl The logout URL to POST to
* @return LogoutRequestBuilder for configuration
*/
public static LogoutRequestBuilder logout(String logoutUrl);
}Fluent builder for form-based login requests with CSRF protection.
/**
* Builder for form login requests with automatic CSRF token inclusion
*/
public interface FormLoginRequestBuilder extends RequestBuilder {
/** Set the login processing URL */
FormLoginRequestBuilder loginProcessingUrl(String loginProcessingUrl);
/** Set the login processing URL with URI variables */
FormLoginRequestBuilder loginProcessingUrl(String loginProcessingUrl, Object... uriVars);
/** Set the username parameter name (default: "username") */
FormLoginRequestBuilder userParameter(String usernameParameter);
/** Set the password parameter name (default: "password") */
FormLoginRequestBuilder passwordParam(String passwordParameter);
/** Set the username value (default: "user") */
FormLoginRequestBuilder user(String username);
/** Set the password value (default: "password") */
FormLoginRequestBuilder password(String password);
/** Set both username parameter name and value */
FormLoginRequestBuilder user(String usernameParameter, String username);
/** Set both password parameter name and value */
FormLoginRequestBuilder password(String passwordParameter, String password);
/** Set the Accept header media type */
FormLoginRequestBuilder acceptMediaType(MediaType acceptMediaType);
}Fluent builder for logout requests with CSRF protection.
/**
* Builder for logout requests with automatic CSRF token inclusion
*/
public interface LogoutRequestBuilder extends RequestBuilder {
/** Set the logout URL (default: "/logout") */
LogoutRequestBuilder logoutUrl(String logoutUrl);
/** Set the logout URL with URI variables */
LogoutRequestBuilder logoutUrl(String logoutUrl, Object... uriVars);
}Usage Examples:
@Test
public void testFormLogin() throws Exception {
mockMvc.perform(formLogin()
.user("john")
.password("secret"))
.andExpect(status().is3xxRedirection())
.andExpect(authenticated().withUsername("john"));
}
@Test
public void testCustomFormLogin() throws Exception {
mockMvc.perform(formLogin("/custom-login")
.userParameter("email")
.passwordParam("pass")
.user("john@example.com")
.password("secret"))
.andExpect(status().is3xxRedirection());
}
@Test
public void testLogout() throws Exception {
mockMvc.perform(logout()
.with(user("testuser")))
.andExpect(status().is3xxRedirection())
.andExpect(unauthenticated());
}
@Test
public void testCustomLogout() throws Exception {
mockMvc.perform(logout("/custom-logout")
.with(user("testuser")))
.andExpect(status().is3xxRedirection());
}@SpringBootTest
@AutoConfigureTestDatabase
public class ComprehensiveSecurityTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@BeforeEach
public void setup() {
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
@Test
public void testCompleteUserFlow() throws Exception {
// Test unauthenticated access
mockMvc.perform(get("/secure"))
.andExpect(status().isUnauthorized())
.andExpect(unauthenticated());
// Test authenticated access
mockMvc.perform(get("/secure")
.with(user("john").roles("USER")))
.andExpect(status().isOk())
.andExpect(authenticated().withUsername("john"));
// Test admin-only endpoint
mockMvc.perform(get("/admin")
.with(user("john").roles("USER")))
.andExpect(status().isForbidden());
mockMvc.perform(get("/admin")
.with(user("admin").roles("ADMIN")))
.andExpect(status().isOk());
}
@Test
public void testFormSubmissionWithCsrf() throws Exception {
mockMvc.perform(post("/form")
.param("data", "test")
.with(csrf())
.with(user("user")))
.andExpect(status().is3xxRedirection());
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-security--spring-security-test