Platform Owner API

Comprehensive administrative endpoints for managing AuthOS including governance, organization lifecycle, analytics, and security oversight.

Updated Dec 16, 2025
Edit on GitHub
platform admin governance super-admin

Platform Owner API

The Platform Owner API provides comprehensive administrative endpoints for managing AuthOS. These endpoints are restricted to platform owners for governance, organization lifecycle management, analytics, and security oversight.

Overview

Platform owners have elevated permissions to:

  • Approve/Reject Organizations: Govern which organizations can use the platform
  • Manage Organization Tiers: Update subscription tiers and resource limits
  • Platform Owner Management: Promote and demote platform administrators
  • Analytics & Reporting: Access platform-wide metrics and trends
  • MFA Management: Oversee multi-factor authentication security
  • User Search: Find users across all organizations
  • Audit Logging: Track all platform administrative actions

All platform owner endpoints require JWT authentication with is_platform_owner: true claim.

Endpoints Summary

Method Path Description
GET /api/platform/tiers List organization tiers
GET /api/platform/organizations List all organizations
POST /api/platform/organizations/:id/approve Approve pending organization
POST /api/platform/organizations/:id/reject Reject pending organization
POST /api/platform/organizations/:id/suspend Suspend active organization
POST /api/platform/organizations/:id/activate Reactivate suspended organization
PATCH /api/platform/organizations/:id/tier Update organization tier
DELETE /api/platform/organizations/:id Delete organization
POST /api/platform/owners Promote user to platform owner
DELETE /api/platform/owners/:user_id Demote platform owner
GET /api/platform/audit-log Get platform audit logs
GET /api/platform/analytics/overview Get platform overview metrics
GET /api/platform/analytics/organization-status Get organization status breakdown
GET /api/platform/analytics/growth-trends Get growth trends over time
GET /api/platform/analytics/login-activity Get login activity trends
GET /api/platform/analytics/top-organizations Get most active organizations
GET /api/platform/analytics/recent-organizations Get recently created organizations
GET /api/platform/users/search Search users by email or ID
GET /api/platform/users/:user_id/mfa/status Get user MFA status
DELETE /api/platform/users/:user_id/mfa Force disable user MFA
GET /api/platform/mfa/metrics Get MFA usage metrics
GET /api/platform/mfa/suspicious Get suspicious MFA activity
GET /api/platform/mfa/metrics/generate Generate daily MFA metrics

Organization Tier Management

GET /api/platform/tiers

List all available organization tiers with pricing and resource limits.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Response (200 OK):

[
  {
    "id": "tier_free",
    "name": "free",
    "display_name": "Free Tier",
    "default_max_services": 3,
    "default_max_users": 100,
    "features": ["oauth", "email_auth"],
    "price_cents": 0,
    "currency": "USD",
    "created_at": "2025-01-15T10:00:00Z"
  },
  {
    "id": "tier_pro",
    "name": "pro",
    "display_name": "Professional",
    "default_max_services": 10,
    "default_max_users": 1000,
    "features": ["oauth", "email_auth", "saml", "custom_domain", "branding"],
    "price_cents": 9900,
    "currency": "USD",
    "created_at": "2025-01-15T10:00:00Z"
  }
]

Example Request:

curl -X GET https://sso.example.com/api/platform/tiers \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Organization Governance

GET /api/platform/organizations

List all organizations with optional filtering and pagination.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Query Parameters:

Parameter Type Required Description
status string No Filter by status: pending, active, suspended, rejected
tier_id string No Filter by tier ID
limit integer No Maximum results (default: 50, max: 100)
offset integer No Pagination offset (default: 0)

Response (200 OK):

{
  "organizations": [
    {
      "organization": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "slug": "acme-corp",
        "name": "Acme Corporation",
        "owner_user_id": "user_123",
        "status": "active",
        "tier_id": "tier_pro",
        "max_services": 10,
        "max_users": 1000,
        "approved_by": "admin_456",
        "approved_at": "2025-01-15T10:30:00Z",
        "rejected_by": null,
        "rejected_at": null,
        "rejection_reason": null,
        "custom_domain": "auth.acme.com",
        "domain_verified": true,
        "domain_verification_token": null,
        "brand_logo_url": "https://cdn.acme.com/logo.png",
        "brand_primary_color": "#FF5733",
        "created_at": "2025-01-15T09:00:00Z",
        "updated_at": "2025-01-15T10:30:00Z"
      },
      "tier": {
        "id": "tier_pro",
        "name": "pro",
        "display_name": "Professional",
        "default_max_services": 10,
        "default_max_users": 1000,
        "features": ["oauth", "email_auth", "saml", "custom_domain"],
        "price_cents": 9900,
        "currency": "USD",
        "created_at": "2025-01-01T00:00:00Z"
      },
      "owner": {
        "id": "user_123",
        "email": "owner@acme.com",
        "is_platform_owner": false,
        "created_at": "2025-01-10T08:00:00Z"
      }
    }
  ],
  "total": 42
}

Example Request:

curl -X GET "https://sso.example.com/api/platform/organizations?status=pending&limit=20" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

POST /api/platform/organizations/:id/approve

Approve a pending organization and assign it a tier. Changes status from pending to active.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Path Parameters:

Parameter Type Description
id string Organization ID (UUID)

Request Body:

Field Type Required Description
tier_id string No Tier ID to assign (default: tier_free)

Example Request:

curl -X POST https://sso.example.com/api/platform/organizations/550e8400-e29b-41d4-a716-446655440000/approve \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "tier_id": "tier_pro"
  }'

Response (200 OK):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "slug": "acme-corp",
  "name": "Acme Corporation",
  "status": "active",
  "tier_id": "tier_pro",
  "approved_by": "admin_456",
  "approved_at": "2025-01-15T10:30:00Z"
}

Error Responses:

  • 400 Bad Request: Organization not in pending status
    {
      "error": "Organization is not in pending status",
      "error_code": "BAD_REQUEST"
    }
    
  • 404 Not Found: Organization or tier not found
    {
      "error": "Organization not found",
      "error_code": "NOT_FOUND"
    }
    

POST /api/platform/organizations/:id/reject

Reject a pending organization with a reason. Changes status from pending to rejected.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Path Parameters:

Parameter Type Description
id string Organization ID (UUID)

Request Body:

Field Type Required Description
reason string Yes Rejection reason (stored and may be shown to org owner)

Example Request:

curl -X POST https://sso.example.com/api/platform/organizations/550e8400-e29b-41d4-a716-446655440000/reject \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Organization name violates terms of service"
  }'

Response (200 OK):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "slug": "acme-corp",
  "name": "Acme Corporation",
  "status": "rejected",
  "rejected_by": "admin_456",
  "rejected_at": "2025-01-15T10:30:00Z",
  "rejection_reason": "Organization name violates terms of service"
}

Error Responses:

  • 400 Bad Request: Organization not in pending status
  • 404 Not Found: Organization not found

POST /api/platform/organizations/:id/suspend

Suspend an organization. Prevents users from authenticating until reactivated.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Path Parameters:

Parameter Type Description
id string Organization ID (UUID)

Example Request:

curl -X POST https://sso.example.com/api/platform/organizations/550e8400-e29b-41d4-a716-446655440000/suspend \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Response (200 OK):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "slug": "acme-corp",
  "name": "Acme Corporation",
  "status": "suspended",
  "updated_at": "2025-01-15T10:30:00Z"
}

Error Responses:

  • 400 Bad Request: Organization already suspended
  • 404 Not Found: Organization not found

POST /api/platform/organizations/:id/activate

Reactivate a suspended organization. Can only be used on organizations with suspended status.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Path Parameters:

Parameter Type Description
id string Organization ID (UUID)

Example Request:

curl -X POST https://sso.example.com/api/platform/organizations/550e8400-e29b-41d4-a716-446655440000/activate \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Response (200 OK):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "slug": "acme-corp",
  "name": "Acme Corporation",
  "status": "active",
  "updated_at": "2025-01-15T10:30:00Z"
}

Error Responses:

  • 400 Bad Request: Organization is not suspended
  • 404 Not Found: Organization not found

PATCH /api/platform/organizations/:id/tier

Update organization tier and optionally override resource limits.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Path Parameters:

Parameter Type Description
id string Organization ID (UUID)

Request Body:

Field Type Required Description
tier_id string Yes New tier ID
max_services integer No Override max services limit
max_users integer No Override max users limit

Example Request:

curl -X PATCH https://sso.example.com/api/platform/organizations/550e8400-e29b-41d4-a716-446655440000/tier \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "tier_id": "tier_enterprise",
    "max_services": 50,
    "max_users": 10000
  }'

Response (200 OK):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "slug": "acme-corp",
  "name": "Acme Corporation",
  "tier_id": "tier_enterprise",
  "max_services": 50,
  "max_users": 10000,
  "updated_at": "2025-01-15T10:30:00Z"
}

Error Responses:

  • 404 Not Found: Organization or tier not found

DELETE /api/platform/organizations/:id

Permanently delete an organization and all related data (services, members, users, etc.). This action is irreversible.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Path Parameters:

Parameter Type Description
id string Organization ID (UUID)

Example Request:

curl -X DELETE https://sso.example.com/api/platform/organizations/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Response (200 OK):

{
  "success": true,
  "message": "Organization deleted successfully"
}

Error Responses:

  • 404 Not Found: Organization not found

Platform Owner Management

POST /api/platform/owners

Promote a user to platform owner. Grants full administrative access to the platform.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Request Body:

Field Type Required Description
user_id string Yes User ID (UUID) to promote

Example Request:

curl -X POST https://sso.example.com/api/platform/owners \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user_123"
  }'

Response (200 OK):

{
  "id": "user_123",
  "email": "admin@example.com",
  "is_platform_owner": true,
  "created_at": "2025-01-10T08:00:00Z"
}

Error Responses:

  • 400 Bad Request: User is already a platform owner
  • 404 Not Found: User not found

DELETE /api/platform/owners/:user_id

Demote a platform owner to regular user. Cannot demote yourself or the last platform owner.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Path Parameters:

Parameter Type Description
user_id string User ID (UUID) to demote

Example Request:

curl -X DELETE https://sso.example.com/api/platform/owners/user_123 \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Response (200 OK):

{
  "id": "user_123",
  "email": "admin@example.com",
  "is_platform_owner": false,
  "created_at": "2025-01-10T08:00:00Z"
}

Error Responses:

  • 400 Bad Request: Cannot demote yourself
    {
      "error": "Cannot demote yourself",
      "error_code": "BAD_REQUEST"
    }
    
  • 400 Bad Request: Cannot demote last platform owner
    {
      "error": "Cannot demote the last platform owner",
      "error_code": "BAD_REQUEST"
    }
    
  • 400 Bad Request: User is not a platform owner
  • 404 Not Found: User not found

Audit Logging

GET /api/platform/audit-log

Retrieve platform audit logs with optional filtering and pagination. Tracks all administrative actions.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Query Parameters:

Parameter Type Required Description
action string No Filter by action (e.g., approve_organization)
target_type string No Filter by target type (e.g., organization, user)
target_id string No Filter by specific target ID
limit integer No Maximum results (default: 50, max: 100)
offset integer No Pagination offset (default: 0)

Response (200 OK):

{
  "logs": [
    {
      "id": "log_123",
      "platform_owner_id": "admin_456",
      "action": "approve_organization",
      "target_type": "organization",
      "target_id": "550e8400-e29b-41d4-a716-446655440000",
      "metadata": {
        "old_status": "pending",
        "new_status": "active",
        "tier_id": "tier_pro"
      },
      "created_at": "2025-01-15T10:30:00Z"
    },
    {
      "id": "log_124",
      "platform_owner_id": "admin_456",
      "action": "suspend_organization",
      "target_type": "organization",
      "target_id": "660e8400-e29b-41d4-a716-446655440111",
      "metadata": {
        "old_status": "active",
        "new_status": "suspended"
      },
      "created_at": "2025-01-15T11:00:00Z"
    }
  ],
  "total": 256
}

Example Request:

curl -X GET "https://sso.example.com/api/platform/audit-log?action=approve_organization&limit=20" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Tracked Actions:

  • approve_organization, reject_organization
  • suspend_organization, activate_organization
  • update_organization_tier, delete_organization
  • promote_platform_owner, demote_platform_owner
  • force_disable_mfa

Platform Analytics

GET /api/platform/analytics/overview

Get high-level platform metrics including organization counts, user counts, and login activity.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Response (200 OK):

{
  "total_organizations": 42,
  "total_users": 1250,
  "total_end_users": 15000,
  "total_services": 120,
  "total_logins_24h": 5420,
  "total_logins_30d": 152340
}

Example Request:

curl -X GET https://sso.example.com/api/platform/analytics/overview \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Metrics Explained:

  • total_organizations: All organizations regardless of status
  • total_users: Platform owners and organization admins/members
  • total_end_users: Regular users who authenticate with services
  • total_services: All services across all organizations
  • total_logins_24h: Login events in last 24 hours
  • total_logins_30d: Login events in last 30 days

GET /api/platform/analytics/organization-status

Get breakdown of organizations by status.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Response (200 OK):

{
  "pending": 5,
  "active": 35,
  "suspended": 1,
  "rejected": 1
}

Example Request:

curl -X GET https://sso.example.com/api/platform/analytics/organization-status \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Get platform growth trends showing new organizations and users over time.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Query Parameters:

Parameter Type Required Description
start_date string No Start date (YYYY-MM-DD) (default: 30 days ago)
end_date string No End date (YYYY-MM-DD) (default: today)

Response (200 OK):

[
  {
    "date": "2025-01-10",
    "new_organizations": 3,
    "new_users": 42
  },
  {
    "date": "2025-01-11",
    "new_organizations": 2,
    "new_users": 35
  },
  {
    "date": "2025-01-12",
    "new_organizations": 5,
    "new_users": 67
  }
]

Example Request:

curl -X GET "https://sso.example.com/api/platform/analytics/growth-trends?start_date=2025-01-01&end_date=2025-01-15" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

GET /api/platform/analytics/login-activity

Get platform-wide login activity trends over time.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Query Parameters:

Parameter Type Required Description
start_date string No Start date (YYYY-MM-DD) (default: 30 days ago)
end_date string No End date (YYYY-MM-DD) (default: today)

Response (200 OK):

[
  {
    "date": "2025-01-10",
    "count": 4520
  },
  {
    "date": "2025-01-11",
    "count": 5130
  },
  {
    "date": "2025-01-12",
    "count": 4890
  }
]

Example Request:

curl -X GET "https://sso.example.com/api/platform/analytics/login-activity?start_date=2025-01-01&end_date=2025-01-15" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

GET /api/platform/analytics/top-organizations

Get most active organizations ranked by user count, service count, and login activity.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Response (200 OK):

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Acme Corporation",
    "slug": "acme-corp",
    "user_count": 250,
    "service_count": 12,
    "login_count_30d": 15420
  },
  {
    "id": "660e8400-e29b-41d4-a716-446655440111",
    "name": "Tech Startup Inc",
    "slug": "tech-startup",
    "user_count": 180,
    "service_count": 8,
    "login_count_30d": 12350
  }
]

Example Request:

curl -X GET https://sso.example.com/api/platform/analytics/top-organizations \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Note: Returns top 10 organizations by default.


GET /api/platform/analytics/recent-organizations

Get recently created organizations with their current status.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Query Parameters:

Parameter Type Required Description
limit integer No Maximum results (default: 10, max: 50)

Response (200 OK):

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "New Startup LLC",
    "slug": "new-startup",
    "status": "pending",
    "created_at": "2025-01-15T09:30:00Z"
  },
  {
    "id": "660e8400-e29b-41d4-a716-446655440111",
    "name": "Tech Corp",
    "slug": "tech-corp",
    "status": "active",
    "created_at": "2025-01-15T08:00:00Z"
  }
]

Example Request:

curl -X GET "https://sso.example.com/api/platform/analytics/recent-organizations?limit=20" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

User Management

GET /api/platform/users/search

Search for users across all organizations by email or user ID.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Query Parameters:

Parameter Type Required Description
q string Yes Search query (email or user ID)
limit integer No Maximum results (default: 10, max: 50)

Response (200 OK):

[
  {
    "id": "user_123",
    "email": "john@example.com",
    "is_platform_owner": false,
    "created_at": "2025-01-10T08:00:00Z"
  },
  {
    "id": "user_456",
    "email": "john.doe@company.com",
    "is_platform_owner": false,
    "created_at": "2025-01-12T10:30:00Z"
  }
]

Example Request:

curl -X GET "https://sso.example.com/api/platform/users/search?q=john@example.com" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Search Behavior:

  • Searches both email addresses and user IDs
  • Case-insensitive partial matching
  • Results ordered by relevance (exact matches first)

MFA Management

GET /api/platform/users/:user_id/mfa/status

Get MFA status for a specific user including whether MFA is enabled and if backup codes exist.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Path Parameters:

Parameter Type Description
user_id string User ID (UUID)

Response (200 OK):

{
  "enabled": true,
  "has_backup_codes": true
}

Example Request:

curl -X GET https://sso.example.com/api/platform/users/user_123/mfa/status \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Error Responses:

  • 404 Not Found: User not found

DELETE /api/platform/users/:user_id/mfa

Force disable MFA for a user. Used when a user loses access to their authenticator app and backup codes.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Path Parameters:

Parameter Type Description
user_id string User ID (UUID)

Response (200 OK):

{
  "success": true,
  "message": "MFA has been force-disabled for the user"
}

Example Request:

curl -X DELETE https://sso.example.com/api/platform/users/user_123/mfa \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Important Notes:

  • Deletes both TOTP secret and all backup codes
  • Creates audit log entry
  • User will need to re-enable MFA if desired
  • Use sparingly and only for legitimate account recovery

Error Responses:

  • 404 Not Found: User not found

GET /api/platform/mfa/metrics

Get comprehensive MFA usage metrics and adoption trends.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Query Parameters:

Parameter Type Required Description
start_date string No Start date (YYYY-MM-DD)
end_date string No End date (YYYY-MM-DD)
days integer No Days of history (default: 30)

Response (200 OK):

{
  "period": "last_30_days",
  "data": [
    {
      "date": "2025-01-10",
      "total_users": 1250,
      "users_with_mfa": 450,
      "mfa_adoption_rate": 36.0,
      "new_mfa_setups": 15,
      "mfa_disables": 2,
      "failed_attempts": 8,
      "backup_code_uses": 3
    }
  ]
}

Example Request:

curl -X GET "https://sso.example.com/api/platform/mfa/metrics?days=30" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Custom Date Range:

curl -X GET "https://sso.example.com/api/platform/mfa/metrics?start_date=2025-01-01&end_date=2025-01-15" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

GET /api/platform/mfa/suspicious

Get suspicious MFA activity alerts for security monitoring.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Query Parameters:

Parameter Type Required Description
hours integer No Hours to look back (default: 24)

Response (200 OK):

[
  {
    "user_id": "user_123",
    "user_email": "suspicious@example.com",
    "alert_type": "excessive_failed_attempts",
    "severity": "high",
    "failed_attempts": 15,
    "time_window_hours": 1,
    "first_attempt": "2025-01-15T10:00:00Z",
    "last_attempt": "2025-01-15T10:45:00Z",
    "description": "User has 15 failed MFA attempts in the last hour"
  },
  {
    "user_id": "user_456",
    "user_email": "another@example.com",
    "alert_type": "multiple_backup_code_uses",
    "severity": "medium",
    "backup_codes_used": 5,
    "time_window_hours": 24,
    "first_use": "2025-01-15T08:00:00Z",
    "last_use": "2025-01-15T11:30:00Z",
    "description": "User has used 5 backup codes in 24 hours"
  }
]

Example Request:

curl -X GET "https://sso.example.com/api/platform/mfa/suspicious?hours=48" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Alert Types:

  • excessive_failed_attempts: Multiple failed MFA verifications
  • multiple_backup_code_uses: Unusual backup code usage pattern
  • rapid_mfa_toggles: MFA enabled/disabled multiple times

Severity Levels:

  • high: Immediate attention recommended
  • medium: Monitor for patterns
  • low: Informational

GET /api/platform/mfa/metrics/generate

Generate daily MFA metrics for a specific date. Used for backfilling historical data or troubleshooting.

Permissions: Platform Owner

Headers:

Header Value Required
Authorization Bearer {jwt} Yes

Query Parameters:

Parameter Type Required Description
date string No Date to generate metrics for (YYYY-MM-DD) (default: today)

Response (200 OK):

{
  "date": "2025-01-15",
  "total_users": 1250,
  "users_with_mfa": 450,
  "mfa_adoption_rate": 36.0,
  "new_mfa_setups": 15,
  "mfa_disables": 2,
  "failed_attempts": 8,
  "backup_code_uses": 3,
  "generated_at": "2025-01-15T12:00:00Z"
}

Example Request:

curl -X GET "https://sso.example.com/api/platform/mfa/metrics/generate?date=2025-01-15" \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Error Responses:

  • 400 Bad Request: Invalid date format
    {
      "error": "Invalid date format. Use YYYY-MM-DD",
      "error_code": "BAD_REQUEST"
    }
    

Security Considerations

Authorization

All endpoints require:

  • Valid JWT in Authorization: Bearer {jwt} header
  • JWT claim is_platform_owner: true

Platform owner status is verified on every request via middleware.

Audit Logging

All administrative actions are automatically logged:

  • Organization status changes (approve, reject, suspend, activate)
  • Tier updates and limit overrides
  • Organization deletions
  • Platform owner promotions/demotions
  • Forced MFA disables

Audit logs include:

  • Platform owner performing the action
  • Timestamp
  • Target resource
  • Previous and new values (where applicable)

Rate Limiting

Platform owner endpoints have generous rate limits but are still protected:

  • 100 requests per minute per platform owner
  • Higher limits for read-only analytics endpoints

Data Isolation

Platform owners can access data across all organizations, but:

  • Cannot access user passwords (hashed with Argon2id)
  • Cannot access encrypted TOTP secrets
  • Cannot access encrypted OAuth credentials
  • All sensitive data access is logged

Error Responses

All endpoints return consistent error format:

{
  "error": "Human-readable error message",
  "error_code": "ERROR_CODE_ENUM",
  "timestamp": "2025-01-15T10:30:00Z"
}

Common Error Codes

HTTP Status Error Code Description
400 Bad Request BAD_REQUEST Invalid request parameters
401 Unauthorized UNAUTHORIZED Missing or invalid JWT
403 Forbidden FORBIDDEN Not a platform owner
404 Not Found NOT_FOUND Resource not found
500 Internal Server Error INTERNAL_SERVER_ERROR Server error
500 Internal Server Error DATABASE_ERROR Database operation failed

Best Practices

Organization Management

  1. Review pending organizations promptly: Set up notifications for new org requests
  2. Document rejection reasons clearly: Help users understand why their org was rejected
  3. Use suspend instead of delete: Suspended orgs can be reactivated if issues are resolved
  4. Monitor tier usage: Check if organizations are hitting their limits

Platform Owner Permissions

  1. Limit platform owners: Only promote trusted administrators
  2. Document promotions: Keep external records of who has platform owner access
  3. Regular audits: Review platform owner list quarterly
  4. Prevent last owner lockout: Never demote the last platform owner

Analytics

  1. Monitor growth trends: Watch for unusual spikes in signups or login activity
  2. Track MFA adoption: Encourage organizations to enable MFA
  3. Review suspicious activity: Check MFA alerts daily
  4. Export audit logs: Regularly backup audit logs for compliance

Security

  1. Use MFA yourself: All platform owners should enable MFA
  2. Review audit logs regularly: Look for unauthorized changes
  3. Be cautious with force disable: Only use for legitimate account recovery
  4. Rotate platform owner access: Remove access when team members leave