Spring Security Test provides comprehensive testing utilities for Spring Security applications with mock authentication, security context testing, and web security testing features.
—
WebTestClient integration for testing security in reactive Spring WebFlux applications, providing mutators for various authentication scenarios including OAuth2, JWT, and OIDC. This integration enables comprehensive testing of reactive security configurations and authentication flows.
Configure WebTestClient with Spring Security support for reactive applications.
/**
* Security configurers for reactive testing
*/
public class SecurityMockServerConfigurers {
/**
* Configure Spring Security with WebTestClient
* @return MockServerConfigurer for reactive security integration
*/
public static MockServerConfigurer springSecurity();
}Usage Examples:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ReactiveSecurityTest {
@Autowired
private WebTestClient webTestClient;
// WebTestClient is auto-configured with Spring Security in Spring Boot tests
@Test
public void testReactiveEndpoint() {
webTestClient
.mutateWith(mockUser())
.get().uri("/reactive/secure")
.exchange()
.expectStatus().isOk();
}
}Create user-based authentication for reactive testing.
/**
* Mock authentication with specific Authentication object
* @param authentication The authentication to use
* @return Mutator that applies the authentication
*/
public static <T> T mockAuthentication(Authentication authentication);
/**
* Mock user from UserDetails
* @param userDetails The UserDetails to use
* @return Mutator that applies user authentication
*/
public static <T> T mockUser(UserDetails userDetails);
/**
* Mock default user with username "user" and role "USER"
* @return UserExchangeMutator for configuration
*/
public static UserExchangeMutator mockUser();
/**
* Mock user with specific username
* @param username The username for authentication
* @return UserExchangeMutator for configuration
*/
public static UserExchangeMutator mockUser(String username);
/**
* Fluent configuration for user authentication in reactive tests
*/
public interface UserExchangeMutator extends WebTestClientConfigurer, MockServerConfigurer {
/** Set user password */
UserExchangeMutator password(String password);
/** Set user roles (automatically prefixed with "ROLE_") */
UserExchangeMutator roles(String... roles);
/** Set granted authorities */
UserExchangeMutator authorities(GrantedAuthority... authorities);
}Usage Examples:
@Test
public void testWithDefaultUser() {
webTestClient
.mutateWith(mockUser()) // username="user", roles=["USER"]
.get().uri("/api/user-data")
.exchange()
.expectStatus().isOk();
}
@Test
public void testWithCustomUser() {
webTestClient
.mutateWith(mockUser("alice")
.roles("USER", "MANAGER")
.password("secret"))
.get().uri("/api/manager-data")
.exchange()
.expectStatus().isOk();
}
@Test
public void testWithUserDetails() {
UserDetails user = User.builder()
.username("bob")
.password("password")
.authorities("ROLE_ADMIN", "READ_PRIVILEGES")
.build();
webTestClient
.mutateWith(mockUser(user))
.get().uri("/api/admin-data")
.exchange()
.expectStatus().isOk();
}
@Test
public void testWithCustomAuthentication() {
Authentication auth = new UsernamePasswordAuthenticationToken(
"customuser",
"credentials",
Arrays.asList(new SimpleGrantedAuthority("CUSTOM_AUTHORITY"))
);
webTestClient
.mutateWith(mockAuthentication(auth))
.get().uri("/api/custom")
.exchange()
.expectStatus().isOk();
}Comprehensive JWT authentication support for reactive applications.
/**
* Mock JWT authentication with default configuration
* @return JwtMutator for configuration
*/
public static JwtMutator mockJwt();
/**
* Fluent configuration for JWT authentication in reactive tests
*/
public interface JwtMutator extends WebTestClientConfigurer, MockServerConfigurer {
/**
* Configure JWT using builder consumer
* @param jwtBuilderConsumer Consumer to configure JWT builder
* @return JwtMutator for chaining
*/
JwtMutator jwt(Consumer<Jwt.Builder> jwtBuilderConsumer);
/**
* Use specific JWT instance
* @param jwt The JWT to use
* @return JwtMutator for chaining
*/
JwtMutator jwt(Jwt jwt);
/**
* Set authorities for JWT authentication
* @param authorities The granted authorities
* @return JwtMutator for chaining
*/
JwtMutator authorities(GrantedAuthority... authorities);
}Usage Examples:
@Test
public void testWithJwt() {
webTestClient
.mutateWith(mockJwt()
.jwt(jwt -> jwt
.claim("sub", "user123")
.claim("scope", "read write")
.claim("aud", "my-app"))
.authorities(
new SimpleGrantedAuthority("SCOPE_read"),
new SimpleGrantedAuthority("SCOPE_write")
))
.get().uri("/api/jwt-protected")
.exchange()
.expectStatus().isOk();
}
@Test
public void testWithPrebuiltJwt() {
Jwt jwt = Jwt.withTokenValue("token-value")
.header("alg", "HS256")
.claim("sub", "user456")
.claim("scope", "admin")
.build();
webTestClient
.mutateWith(mockJwt().jwt(jwt))
.get().uri("/api/admin-jwt")
.exchange()
.expectStatus().isOk();
}Support for OAuth2 opaque token authentication in reactive applications.
/**
* Mock OAuth2 opaque token authentication
* @return OpaqueTokenMutator for configuration
*/
public static OpaqueTokenMutator mockOpaqueToken();
/**
* Fluent configuration for opaque token authentication
*/
public interface OpaqueTokenMutator extends WebTestClientConfigurer, MockServerConfigurer {
/**
* Set token attributes
* @param attributes Map of token attributes
* @return OpaqueTokenMutator for chaining
*/
OpaqueTokenMutator attributes(Map<String, Object> attributes);
/**
* Configure token attributes using consumer
* @param attributesConsumer Consumer to configure attributes
* @return OpaqueTokenMutator for chaining
*/
OpaqueTokenMutator attributes(Consumer<Map<String, Object>> attributesConsumer);
/**
* Set authorities for token authentication
* @param authorities The granted authorities
* @return OpaqueTokenMutator for chaining
*/
OpaqueTokenMutator authorities(GrantedAuthority... authorities);
}Usage Examples:
@Test
public void testWithOpaqueToken() {
webTestClient
.mutateWith(mockOpaqueToken()
.attributes(attrs -> {
attrs.put("sub", "user789");
attrs.put("scope", "read write");
attrs.put("client_id", "my-client");
})
.authorities(
new SimpleGrantedAuthority("SCOPE_read"),
new SimpleGrantedAuthority("SCOPE_write")
))
.get().uri("/api/token-secured")
.exchange()
.expectStatus().isOk();
}OAuth2 login authentication support for reactive applications.
/**
* Mock OAuth2 login authentication
* @return OAuth2LoginMutator for configuration
*/
public static OAuth2LoginMutator mockOAuth2Login();
/**
* Fluent configuration for OAuth2 login authentication
*/
public interface OAuth2LoginMutator extends WebTestClientConfigurer, MockServerConfigurer {
/**
* Set OAuth2 user attributes
* @param attributes Map of user attributes
* @return OAuth2LoginMutator for chaining
*/
OAuth2LoginMutator attributes(Map<String, Object> attributes);
/**
* Configure OAuth2 user attributes using consumer
* @param attributesConsumer Consumer to configure attributes
* @return OAuth2LoginMutator for chaining
*/
OAuth2LoginMutator attributes(Consumer<Map<String, Object>> attributesConsumer);
/**
* Set client registration ID
* @param clientRegistrationId The client registration ID
* @return OAuth2LoginMutator for chaining
*/
OAuth2LoginMutator clientRegistrationId(String clientRegistrationId);
/**
* Set authorities for OAuth2 authentication
* @param authorities The granted authorities
* @return OAuth2LoginMutator for chaining
*/
OAuth2LoginMutator authorities(GrantedAuthority... authorities);
}Usage Examples:
@Test
public void testWithOAuth2Login() {
webTestClient
.mutateWith(mockOAuth2Login()
.clientRegistrationId("google")
.attributes(attrs -> {
attrs.put("sub", "12345");
attrs.put("name", "John Doe");
attrs.put("email", "john@example.com");
})
.authorities(new SimpleGrantedAuthority("ROLE_USER")))
.get().uri("/oauth2/user")
.exchange()
.expectStatus().isOk();
}OpenID Connect login authentication support for reactive applications.
/**
* Mock OIDC login authentication
* @return OidcLoginMutator for configuration
*/
public static OidcLoginMutator mockOidcLogin();
/**
* Fluent configuration for OIDC login authentication
*/
public interface OidcLoginMutator extends WebTestClientConfigurer, MockServerConfigurer {
/**
* Configure ID token
* @param idTokenBuilderConsumer Consumer to configure ID token
* @return OidcLoginMutator for chaining
*/
OidcLoginMutator idToken(Consumer<OidcIdToken.Builder> idTokenBuilderConsumer);
/**
* Configure user info
* @param userInfoConsumer Consumer to configure user info
* @return OidcLoginMutator for chaining
*/
OidcLoginMutator userInfo(Consumer<Map<String, Object>> userInfoConsumer);
/**
* Set client registration ID
* @param clientRegistrationId The client registration ID
* @return OidcLoginMutator for chaining
*/
OidcLoginMutator clientRegistrationId(String clientRegistrationId);
/**
* Set authorities for OIDC authentication
* @param authorities The granted authorities
* @return OidcLoginMutator for chaining
*/
OidcLoginMutator authorities(GrantedAuthority... authorities);
}Usage Examples:
@Test
public void testWithOidcLogin() {
webTestClient
.mutateWith(mockOidcLogin()
.clientRegistrationId("auth0")
.idToken(token -> token
.claim("sub", "user123")
.claim("email", "user@example.com")
.claim("email_verified", true))
.userInfo(userInfo -> {
userInfo.put("given_name", "John");
userInfo.put("family_name", "Doe");
userInfo.put("picture", "https://example.com/avatar.jpg");
})
.authorities(
new SimpleGrantedAuthority("ROLE_USER"),
new SimpleGrantedAuthority("SCOPE_openid")
))
.get().uri("/oidc/userinfo")
.exchange()
.expectStatus().isOk();
}OAuth2 client configuration for reactive applications.
/**
* Mock OAuth2 client with default configuration
* @return OAuth2ClientMutator for configuration
*/
public static OAuth2ClientMutator mockOAuth2Client();
/**
* Mock OAuth2 client with specific registration ID
* @param registrationId The client registration ID
* @return OAuth2ClientMutator for configuration
*/
public static OAuth2ClientMutator mockOAuth2Client(String registrationId);
/**
* Fluent configuration for OAuth2 client
*/
public interface OAuth2ClientMutator extends WebTestClientConfigurer, MockServerConfigurer {
/**
* Set client registration ID
* @param registrationId The client registration ID
* @return OAuth2ClientMutator for chaining
*/
OAuth2ClientMutator registrationId(String registrationId);
/**
* Set access token
* @param accessToken The access token
* @return OAuth2ClientMutator for chaining
*/
OAuth2ClientMutator accessToken(OAuth2AccessToken accessToken);
/**
* Configure access token using consumer
* @param accessTokenConsumer Consumer to configure access token
* @return OAuth2ClientMutator for chaining
*/
OAuth2ClientMutator accessToken(Consumer<OAuth2AccessToken.Builder> accessTokenConsumer);
}Usage Examples:
@Test
public void testWithOAuth2Client() {
webTestClient
.mutateWith(mockOAuth2Client("api-client")
.accessToken(token -> token
.tokenType(OAuth2AccessToken.TokenType.BEARER)
.scopes(Set.of("read", "write"))
.tokenValue("access-token-value")))
.get().uri("/api/client-data")
.exchange()
.expectStatus().isOk();
}CSRF token support for reactive applications.
/**
* Mock CSRF support for reactive applications
* @return CsrfMutator for configuration
*/
public static CsrfMutator csrf();
/**
* Fluent configuration for CSRF in reactive tests
*/
public interface CsrfMutator extends WebTestClientConfigurer, MockServerConfigurer {
// CSRF-specific configuration methods for reactive testing
}Usage Examples:
@Test
public void testCsrfProtectedEndpoint() {
webTestClient
.mutateWith(csrf())
.mutateWith(mockUser())
.post().uri("/api/form-submit")
.bodyValue("data=test")
.exchange()
.expectStatus().isOk();
}@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ReactiveSecurityIntegrationTest {
@Autowired
private WebTestClient webTestClient;
@Test
public void testUnauthenticatedAccess() {
webTestClient
.get().uri("/api/public")
.exchange()
.expectStatus().isOk();
webTestClient
.get().uri("/api/secure")
.exchange()
.expectStatus().isUnauthorized();
}
@Test
public void testUserAuthentication() {
webTestClient
.mutateWith(mockUser("testuser").roles("USER"))
.get().uri("/api/user-data")
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.value(response -> {
assertThat(response).contains("testuser");
});
}
@Test
public void testAdminOnlyEndpoint() {
// Test user access - should be forbidden
webTestClient
.mutateWith(mockUser("user").roles("USER"))
.get().uri("/api/admin")
.exchange()
.expectStatus().isForbidden();
// Test admin access - should succeed
webTestClient
.mutateWith(mockUser("admin").roles("ADMIN"))
.get().uri("/api/admin")
.exchange()
.expectStatus().isOk();
}
@Test
public void testJwtAuthentication() {
webTestClient
.mutateWith(mockJwt()
.jwt(jwt -> jwt
.claim("sub", "jwt-user")
.claim("scope", "read write"))
.authorities(
new SimpleGrantedAuthority("SCOPE_read"),
new SimpleGrantedAuthority("SCOPE_write")
))
.get().uri("/api/jwt-data")
.exchange()
.expectStatus().isOk();
}
@Test
public void testOAuth2Login() {
webTestClient
.mutateWith(mockOAuth2Login()
.attributes(attrs -> {
attrs.put("sub", "oauth-user");
attrs.put("name", "OAuth User");
attrs.put("email", "oauth@example.com");
}))
.get().uri("/oauth2/profile")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$.name").isEqualTo("OAuth User")
.jsonPath("$.email").isEqualTo("oauth@example.com");
}
@Test
public void testReactiveCsrfProtection() {
webTestClient
.mutateWith(csrf())
.mutateWith(mockUser())
.post().uri("/api/form")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.bodyValue("field=value")
.exchange()
.expectStatus().isOk();
}
}@Test
public void testSecurityConfiguration() {
// Test method security
webTestClient
.mutateWith(mockUser("user").roles("USER"))
.get().uri("/api/user-method")
.exchange()
.expectStatus().isOk();
webTestClient
.mutateWith(mockUser("user").roles("USER"))
.get().uri("/api/admin-method")
.exchange()
.expectStatus().isForbidden();
// Test reactive security context
webTestClient
.mutateWith(mockUser("testuser"))
.get().uri("/api/current-user")
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.isEqualTo("testuser");
}@Test
public void testAuthenticationFailures() {
// Test expired JWT
Jwt expiredJwt = Jwt.withTokenValue("expired-token")
.header("alg", "HS256")
.claim("sub", "user")
.claim("exp", Instant.now().minusSeconds(3600)) // Expired
.build();
webTestClient
.mutateWith(mockJwt().jwt(expiredJwt))
.get().uri("/api/secure")
.exchange()
.expectStatus().isUnauthorized();
// Test insufficient authorities
webTestClient
.mutateWith(mockUser("user").roles("USER"))
.get().uri("/api/admin-only")
.exchange()
.expectStatus().isForbidden();
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-security--spring-security-test