Skip to main content

Service Communication

How SVA services communicate securely with each other.

Overview

SVA OAuth consists of three main services that need to communicate:

  1. SVA OAuth Provider (sva_oauth) - Public-facing OAuth server
  2. SVA Core (sva_server) - User account and vault management
  3. SVA Client (sva_client) - User-facing consent UI

Communication Model

┌──────────────┐         ┌──────────────┐         ┌──────────────┐
│ SVA Client │────────▶│ SVA Core │────────▶│ SVA OAuth │
│ (Frontend) │ │ (Server) │ │ Provider │
└──────────────┘ └──────────────┘ └──────────────┘

Service Token Authentication

All inter-service communication uses a shared secret token.

Configuration

Both services must have the same INTERNAL_SERVICE_TOKEN:

# sva_oauth/backend/config/settings.py
INTERNAL_SERVICE_TOKEN = os.getenv('INTERNAL_SERVICE_TOKEN', 'dev-shared-secret')

# sva_server/backend/settings.py
INTERNAL_SERVICE_TOKEN = os.getenv('INTERNAL_SERVICE_TOKEN', 'dev-shared-secret')

Service-to-service requests include the token in headers:

headers = {
'X-Service-Token': INTERNAL_SERVICE_TOKEN
}

Internal Endpoints

SVA OAuth Internal Endpoints

These endpoints are only accessible with service token authentication:

Get Auth Request Details

GET /api/auth/internal/auth-request-details/?auth_request_id={id}
Headers: {
"X-Service-Token": "shared-secret"
}

Response:

{
"auth_request_id": "uuid",
"status": "pending",
"expires_at": "2024-01-01T00:00:00Z",
"requested_scopes": ["email", "profile"],
"scope_details": [...],
"state": "state-parameter",
"redirect_uri": "https://app.com/callback/",
"client": {
"client_id": "client_id",
"name": "App Name",
"logo": "https://...",
"description": "App description"
}
}
POST /api/auth/internal/consent-complete/
Headers: {
"X-Service-Token": "shared-secret"
}
Body: {
"auth_request_id": "uuid",
"user_id": "user_id",
"approved_scopes": ["email", "profile"],
"data_token": "jwt-token"
}

Response:

{
"redirect_uri": "https://app.com/callback/",
"authorization_code": "code",
"state": "state-parameter"
}

SVA Core Internal Endpoints

These endpoints proxy requests to SVA OAuth:

Get Auth Request (Proxy)

GET /api/internal/oauth/requests/{auth_request_id}/
Headers: {
"Authorization": "Bearer user-session-token"
}

Flow:

  1. SVA Client calls SVA Core
  2. SVA Core validates user session
  3. SVA Core proxies to SVA OAuth with service token
  4. SVA Core returns response to SVA Client

Attest Data

POST /api/internal/attest-data/
Headers: {
"Authorization": "Bearer user-session-token"
}
Body: {
"auth_request_id": "uuid",
"user_id": "user_id",
"audience": "client_id",
"claims": {
"email": "[email protected]",
"name": "John Doe"
}
}

Response:

{
"data_token": "jwt-token"
}
POST /api/internal/oauth/requests/{auth_request_id}/complete/
Headers: {
"Authorization": "Bearer user-session-token"
}
Body: {
"approved_scopes": ["email", "profile"],
"data_token": "jwt-token"
}

Flow:

  1. SVA Client calls SVA Core
  2. SVA Core validates user session
  3. SVA Core proxies to SVA OAuth with service token
  4. SVA Core returns response to SVA Client

Security Model

Service Token

  • Purpose: Authenticate service-to-service requests
  • Storage: Environment variable
  • Strength: Strong, randomly generated secret
  • Rotation: Should be rotated periodically

Network Isolation

  • Services communicate via internal network addresses
  • Production: Use private network (e.g., Docker network)
  • Development: Use localhost with different ports

HTTPS

  • All production communication over HTTPS
  • Internal services can use HTTP if on private network
  • Public endpoints must use HTTPS

Error Handling

Invalid Service Token

# Returns 401 Unauthorized
{
"error": "Invalid service token"
}

Service Unavailable

# Returns 503 Service Unavailable
{
"error": "Service temporarily unavailable"
}

Timeout Configuration

# sva_server/backend/settings.py
INTERNAL_SERVICE_TIMEOUT = 5 # seconds

Example: Service-to-Service Call

import requests
from django.conf import settings

def get_auth_request_details(auth_request_id):
"""Call SVA OAuth from SVA Core"""
url = f"{settings.SVA_AUTH_SERVER_BASE_URL}/api/auth/internal/auth-request-details/"
headers = {
'X-Service-Token': settings.INTERNAL_SERVICE_TOKEN
}
params = {
'auth_request_id': auth_request_id
}

response = requests.get(url, headers=headers, params=params, timeout=5)
response.raise_for_status()
return response.json()

Best Practices

  1. Use environment variables - Never hardcode service tokens
  2. Rotate tokens regularly - Change service tokens periodically
  3. Use HTTPS in production - Encrypt all communication
  4. Implement timeouts - Prevent hanging requests
  5. Log service calls - Monitor inter-service communication
  6. Handle errors gracefully - Implement retry logic
  7. Validate responses - Check response structure

Next Steps