Skip to main content
Service principals enable machine-to-machine authentication for batch jobs, streaming tasks, and background processes. They support long-lived credentials (30-day refresh tokens) and can inherit permissions from user principals. See ADR-0033 for architectural details.

Overview

Service principals are first-class identities separate from users, designed for:
  • Batch ETL Jobs: Multi-hour data processing tasks
  • Streaming Connections: WebSocket connections requiring persistent auth
  • Background Processors: Queue processors with continuous authentication
  • Scheduled Reports: Automated report generation on behalf of users
  • CI/CD Pipelines: Deployment automation
  • API Integrations: Third-party systems with programmatic access

Authentication Modes

OAuth2 client credentials flow using Keycloak client configuration. Use when:
  • Dedicated service or microservice
  • OAuth2 compliance required
  • Rotating credentials needed
Setup:
Response:
Authentication:

Mode 2: Service Account User

Special user account marked as service principal. Use when:
  • Legacy system migration
  • Mixed authentication needs
  • Simpler deployment (username/password)
Setup:
Authentication:

Permission Inheritance

Service principals can inherit permissions from user principals via the acts_as relationship.

Example Scenario

Alice owns a conversation. She creates a service principal for scheduled reports:
OpenFGA Tuples Created:
Permission Check:

Long-Lived Sessions

Service principals support 30-day refresh tokens for persistent authentication.

Configuration

Client Implementation

Management Operations

List Service Principals

Rotate Secret

Delete Service Principal

Best Practices

Security

  • ✅ Store client secrets in secrets manager (not environment variables)
  • ✅ Rotate secrets every 90 days
  • ✅ Use IP whitelisting for sensitive services
  • ✅ Monitor service principal usage
  • ✅ Revoke unused service principals

Permissions

  • ✅ Use least privilege (only associate with user if needed)
  • ✅ Document permission inheritance in service description
  • ✅ Audit inherited access regularly
  • ✅ Create dedicated users for services when possible

Operations

  • ✅ Name services descriptively (e.g., “nightly-etl-job”)
  • ✅ Document purpose in description field
  • ✅ Tag owner for accountability
  • ✅ Monitor token refresh failures
  • ✅ Set alerts for authentication errors

Troubleshooting

Authentication Fails

Symptom: 401 Unauthorized when authenticating Solutions:
  • Verify client_id matches service_id
  • Check client_secret is correct
  • Ensure service principal is enabled
  • Verify Keycloak realm and endpoint URLs

Permission Denied

Symptom: 403 Forbidden when accessing resources Solutions:
  • Check if service has direct permissions
  • Verify acts_as relationship exists (if using inheritance)
  • Confirm associated user has required permissions
  • Check OpenFGA tuples: openfga-cli check

Token Expired

Symptom: 401 Unauthorized with “Token has expired” Solutions:
  • Implement automatic refresh before expiration
  • Check system clock synchronization (NTP)
  • Verify refresh token hasn’t expired (30 days)
  • Re-authenticate if refresh token expired

Examples

See examples/service_principals/ for complete examples:
  • batch_job_example.py - Batch processing with 12-hour runtime
  • streaming_example.py - WebSocket streaming with persistent auth
  • scheduled_task_example.py - Cron job with user permission inheritance

References

Architecture & API Docs