- JWT bearer authentication via spring-boot-starter-oauth2-resource-server, validated against
an RSA keypair DemoJwtIssuer generates and signs with locally, so the whole module runs and
tests deterministically with no external Authorization Server.
- @PreAuthorize on @McpTool methods maps SCOPE_orders:read / SCOPE_orders:write to lookup_order
and refund_order -- confirmed empirically that method security actually applies to a bean the
MCP server autoconfiguration invokes via reflection, since it invokes the Spring-proxied bean.
- SecurityFilterChain requires authentication on every request, so tool discovery (initialize/
tools-list) is rejected before it ever reaches the MCP dispatcher -- no anonymous tool listing.
- ToolAuditAspect logs every tool call through MDC (subject, scopes, tool, outcome), pinned to
@Order(150) -- between AuthorizationInterceptorsOrder.PRE_FILTER (100) and PRE_AUTHORIZE (200)
-- so it wraps @PreAuthorize's interceptor and still logs denied calls, not only successful
ones. Verified with a real Logback ListAppender reading back real MDC contents.
Two real findings worth a note: Spring Boot 4.0 renamed spring-boot-starter-aop to
spring-boot-starter-aspectj (the old artifact stops existing after 4.0.0-M2); and Spring AI's
AbstractSyncMcpToolMethodCallback.createSyncErrorResult concatenates an exception's message with
its root cause's message, which duplicates the text when they're the same exception -- visible
directly in the captured output when @PreAuthorize denies a call ("Access Denied\nAccess Denied").
5/5 tests pass against a real running server over real Streamable HTTP, with real signed JWTs.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FtpJvZfg4nvLvtzgJTDWpB
9 lines
352 B
Bash
Executable File
9 lines
352 B
Bash
Executable File
#!/usr/bin/env bash
|
|
# Regenerates output/01 through output/05 (the test suite writes these itself, overwriting
|
|
# each file in place). output/06-starter-aop-renamed.txt is a separately captured investigation
|
|
# transcript, not test output -- its own header says how to reproduce it.
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
rm -rf target
|
|
mvn -q -o test
|