2.8 KiB
7. Choosing
Prev: 6. mTLS
Which propagation strategy
| Situation | Use |
|---|---|
| One hop, same team, same trust boundary, audit needs the user | Relay |
| A job with no user: scheduler, message listener, reconciliation | Client credentials |
| The next hop is another team's service, and audit needs the user | Token exchange |
| The next hop is outside your organisation | Client credentials, and a token minted for them |
The honest default is relay inside a boundary, exchange across one. Client credentials is the right answer more often than it is used for work with no user attached, and the wrong answer whenever somebody will later ask "who did this?".
Do you need any of this?
A callout that belongs in every article on this subject and is usually missing:
If your services are a single deployment behind one ingress, all of this is cost with no benefit. Two Spring Boot applications in one VPC, called by one another, with no multi-tenancy and no external partner, do not need an authorization server, a token exchange grant or a mesh. Network-level isolation plus a shared secret is a defensible design, and it is a design you can reason about at 3am. The machinery in this repository earns its keep when there are enough services, enough teams, or enough regulatory pressure that "who called this, on whose behalf, with what permission" has to be answerable from a log rather than from memory.
A checklist that is short on purpose
- Every resource server validates audience, not just signature and expiry (chapter 4).
- No relay reads
SecurityContextHolderfrom a thread the request did not create (chapter 2). - Every service has a
SecurityFilterChainbean, so nothing falls back to Boot's Basic default (chapter 5). - Client registrations name
token-uri/jwk-set-urirather thanissuer-uri, unless you want a startup-ordering dependency (chapter 1). - If identity arrives in a header, something upstream strips that header from every external request, and you can name the component that does it (chapter 6).
- Token lifetimes are short enough that the audience gap in item 1 is bounded even when somebody forgets.
Further reading
- Spring Security Context Propagation — why the async relay returns 401
- The Spring Security Filter Chain Explained — where
BearerTokenAuthenticationFiltersits - RFC 8693 — token exchange
- RFC 9068 — the
at+jwtaccess token profile - RFC 8705 — mTLS client authentication and certificate-bound access tokens
Prev: 6. mTLS