0
0
Microservicessystem_design~7 mins

OAuth 2.0 for microservices - System Design Guide

Choose your learning style9 modes available
Problem Statement
When multiple microservices need to securely communicate and verify user identity, relying on each service to handle authentication separately leads to inconsistent security, duplicated effort, and potential vulnerabilities. Without a centralized authorization mechanism, services may expose sensitive data or fail to enforce proper access controls, risking data breaches and unauthorized actions.
Solution
OAuth 2.0 provides a standardized way for microservices to delegate user authentication and authorization to a trusted authorization server. Services receive access tokens that prove the user's identity and permissions, allowing them to verify requests without managing credentials themselves. This centralizes security, reduces duplication, and enables fine-grained access control across services.
Architecture
┌───────────────┐       ┌────────────────────┐       ┌───────────────┐
│               │       │                    │       │               │
│   Client App  ├──────▶│ Authorization Server├──────▶│   Microservice│
│               │       │                    │       │               │
└───────────────┘       └────────────────────┘       └───────────────┘
         │                        ▲                          │
         │                        │                          │
         │                        │                          │
         │                        │                          │
         └────────────────────────┴──────────────────────────┘

Legend:
Client App requests access token from Authorization Server.
Authorization Server issues token after user authentication.
Client App calls Microservice with token.
Microservice validates token with Authorization Server or introspection endpoint.

This diagram shows the flow where a client app obtains an access token from an authorization server and then calls a microservice with that token. The microservice validates the token to authorize the request.

Trade-offs
✓ Pros
Centralizes authentication and authorization logic, reducing duplicated code in microservices.
Enables fine-grained access control with scopes and roles embedded in tokens.
Improves security by avoiding direct credential sharing between services.
Supports token expiration and revocation for better session management.
✗ Cons
Adds complexity with the need for an authorization server and token management.
Token validation can introduce latency if done synchronously via introspection.
Requires careful token design to avoid overly large tokens or insufficient permissions.
Use OAuth 2.0 when your system has multiple microservices requiring secure, delegated user authorization, especially when user identity and permissions must be consistently enforced across services at scale (hundreds to thousands of requests per second).
Avoid OAuth 2.0 if your system is a simple monolith or has very low inter-service communication where simpler authentication methods suffice, as the overhead of token management may outweigh benefits.
Real World Examples
Netflix
Uses OAuth 2.0 tokens to authorize user requests across many microservices, ensuring consistent access control for streaming content.
Uber
Employs OAuth 2.0 to manage user permissions and secure communication between rider, driver, and backend microservices.
Google
Implements OAuth 2.0 extensively to allow users to authorize third-party apps and to secure internal microservice interactions.
Code Example
The before code shows a microservice directly validating user credentials, which duplicates authentication logic and is insecure. The after code shows the microservice validating an OAuth 2.0 JWT access token issued by an authorization server, checking scopes for authorization. This centralizes auth and improves security.
Microservices
### Before: Microservice directly checks user credentials (bad practice)

class Microservice:
    def handle_request(self, user_credentials):
        if not self.validate_user(user_credentials):
            return "Unauthorized"
        return "Data for user"

    def validate_user(self, creds):
        # Naive check, duplicates auth logic
        return creds == "valid_password"


### After: Microservice validates OAuth 2.0 access token

import jwt

class Microservice:
    AUTH_SERVER_PUBLIC_KEY = "<public_key_here>"

    def handle_request(self, access_token):
        try:
            payload = jwt.decode(access_token, self.AUTH_SERVER_PUBLIC_KEY, algorithms=["RS256"])
            if "read:data" in payload.get("scopes", []):
                return "Data for user"
            else:
                return "Forbidden: insufficient scope"
        except jwt.ExpiredSignatureError:
            return "Unauthorized: token expired"
        except jwt.InvalidTokenError:
            return "Unauthorized: invalid token"
OutputSuccess
Alternatives
API Key Authentication
Uses static keys for service authentication without user delegation or fine-grained scopes.
Use when: Choose when services only need simple authentication without user context or complex permissions.
Mutual TLS (mTLS)
Uses client and server certificates for mutual authentication at the transport layer, not user authorization.
Use when: Choose when strong service-to-service authentication is needed without user identity delegation.
JWT without OAuth
Services issue and validate JWT tokens independently without a centralized authorization server.
Use when: Choose when you want lightweight token-based auth but can manage token issuance and revocation internally.
Summary
OAuth 2.0 centralizes authorization for microservices by issuing access tokens that prove user permissions.
Microservices validate tokens to enforce consistent access control without managing user credentials.
This pattern improves security and scalability but adds complexity with token management and validation.