1
0
Files
spring-security-demo/service-to-service/README.md

5.3 KiB

service-to-service — token relay, client credentials, exchange and mTLS

Companion project for Securing Spring Boot Microservices: Token Relay, Service-to-Service JWT and mTLS on ankurm.com.

Four real processes and a real Spring Authorization Server, so that questions like "whose identity arrives at the last service?" and "what does that service actually check?" have transcripts for answers. Everything under docs/output/ was produced by scripts/run-all.sh.

Versions

Version Notes
JDK 25 (Temurin 25.0.4.1+1) current LTS
Spring Boot 4.1.1 inherited as parent
Spring Framework 7.0.9
Spring Security 7.1.1 resource server, OAuth2 client, authorization server
Spring Cloud 2025.1.3 (gateway 5.0.3) built against Boot 4.0.8 — see docs/01
Tomcat 11.0.24

Versions were read from repo1.maven.org/.../maven-metadata.xml.

Quickstart

./scripts/run.sh                      # all four processes, in order
TOKEN=$(./scripts/user-token.sh)      # a real authorization_code + PKCE flow, in curl
./scripts/claims.sh "$TOKEN"

curl -H "Authorization: Bearer $TOKEN" 127.0.0.1:8081/edge/relay
curl -H "Authorization: Bearer $TOKEN" 127.0.0.1:8081/edge/client-credentials
curl -H "Authorization: Bearer $TOKEN" 127.0.0.1:8081/edge/exchange

STRICT=true ./scripts/run.sh          # issuer + audience + RFC 9068 validation
./scripts/certs.sh && ./scripts/run-all.sh
mvn test                              # the 8 validator assertions
./scripts/stop.sh

The user is alice / password.

Processes

Process Port Main class Role
authserver 9000 AuthServerApplication Spring Authorization Server. Mints every token used here
gateway 8080 GatewayApplication Spring Cloud Gateway Server MVC, with and without TokenRelay
edge 8081 EdgeApplication Resource server and OAuth2 client
downstream 8082 DownstreamApplication Resource server. Reports who it thinks is calling
mtls 8443 MtlsApplication Certificate authentication instead of tokens

Endpoints

Endpoint Strategy
GET /edge/naive No token forwarded — the control
GET /edge/relay The incoming bearer token, unchanged
GET /edge/client-credentials The edge service's own identity
GET /edge/exchange RFC 8693 token exchange
GET /edge/relay-async Relay from another thread — the ThreadLocal trap
GET /orders Downstream. Echoes sub, aud, scope, client_id, cnf
GET /mtls/whoami The verified certificate identity
GET /mtls/trusted-header An identity taken from a header, verified by nothing

Switches

Switch Effect
STRICT=true ./scripts/run.sh Authorization server emits RFC 9068 tokens; downstream validates issuer, audience and the required-claim set
RS_LOG_LEVEL / CLIENT_LOG_LEVEL / AS_LOG_LEVEL / GATEWAY_LOG_LEVEL DEBUG on the corresponding package

Documentation

Chapter
01 The four processes, a browser flow in curl, and four things that cost time
02 Relay, client credentials, token exchange — and the thread that loses the token
03 OAuth2ClientHttpRequestInterceptor and which OAuth2AuthorizedClientManager
04 What a resource server does not validate by default
05 What TokenRelay actually relays
06 Mesh mTLS versus in-application mTLS
07 Choosing, and whether you need any of it

Captured output

File
01-user-token.txt A complete authorization_code + PKCE flow, in curl
02-five-strategies.txt Five propagation strategies, one request
03-audience-ignored.txt A token for another service, accepted with HTTP 200
04-gateway-token-relay.txt The same route with and without TokenRelay
05-strict-validation.txt Strict validation, and what turning it on breaks
06-mtls.txt Two certificates with the same subject and different issuers
07-tests.txt mvn test