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 status404 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 suspended404 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 suspended404 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 owner404 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 owner404 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_organizationsuspend_organization,activate_organizationupdate_organization_tier,delete_organizationpromote_platform_owner,demote_platform_ownerforce_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 statustotal_users: Platform owners and organization admins/memberstotal_end_users: Regular users who authenticate with servicestotal_services: All services across all organizationstotal_logins_24h: Login events in last 24 hourstotal_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 /api/platform/analytics/growth-trends
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 verificationsmultiple_backup_code_uses: Unusual backup code usage patternrapid_mfa_toggles: MFA enabled/disabled multiple times
Severity Levels:
high: Immediate attention recommendedmedium: Monitor for patternslow: 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
- Review pending organizations promptly: Set up notifications for new org requests
- Document rejection reasons clearly: Help users understand why their org was rejected
- Use suspend instead of delete: Suspended orgs can be reactivated if issues are resolved
- Monitor tier usage: Check if organizations are hitting their limits
Platform Owner Permissions
- Limit platform owners: Only promote trusted administrators
- Document promotions: Keep external records of who has platform owner access
- Regular audits: Review platform owner list quarterly
- Prevent last owner lockout: Never demote the last platform owner
Analytics
- Monitor growth trends: Watch for unusual spikes in signups or login activity
- Track MFA adoption: Encourage organizations to enable MFA
- Review suspicious activity: Check MFA alerts daily
- Export audit logs: Regularly backup audit logs for compliance
Security
- Use MFA yourself: All platform owners should enable MFA
- Review audit logs regularly: Look for unauthorized changes
- Be cautious with force disable: Only use for legitimate account recovery
- Rotate platform owner access: Remove access when team members leave