Chapter 18: Testing security configurations
The chapter introduction explains why regression tests and Spring Security integration tests are necessary when code or dependencies change.
After this chapter you will be able to
- Regression testing and continuous integration. Explain how tests help detect regressions when developers fix bugs or add features, and how continuous integration runs existing tests after code is uploaded and notifies the team of failures.
- Security integration testing priority. Justify testing an application's integration with Spring Security, especially when upgrading dependencies, and explain why security configuration tests should be part of the definition of done.
- Isolated authorization testing. Explain why mock users let authorization tests skip authentication and what those tests do—and do not—cover.
- Endpoint test outcomes. Describe how the section tests the /hello endpoint with and without a mock authenticated user, including the expected responses.
- UserDetailsService testing purpose. Explain why a test might load its user from a UserDetailsService rather than create a mock user.
- Authenticated test user setup. Describe how the section specifies a user from a UserDetailsService for an endpoint test.
- Custom SecurityContext control. Explain why a test might need a custom Authentication type and how a factory provides control over the test’s SecurityContext.
- Custom test annotation setup. Describe the three steps for connecting a custom test annotation to a factory-built SecurityContext, including why the annotation needs runtime retention.
- Authentication bypass in tests. Distinguish testing authorization with a supplied mock SecurityContext from testing the custom AuthenticationProvider’s authentication logic.
- Direct method security testing. Explain how to test a secured method without calling an endpoint: set up the test user or SecurityContext, inject the bean from the Spring context, and call its method directly instead of using MockMvc.
- Secured method test outcomes. Describe the three tested outcomes for NameService.getName(): no authenticated user causes AuthenticationException, an authenticated user without the expected write authority causes AccessDeniedException, and a user with that authority gets the expected result.
- Client-like authentication tests. Explain how a test can exercise authentication by sending a request like a normal client, and describe the expected results for valid and invalid HTTP Basic credentials in the custom-provider example.
- Mock resource server tokens. Distinguish how to supply mock JWT and opaque tokens in resource-server authentication tests, and explain how the test can assign the authorities needed for its scenario.
- CSRF protection test outcomes. Describe the two POST /hello test scenarios: a request without a CSRF token should receive 403 Forbidden, while one with a token should receive 200 OK. Explain that Spring Security’s csrf() RequestPostProcessor supplies the token for the test.
- CORS header test approach. Describe how to test a CORS policy by making an HTTP OPTIONS request like a browser preflight request and checking that the relevant response headers exist and have the correct values.
- Mock users in reactive tests. Explain how @WithMockUser supports a reactive security test and why the test uses WebTestClient rather than MockMvc.
- WebTestClientConfigurer test context. Describe what a WebTestClientConfigurer does in a reactive security test and give the examples provided in this section.
What it builds on
- Why is security important? (chapter 1) · The earlier emphasis on taking application security seriously.
- Using the SecurityContext (chapter 6) · The security context holds information about the user.
- Starting your first project (chapter 2) · The earlier /hello endpoint example supplies the endpoint being tested.
- Describing the user (chapter 3) · Users have details such as authorities.
- Understanding the UserDetailsService contract (chapter 3) · The UserDetailsService contract for loading user details
- Applying preauthorization rules (chapter 11) · Protecting method calls with preauthorization rules
- Implementing custom authentication logic (chapter 6) · the custom authentication logic being tested
- Using and configuring HTTP Basic (chapter 6) · HTTP Basic authentication
Section by section
Introduction
The chapter introduction explains why regression tests and Spring Security integration tests are necessary when code or dependencies change.
- Regression testing and continuous integration: Explain how tests help detect regressions when developers fix bugs or add features, and how continuous integration runs existing tests after code is uploaded and notifies the team of failures.
Why it matters: Automated tests give the team a warning when a seemingly useful change damages something that already worked. - Security integration testing priority: Justify testing an application's integration with Spring Security, especially when upgrading dependencies, and explain why security configuration tests should be part of the definition of done.
Why it matters: Security integration tests can expose problems introduced by an upgrade before the work is treated as complete.
Key terms: unit tests, integration tests, regression testing, continuous integration, integration, Spring Security, security configurations, definition of done
18.1 Using mock users for tests
This section shows how to test endpoint authorization with mock users while leaving the authentication process out of those tests.
- Isolated authorization testing: Explain why mock users let authorization tests skip authentication and what those tests do—and do not—cover.
Why it matters: It helps you interpret a passing test correctly and avoid repeating authentication work for every authorization rule. - Endpoint test outcomes: Describe how the section tests the /hello endpoint with and without a mock authenticated user, including the expected responses.
Why it matters: The paired cases show how to check both denial and permitted access to an endpoint. - Mock user setup options: Distinguish setting up a mock user with @WithMockUser from using a RequestPostProcessor, including when each configures the test environment.
Why it matters: Choosing a setup approach lets you give each test the user characteristics its scenario requires.
Key terms: mock user, security context, authentication, authorization, MockMvc, SecurityContext, /hello, 401 Unauthorized, 200 OK, @WithMockUser
18.2 Testing with users from a UserDetailsService
This section shows how to test an endpoint using a user loaded from a UserDetailsService instead of a mock user.
- UserDetailsService testing purpose: Explain why a test might load its user from a UserDetailsService rather than create a mock user.
Why it matters: The choice of test user determines whether the test includes the application's user-loading integration. - Authenticated test user setup: Describe how the section specifies a user from a UserDetailsService for an endpoint test.
Why it matters: The test needs both an available user service and a way to identify which user it should load.
Key terms: UserDetailsService, mock user, data source, UserDetailsService bean, @WithUserDetails, username
18.3 Using custom Authentication objects for testing
Shows how to give a security test a custom Authentication object by building its mock SecurityContext, and explains why that setup does not test authentication.
- Custom SecurityContext control: Explain why a test might need a custom Authentication type and how a factory provides control over the test’s SecurityContext.
Why it matters: This explains when the usual mock-user setup is not enough for a test. - Custom test annotation setup: Describe the three steps for connecting a custom test annotation to a factory-built SecurityContext, including why the annotation needs runtime retention.
Why it matters: The annotation, factory, and link are what make the chosen SecurityContext available to the test. - Authentication bypass in tests: Distinguish testing authorization with a supplied mock SecurityContext from testing the custom AuthenticationProvider’s authentication logic.
Why it matters: A passing test with a mock SecurityContext does not prove that the authentication provider accepts the user.
Key terms: SecurityContext, Authentication, factory class, @WithCustomUser, WithSecurityContextFactory, createSecurityContext(), @WithSecurityContext, RetentionPolicy.RUNTIME, custom AuthenticationProvider, mock SecurityContext
18.4 Testing method security
The section shows how to test method security by calling a Spring-managed bean directly and checking the results for different authenticated users.
- Direct method security testing: Explain how to test a secured method without calling an endpoint: set up the test user or SecurityContext, inject the bean from the Spring context, and call its method directly instead of using MockMvc.
Why it matters: This lets you test security rules even in an application with no web endpoints. - Secured method test outcomes: Describe the three tested outcomes for NameService.getName(): no authenticated user causes AuthenticationException, an authenticated user without the expected write authority causes AccessDeniedException, and a user with that authority gets the expected result.
Why it matters: Checking all three cases shows whether the method both rejects unauthorized calls and permits authorized ones.
Key terms: method security, SecurityContext, @WithMockUser, @WithUserDetails, MockMvc, NameService, getName(), @PreAuthorize, write, AuthenticationException
18.5 Testing authentication
Shows how to test authentication through client-like requests, including HTTP Basic, form login, and mock tokens for resource servers.
- Client-like authentication tests: Explain how a test can exercise authentication by sending a request like a normal client, and describe the expected results for valid and invalid HTTP Basic credentials in the custom-provider example.
Why it matters: These tests check whether the configured authentication logic actually accepts and rejects requests as intended. - Form login handler outcomes: Describe the three form-login cases tested and the observable response produced by the application's failure and success handlers.
Why it matters: Checking response headers and redirects catches mistakes in customized authentication handlers. - Mock resource server tokens: Distinguish how to supply mock JWT and opaque tokens in resource-server authentication tests, and explain how the test can assign the authorities needed for its scenario.
Why it matters: Mock tokens let resource-server tests exercise authentication scenarios that require particular authorities.
Key terms: authentication, httpBasic(), AuthenticationProvider, 401 Unauthorized, form login, AuthenticationFailureHandler, AuthenticationSuccessHandler, read authority, resource server, with(jwt())
18.6 Testing CSRF configurations
This section shows how to test that CSRF protection rejects a POST request without a token and accepts one with a token.
- CSRF protection test outcomes: Describe the two POST /hello test scenarios: a request without a CSRF token should receive 403 Forbidden, while one with a token should receive 200 OK. Explain that Spring Security’s csrf() RequestPostProcessor supplies the token for the test.
Why it matters: Both outcomes help verify that the endpoint’s CSRF protection works as expected. - Purpose of CSRF testing: Explain why tests of mutating endpoints may need to check CSRF protection: an attacker could otherwise trick a logged-in user into unwanted actions, and Spring Security uses CSRF tokens to mitigate that risk.
Why it matters: It explains why a security test should exercise mutating requests, not just GET requests.
Key terms: CSRF token, RequestPostProcessor, csrf(), 403 Forbidden, 200 OK, CSRF vulnerability, CSRF protection, mutating operation
18.7 Testing CORS configurations
The section explains how to test CORS policies by making a preflight-style request and checking the response headers.
- CORS header test approach: Describe how to test a CORS policy by making an HTTP OPTIONS request like a browser preflight request and checking that the relevant response headers exist and have the correct values.
Why it matters: Checking the returned headers verifies what the CORS policy tells a browser about the response. - Cross-origin policy purpose: Explain why CORS policies matter when an app loaded from one origin uses a response from another, and how response headers express the policy.
Why it matters: This explains why the test inspects response headers rather than just the request’s outcome.
Key terms: CORS policies, preflight request, HTTP OPTIONS, Access-Control-Allow-Origin, Access-Control-Allow-Methods, origin, response headers
18.8 Testing reactive Spring Security implementations
This section explains two ways to test security in reactive Spring applications: mock users with @WithMockUser and test-context configuration with WebTestClientConfigurer.
- Mock users in reactive tests: Explain how @WithMockUser supports a reactive security test and why the test uses WebTestClient rather than MockMvc.
Why it matters: It lets you test a reactive endpoint’s authorization rules without making the test authenticate a real user. - WebTestClientConfigurer test context: Describe what a WebTestClientConfigurer does in a reactive security test and give the examples provided in this section.
Why it matters: It provides another way to set up security-related conditions for reactive tests, including mock users and CSRF tokens.
Key terms: @WithMockUser, WebTestClient, MockMvc, SecurityContext, mock user, WebTestClientConfigurer, RequestPostProcessor, CSRF token, test context
18.9 Summary
Concepts explained in this chapter
- mock userA mock user is a test fixture that represents an authenticated user without performing the normal authentication process.
- RequestPostProcessorA request postprocessor is a test component that modifies or prepares a simulated HTTP request before it is executed.
- authorization constraintAn authorization configuration is a set of rules that determines which authenticated or unauthenticated requests may access application functionality.
- @WithMockUser@WithMockUser is a Spring Security test annotation that establishes a SecurityContext containing a configured mock authenticated user.
- MockMvcMockMvc is a Spring testing utility that performs simulated HTTP requests against MVC application components without requiring a running server.
- @SpringBootTest@SpringBootTest is a Spring Boot test annotation that loads an application context for integration testing.
- method-level securityGlobal method security is a method-authorization capability that applies authorization rules across application methods.
- Spring SecuritySpring Security is an open-source framework for securing Spring applications through authentication, authorization, access control, and protection against common attacks.
- opaque tokenAn opaque token is an access token whose contents do not reveal claims or other usable information to the resource server, which must obtain its validity and associated details from the authorization server.
- custom authentication logicCustom authentication logic is application-defined processing that verifies a user's identity instead of relying entirely on a framework's default authentication behavior.
- custom authentication objectA custom authentication object is an application-defined authentication-token subtype that carries identity, authorities, and additional authentication data.
- security contextA security context is a Spring Security object that holds authentication information associated with the current execution or request.
- CORSCross-origin resource sharing is a browser security mechanism that controls whether a web page may access resources from another origin.
- Access-Control-Allow headersAccess-Control-Allow-Origin is an HTTP response header that specifies which origins may access a resource through cross-origin requests.
- access-control-allow-methodsAccess-Control-Allow-Methods is an HTTP response header that specifies the HTTP methods permitted for cross-origin requests.
- preflight requestA preflight request is a browser-generated HTTP request that tests whether a cross-origin request is permitted before the browser sends the original request.
- UserDetailsServiceUserDetailsService is a Spring Security interface for retrieving user-specific data needed to authenticate a user.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
