Auth Service
The Auth Service provides centralized Role-Based Access Control (RBAC) and permission management for the Rippler platform. It manages roles, permissions, principal bindings, and validates access requests with caching for performance.
Architecture Diagram
The following diagram illustrates the internal architecture of the Auth Service, showing the flow from API requests through role and permission management, caching layers, integration with Keycloak JWT validation, and data persistence.
To view and edit the architecture diagram:
- Open
/docs/architecture/services/auth-service.drawioin diagrams.net or VS Code with the Draw.io extension - The diagram shows the complete RBAC architecture including role management, permission checking, Redis caching, PostgreSQL persistence, and Keycloak integration
- After making changes, export to HTML and copy to
/website/static/architecture/services/auth-service.drawio.html
Overview
Port: 18008
Technology: Spring Boot 3.2.0, Java 17, PostgreSQL, Redis
API Prefix: /api/v1
Features
- ✅ Role management (create, list, assign permissions)
- ✅ Permission management with resource types
- ✅ Principal (user/service account) management
- ✅ Role bindings with optional resource scoping
- ✅ Permission checks with Redis caching (10 min TTL)
- ✅ Flyway database migrations
- ✅ Integration with Keycloak for JWT validation
Architecture
graph TD
A[Client] -->|JWT Token| B[Auth Service]
B -->|Validate| C[Keycloak JWKS]
B -->|Query| D[PostgreSQL]
B -->|Cache| E[Redis]
B -->|Return| A
Database Schema
Tables
- roles - Role definitions (reader, contributor, maintainer, admin)
- permissions - Permission definitions (impact:read, llm:use, etc.)
- role_permissions - Many-to-many role-permission mapping
- principals - User/service account records
- principal_roles - Role bindings with optional resource patterns
Entity Relationships
principals 1---* principal_roles *---1 roles
|
|
1---*
|
permissions
API Endpoints
Role Management
Create Role
POST /api/v1/roles
Content-Type: application/json
{
"name": "service-owner",
"description": "Owner of a specific service"
}
Response: 201 Created
{
"id": 5,
"name": "service-owner",
"description": "Owner of a specific service",
"permissions": [],
"createdAt": "2024-01-15T10:00:00",
"updatedAt": "2024-01-15T10:00:00"
}
List Roles
GET /api/v1/roles
Response: 200 OK
[
{
"id": 1,
"name": "reader",
"description": "Read-only access to all services",
"permissions": [...]
}
]
Get Role by Name
GET /api/v1/roles/{name}
Permission Management
Create Permission
POST /api/v1/permissions
Content-Type: application/json
{
"name": "impact:admin",
"description": "Full admin access to impact analyzer",
"resourceType": "impact-analyzer"
}
List Permissions
GET /api/v1/permissions
Add Permission to Role
POST /api/v1/roles/{roleId}/permissions/{permissionId}
Role Bindings
Create Binding
POST /api/v1/bindings
Content-Type: application/json
{
"principalSubject": "user|alice",
"roleId": 2,
"resourcePattern": "service:impact-analyzer",
"grantedBy": "admin"
}
Resource Patterns:
nullor omitted - Global accessservice:impact-analyzer- Specific serviceservice:*- All services (wildcard)
List Bindings
GET /api/v1/bindings?user=user|alice
Permission Checks
Check Permission
POST /api/v1/check
Content-Type: application/json
{
"principalSubject": "user|alice",
"permissionName": "impact:read",
"resourcePattern": "service:impact-analyzer"
}
Response: 200 OK
{
"granted": true,
"reason": "Permission granted through role: contributor",
"matchedRole": "contributor",
"matchedResourcePattern": null
}
Default Roles
The service automatically creates these roles on startup:
| Role | Description | Permissions |
|---|---|---|
| reader | Read-only access | impact:read, metadata:read, graph:read |
| contributor | Read + contribute | impact:read, impact:run, metadata:read, graph:read, llm:use |
| maintainer | Maintain services | All contributor permissions + impact:simulate, metadata:modify, graph:modify, notifications:send |
| admin | Full administrative access | All permissions |
Default Permissions
Service-specific permissions included by default:
- Impact Analyzer:
impact:read,impact:run,impact:simulate - Notifications:
notifications:send - Metadata:
metadata:read,metadata:modify - LLM:
llm:use - Dependency Graph:
graph:read,graph:modify
Environment Variables
# Database
SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/rippler_auth
SPRING_DATASOURCE_USERNAME=rippler
SPRING_DATASOURCE_PASSWORD=rippler_pass
# Redis Cache
REDIS_HOST=redis
REDIS_PORT=6379
# Keycloak
KEYCLOAK_ISSUER_URI=http://keycloak:8080/realms/rippler
KEYCLOAK_JWK_SET_URI=http://keycloak:8080/realms/rippler/protocol/openid-connect/certs
# Application
SERVER_PORT=8008
SPRING_JPA_HIBERNATE_DDL_AUTO=update
Caching Strategy
Permission checks are cached in Redis for 10 minutes to improve performance.
Cache Key Format:
{principalSubject}:{permissionName}:{resourcePattern}
Cache Invalidation:
- When roles are created or modified
- When permissions are created or modified
- When role bindings change
Resource Pattern Matching
The service supports flexible resource pattern matching:
-
Global Binding (
nullpattern)- Matches everything
- Highest privilege
-
Exact Match (
service:impact-analyzer)- Matches specific resource exactly
-
Wildcard Match (
service:*)- Matches any service
- Prefix-based matching
Integration Example
// Check permission before allowing operation
@Autowired
private RestTemplate restTemplate;
public void runImpactAnalysis(String userId) {
PermissionCheckRequest request = PermissionCheckRequest.builder()
.principalSubject(userId)
.permissionName("impact:run")
.resourcePattern("service:impact-analyzer")
.build();
PermissionCheckResponse response = restTemplate.postForObject(
"http://auth-service:8008/api/v1/check",
request,
PermissionCheckResponse.class
);
if (!response.isGranted()) {
throw new AccessDeniedException("Permission denied");
}
// Proceed with operation
}
Health Check
GET /actuator/health
Response:
{
"status": "UP",
"components": {
"db": { "status": "UP" },
"redis": { "status": "UP" }
}
}
Development
Building
cd services/auth-service
mvn clean package
Running Locally
# With Docker Compose
docker-compose up auth-service
# Standalone
java -jar target/auth-service-1.0.0.jar
Testing
# List roles
curl http://localhost:18008/api/v1/roles
# Create binding
curl -X POST http://localhost:18008/api/v1/bindings \
-H "Content-Type: application/json" \
-d '{
"principalSubject": "user|test",
"roleId": 1,
"grantedBy": "admin"
}'
Monitoring
Key metrics available at /actuator/metrics:
cache.gets- Cache hit/miss ratiohttp.server.requests- API request latencyjvm.memory.used- Memory usagejdbc.connections.active- Database connections
Troubleshooting
Permission Check Returns False
-
Verify user has role assigned:
curl http://localhost:18008/api/v1/bindings?user=user|alice -
Check role has required permission:
curl http://localhost:18008/api/v1/roles -
Verify resource pattern matching
Database Connection Issues
- Check PostgreSQL is running:
docker-compose ps postgres - Verify database exists:
docker-compose exec postgres psql -U rippler -l - Check connection string in environment variables
Redis Connection Issues
- Check Redis is running:
docker-compose ps redis - Test connection:
docker-compose exec redis redis-cli ping - Verify Redis host/port configuration
Security Considerations
- All API endpoints should be protected with JWT validation (except health checks)
- Role assignments should be audited (use Audit Service)
- Cache invalidation is critical for security
- Resource patterns should be validated to prevent injection attacks
See Also
- Audit Service - Authentication and authorization audit logging
- SSO Setup Guide - Complete SSO + RBAC setup instructions
- API Gateway - JWT validation and routing