A JWT authorization trace follows token validation, endpoint scope, method ownership and database lookup in that order.
Spring security exercise: trace four JWT request outcomes
Predict before running
For a GET /contract/tenant/tenant-east, predict the status when a signed token has tenant-east and receipt.read. Repeat with receipt.write, with tenant-west in the URL, and with tenant_id absent. Keep the token issuer, audience and signature valid in each case so only one boundary changes. Write down which layer rejects each request, not only its status code.
The source-kit outcomes are 200 for the matching request, 403 for wrong scope, 403 for wrong tenant and 401 for missing tenant claim. The matching response is tenant-east:accepted from H2. The wrong-tenant request does not return tenant-west:held. Compare scope and ownership before reading the test code. The fixture includes X-Tenant spoofing in both allowed and denied cases.
Extend the exercise
Add a token with a valid tenant_id syntax but a tenant unknown to the application. Decide whether the decoder, service or membership layer should reject it and explain why. The current fixture does not consult a tenant registry, so do not claim it already solves that case. For a write variant, assert the database rows after every denial. This exercise has no hosted judge; run the downloadable JUnit test locally and compare both response and state.
Checked source
mvn -q -Dtest=JwtTenantBoundaryTest testVerification 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 four status outcomes are local MockMvc checks. This exercise does not grade remote submissions or simulate a real issuer. The JUnit run creates a small RSA key and H2 database per local context; no workload result follows from it.
Common Mistakes
- Do not say every 403 came from the same rule.
- Do not use a header value to repair a missing token claim.
- Do not treat a valid token as permission for every tenant.
Read next
Test Spring JWT authorization through filters, service proxy and SQL, Spring Security scope versus tenant ownership: two separate decisions, Spring JWT tenant claims: reject missing or malformed ownership before conversion.
