Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Test Spring JWT authorization through filters, service proxy and SQL

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A security integration test must exercise every layer named in its claim: decoder, filter chain, managed service and scoped query.

Download Spring source kit

The fixture installs actual local components

JwtTenantBoundaryTest creates a Spring web application context, installs springSecurity() on MockMvc, registers a JWT decoder, and calls a managed @PreAuthorize reader backed by JdbcTemplate. It checks success for the matching tenant, 403 for wrong scope, 403 for wrong tenant, 401 for missing tenant claim, and distinct H2 rows under one receipt ID. A direct call to the target method would miss both filters and the proxy rule.

This is broader than standalone MockMvc, which registers a controller directly. It is still a local context, not the site's full Boot application component scan or a live server. The signing keys are generated in the test, not discovered through remote JWKS. The failure-layer lesson explains how to state that evidence honestly.

Keep negative cases tied to state

The test's denied reads return no protected value. For a write, also inspect the database afterward to prove that no mutation occurred. Add an untrusted-header case because a path-only denial can miss an identity override. Before release, repeat these checks against the deployed route, actual issuer and target database, including issuer outage and key rotation.

Checked source

Java
client = MockMvcBuilders.webAppContextSetup(context)
    .apply(springSecurity()).build();

client.perform(get("/contract/tenant/tenant-west")
    .header("Authorization", "Bearer " + eastToken))
    .andExpect(status().isForbidden());

Verification boundary

JwtTenantBoundaryTest.trustedTenantClaimPassesTheMatchingServiceRule, JwtTenantBoundaryTest.wrongScopeIsForbiddenBeforeTheService, JwtTenantBoundaryTest.anotherTenantIsForbiddenAfterAuthentication and JwtTenantBoundaryTest.missingTenantClaimIsRejectedByTheDecoder runs in the downloadable Spring source kit. The excerpt is shortened; the kit contains the complete test.

Costs and limits

The five local tests create an in-memory H2 database and web context per method. They cost more than a plain unit test but omit remote issuer discovery, application deployment, gateway behavior, real database grants and write-side effects. No performance or production trust claim follows from their speed.

Common Mistakes

  • Do not call a direct service-object test proof of a security filter.
  • Do not call MockMvc proof of a deployed proxy path.
  • Do not infer database safety from a 403 without checking the protected state.

Read next

Spring Security JWT tenant principal: map only a validated claim, Spring Security scope versus tenant ownership: two separate decisions, Spring JdbcTemplate tenant predicates: put ownership in the SQL query, Spring MockMvc standalone tests: know which HTTP layers were assembled.

Continue with checked tenant commands

Continue with Spring command rollback test: inspect state after an injected failure.

spring
spring-boot
jwt-web-context-test
Storage details