Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

This section presents a role-based access control (RBAC) example for a fictitious system, “SkyLink API Gateway”.

It illustrates how an RBAC design can be developed and applied within a real-world system context, providing a practical reference for implementing authorisation controls as part of a Security by Design approach.

Overview

SkyLink implements Role-Based Access Control (RBAC) following the Security by Design principle of Least Privilege. Each role has only the minimum permissions required for its function.

Roles

RoleDescriptionUse Case
aircraft_standardDefault aircraft roleBasic operations (weather, telemetry write)
aircraft_premiumPremium aircraftExtended access (+ contacts)
ground_controlGround control stationMonitoring operations (read-only)
maintenanceMaintenance personnelDiagnostic access
adminSystem administratorFull access

Permissions

PermissionDescriptionResources
weather:readAccess weather dataGET /weather/current
contacts:readAccess contacts dataGET /contacts/
telemetry:writeIngest telemetryPOST /telemetry/ingest
telemetry:readRead telemetryGET /telemetry/events/*
config:readRead configurationFuture endpoint
config:writeModify configurationFuture endpoint
audit:readRead audit logsFuture endpoint

Role-Permission Matrix

Roleweather:readcontacts:readtelemetry:writetelemetry:readconfig:readconfig:writeaudit:read
aircraft_standard
aircraft_premium
ground_control
maintenance
admin

Usage

Requesting a Token with Role

# Default role (aircraft_standard)
curl -X POST http://localhost:8000/auth/token \
  -H "Content-Type: application/json" \
  -d '{"aircraft_id": "550e8400-e29b-41d4-a716-446655440000"}'

# With specific role
curl -X POST http://localhost:8000/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "aircraft_id": "550e8400-e29b-41d4-a716-446655440000",
    "role": "aircraft_premium"
  }'

JWT Token Structure

The JWT token includes the role in its claims:

{
  "sub": "550e8400-e29b-41d4-a716-446655440000",
  "aud": "skylink",
  "iat": 1703174400,
  "exp": 1703175300,
  "role": "aircraft_premium"
}

Error Responses

401 Unauthorized

Missing or invalid JWT token.

{
  "detail": "Missing Authorization header"
}

403 Forbidden

Valid token but insufficient permissions.

{
  "detail": "Permission denied: contacts:read required"
}

Implementation

Adding RBAC to an Endpoint

from fastapi import APIRouter, Depends
from skylink.rbac import require_permission
from skylink.rbac_roles import Permission

router = APIRouter()

@router.get("/protected")
async def protected_endpoint(
    token: dict = Depends(require_permission(Permission.WEATHER_READ))
):
    # Token is verified and has required permission
    return {"message": "Access granted"}

Checking Multiple Permissions

@router.get("/multi-protected")
async def multi_protected(
    token: dict = Depends(require_permission(
        Permission.TELEMETRY_READ,
        Permission.CONFIG_READ
    ))
):
    # Requires BOTH permissions
    return {"message": "Access granted"}

Role-Based Restriction

from skylink.rbac import require_role
from skylink.rbac_roles import Role

@router.get("/admin-only")
async def admin_only(
    token: dict = Depends(require_role(Role.ADMIN))
):
    # Only admin role allowed
    return {"message": "Admin access granted"}

Audit Logging

All authorization decisions are logged for security audit:

Authorization Success

{
  "event_type": "AUTHZ_SUCCESS",
  "event_category": "authorization",
  "severity": "info",
  "actor": {"type": "aircraft", "id": "550e8400..."},
  "details": {
    "role": "aircraft_premium",
    "permission": "contacts:read",
    "endpoint": "/contacts/"
  }
}

Authorization Failure

{
  "event_type": "AUTHZ_FAILURE",
  "event_category": "authorization",
  "severity": "warning",
  "actor": {"type": "aircraft", "id": "550e8400..."},
  "details": {
    "role": "aircraft_standard",
    "required_permission": "contacts:read",
    "endpoint": "/contacts/"
  }
}

Security Considerations

  1. Default Role: Tokens without explicit role default to aircraft_standard (least privilege).

  2. Invalid Roles: Invalid role values in tokens fall back to aircraft_standard.

  3. Role in Token: Role is embedded in JWT, preventing runtime escalation.

  4. No Role Enumeration: 403 responses don’t reveal which roles would have access.

  5. Authentication vs Authorization:

    • 401 = Authentication failure (no/invalid token)

    • 403 = Authorization failure (valid token, wrong permissions)

Future Enhancements