Security — Cheat Sheet
Microservices · 4 topics. Download the PDF or the Instagram carousel and share it.
Cheat Sheet · AiCanCode.org
Security
Microservices4 topicsQuick revision reference
1
Service-to-Service Authentication
Mutual TLS or short-lived JWT access tokens (client credentials flow) authenticate services with each other; avoid embedding long-lived secrets in code.
- ✓Never use long-lived shared API keys between services — use short-lived tokens (15min–1h) or mTLS certificates.
- ✓Client Credentials flow: service obtains a token from the auth server, attaches it as Bearer in every request.
- ✓Spring Security resource server validates JWT signature via JWKS URI — no shared secret, no round-trip to auth server per request.
- ✓mTLS via Istio is transparent to application code — Envoy sidecar handles TLS handshake and certificate rotation.
- ✓Inject client_secret via environment variable or Vault — never hardcode in application.properties or source code.
- ✓Use scopes to limit what each service is permitted to do — payments:read vs payments:create as separate scopes.
Properties + Java — OAuth2 client credentials flow
# application.properties — order-service calling payment-service
spring.security.oauth2.client.registration.payment-service.client-id=order-service
spring.security.oauth2.client.registration.payment-service.client-secret=${CLIENT_SECRET}
spring.security.oauth2.client.registration.payment-service.authorization-grant-type=client_credentials
spring.security.oauth2.client.registration.payment-service.scope=payments:create
spring.security.oauth2.client.provider.keycloak.token-uri= https://keycloak.internal/realms/platform/protocol/openid-connect/token
# Configure WebClient with OAuth2 token auto-injection
@Configuration
public class WebClientConfig {
@Bean
public WebClient paymentWebClient(
OAuth2AuthorizedClientManager clientManager) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2 =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientManager);
oauth2.setDefaultClientRegistrationId("payment-service");
return WebClient.builder()
.baseUrl("https://payment-service.internal")
.filter(oauth2) // automatically attaches Bearer token
.build();
}
}2
JWT in Microservices
The API gateway validates the JWT and forwards claims downstream as trusted headers; each service reads claims without needing a round-trip to the auth server.
- ✓JWTs are stateless signed tokens — any service with the public key can validate them without calling the auth server
- ✓API gateway validates JWT once and forwards decoded claims as trusted headers (X-User-Id, X-Roles) downstream
- ✓Downstream services must only trust claim headers from internal gateway network, never from external clients
- ✓Spring Security Resource Server auto-validates JWT signature, expiry, issuer, and audience with zero custom code
- ✓Token relay propagates the original JWT on downstream calls; use Client Credentials for machine-to-machine calls
- ✓JWT revocation challenge: tokens are valid until expiry — use short expiry (5–15 min) + refresh tokens or a revocation list
YAML — JWT structure and Spring Boot Resource Server auto-validation
# JWT structure (decoded)
# Header: {"alg": "RS256", "typ": "JWT", "kid": "key-id-1"}
# Payload: {
# "sub": "user-123", ← subject (user id)
# "iss": "https://auth.example.com",
# "aud": "order-service",
# "exp": 1716840000, ← expiry unix timestamp
# "iat": 1716836400,
# "roles": ["USER", "ORDER_MANAGER"],
# "tenantId": "tenant-abc"
# }
# Signature: RS256(base64(header) + "." + base64(payload), private_key)
# application.yml — resource server validates JWT automatically
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://auth.example.com # fetches JWKS from /.well-known/openid-configuration
# or explicitly:
jwks-uri: https://auth.example.com/.well-known/jwks.json
# Spring Security auto-validates: signature, exp, iss, aud
# Access current user in controller:
# @AuthenticationPrincipal Jwt jwt
# jwt.getClaimAsString("tenantId")
# jwt.getClaimAsStringList("roles")3
Secrets Management
Inject secrets via HashiCorp Vault, AWS Secrets Manager, or Kubernetes Secrets mounted as env variables; never commit credentials to source control.
- ✓Never commit secrets to source control — use .gitignore, pre-commit hooks, and git-secrets scanning
- ✓Kubernetes Secrets are base64-encoded (not encrypted) — enable etcd encryption at rest in production clusters
- ✓Volume-mounted secrets are safer than environment variables — env vars are exposed in process listings and debug outputs
- ✓Vault dynamic secrets generate short-lived credentials per request — leaked credentials expire automatically
- ✓Vault Agent Injector injects secrets as files via pod annotations, removing Vault SDK dependency from applications
- ✓Cloud IRSA (IAM Roles for Service Accounts) eliminates static AWS credentials entirely — pods assume roles dynamically
YAML — Kubernetes Secret as env var and file mount
# Create a Secret
kubectl create secret generic db-credentials \
--from-literal=username=app_user \
--from-literal=password=supersecret
# Pod spec — mount as files (preferred over env vars)
apiVersion: v1
kind: Pod
spec:
containers:
- name: order-service
image: order-service:1.0.0
# Option 1: env var injection (simpler but less secure)
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
# Option 2: volume mount (safer — not in process env)
volumeMounts:
- name: db-secret
mountPath: /etc/secrets/db
readOnly: true
volumes:
- name: db-secret
secret:
secretName: db-credentials
defaultMode: 0400 # owner read-only
# Spring Boot reads file-based secrets:
# spring.datasource.password=${file:/etc/secrets/db/password}4
Zero-Trust Networking
No implicit trust is granted based on network location; every request is authenticated and authorised, enforced by a service mesh (Istio/Linkerd) or explicit token validation.
- ✓Never trust the network perimeter — every request must carry verifiable identity
- ✓mTLS authenticates both caller and callee; Istio automates cert rotation via SPIFFE/SPIRE
- ✓AuthorizationPolicy (Istio) or Spring Security restrict access to specific service identities
- ✓JWTs carry claims (sub, roles, aud) that are validated cryptographically — no session state needed
- ✓Least privilege: grant only the minimum permissions each service needs to function
- ✓Audit logs at the mesh layer capture every service-to-service call for compliance and forensics
YAML — Istio PeerAuthentication + AuthorizationPolicy
# Enable STRICT mTLS for the entire namespace
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: orders
spec:
mtls:
mode: STRICT
---
# Only allow order-service to call payment-service POST /payments
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: payment-authz
namespace: payments
spec:
selector:
matchLabels:
app: payment-service
rules:
- from:
- source:
principals: ["cluster.local/ns/orders/sa/order-service"]
to:
- operation:
methods: ["POST"]
paths: ["/payments"]Learn this free with Aria, your AI tutor → AiCanCode.org/learn/microservices