Um momento
0xD0Lesson 14 of 15

Securing service-to-service traffic

Apply zero trust inside the system: authenticate users at the edge with tokens, authenticate services with mTLS, and authorize every call.

26 min 7-question quiz 2 code exercises
By the end of this lesson you can
  • Explain zero trust and why the internal network isn’t a safe zone
  • Validate JWT access tokens: signature, expiry, audience and scopes
  • Authenticate services with mutual TLS and authorize calls with least privilege

In the monolith, “inside the server” meant safe. With microservices, dozens of services talk over a network - and if an attacker compromises one (say, through a vulnerable library in Recommendations), a flat, trusting internal network lets them call Payments directly. Zero trust: never trust a call just because it comes from inside; authenticate and authorize every one.

  • Users sign in once with an identity provider (OAuth 2.0 / OpenID Connect) and get an access token, usually a JWT. The gateway validates it, and services check what they need.
  • Services prove their identity to each other with mutual TLS (mTLS): both sides present certificates, so Payments knows the caller really is Ordering - and the traffic is encrypted. Service meshes can issue and rotate these certificates automatically.
  • Authorization with least privilege: Ordering may call POST /charges on Payments; Recommendations may not.
a JWT, decoded
1// header
2{"alg": "RS256", "kid": "noodle-key-7"}
3// payload (claims)
4{"sub": "user-123", "iss": "https://auth.galacticnoodle.space", "aud": "noodle-api",
5 "exp": 1791000000, "scope": "orders:read orders:write"}
6// signature: RS256 over header.payload with the identity provider's private key

Validating a JWT means checking, in order: the signature (with the issuer’s public key - never trust an unsigned token or alg: none), the issuer (iss), the expiry (exp), the audience (aud - a token for another API must be rejected), and then the scopes the endpoint needs. The payload is only base64-encoded, not encrypted: anyone can read it, so never put secrets in it.

read_claims.py
1import base64
2import json
3
4token = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyLTEyMyIsImF1ZCI6Im5vb2RsZS1hcGkiLCJleHAiOjE3OTEwMDAwMDAsInNjb3BlIjoib3JkZXJzOnJlYWQifQ.c2lnbmF0dXJl"
5header, payload, signature = token.split(".")
6claims = json.loads(base64.urlsafe_b64decode(payload + "=" * (-len(payload) % 4)))
7print(claims)
8print("can write orders:", "orders:write" in claims["scope"].split())
Output
{'sub': 'user-123', 'aud': 'noodle-api', 'exp': 1791000000, 'scope': 'orders:read'}
can write orders: False

Key takeaways

  • Zero trust: the internal network isn’t safe; authenticate and authorize every call.

  • Users get tokens (OAuth 2.0/OIDC, JWTs); validate signature, issuer, expiry and audience, then scopes.

  • Services authenticate each other with mTLS, often managed by a service mesh.

  • Grant each service only the calls it needs, and keep secrets out of tokens, images and code.

Lesson quiz

7 questions · pass with 5 correct · up to 50 XP

Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.

Practice: simulate microservice patterns in Python

Build small Python simulations of the patterns - routers, sagas, outboxes, circuit breakers, traces - and run them against sample inputs. They run locally in your browser; no servers or containers needed.

Exercise 1

Check token claims

+25 XP

The first input line is now audience required_scope. Each following line is a JWT. (Assume the gateway already verified each signature - this exercise checks the claims.) Decode each payload (base64url, padding stripped) and check, in order: aud must equal the audience, exp must be in the future (greater than now), and the space-separated scope must include the required scope.

Print user-123: allowed or user-9: denied (expired) with the first failing reason: wrong audience, expired or missing scope orders:write.

  • Four tokens
main.py
Loading editor…

Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.

Exercise 2

Enforce service-to-service policy

+25 XP

The input has policy rules caller -> callee METHOD path-prefix (method * allows any), ---, then calls caller -> callee METHOD path. A call is allowed if any rule matches: same caller and callee, method equal or *, and the path equals the prefix or starts with prefix + /. Everything else is denied (default deny). Print ALLOW ordering -> payments POST /charges/9 or DENY ..., then denied: N of M calls.

  • Noodle policy
main.py
Loading editor…

Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.

Questions about this lesson

Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.

Loading posts…

Gostou da aula? 😆👍
Apoie nosso trabalho com uma doação: