Add the service-to-service module
This commit is contained in:
53
service-to-service/docs/07-choosing.md
Normal file
53
service-to-service/docs/07-choosing.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 7. Choosing
|
||||
|
||||
*Prev: [6. mTLS](06-mtls.md)*
|
||||
|
||||
## 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
|
||||
|
||||
1. Every resource server validates **audience**, not just signature and expiry (chapter 4).
|
||||
2. No relay reads `SecurityContextHolder` from a thread the request did not create (chapter 2).
|
||||
3. Every service has a `SecurityFilterChain` bean, so nothing falls back to Boot's Basic default
|
||||
(chapter 5).
|
||||
4. Client registrations name `token-uri` / `jwk-set-uri` rather than `issuer-uri`, unless you
|
||||
want a startup-ordering dependency (chapter 1).
|
||||
5. 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).
|
||||
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](https://ankurm.com/spring-security-context-propagation-complete-guide/) — why the async relay returns 401
|
||||
- [The Spring Security Filter Chain Explained](https://ankurm.com/spring-security-filter-chain-explained/) — where `BearerTokenAuthenticationFilter` sits
|
||||
- [RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693) — token exchange
|
||||
- [RFC 9068](https://datatracker.ietf.org/doc/html/rfc9068) — the `at+jwt` access token profile
|
||||
- [RFC 8705](https://datatracker.ietf.org/doc/html/rfc8705) — mTLS client authentication and certificate-bound access tokens
|
||||
|
||||
---
|
||||
*Prev: [6. mTLS](06-mtls.md)*
|
||||
Reference in New Issue
Block a user