SCIM/OAA Integration Specification
Implementation status:
Overview
SecurityV0 adopts industry-proven patterns from SCIM (System for Cross-domain Identity Management) and OAA (Open Authorization API) to enable interoperability with the broader identity security ecosystem.
Strategic rationale:
- Follow proven patterns — OAA's authorization model is battle-tested across enterprise deployments (Snowflake, Choice Hotels)
- Minimize client integration effort — clients already using SCIM/OAA patterns integrate with minimal mapping
- Preserve SecurityV0 differentiators — ownership decay, temporal drift, and evidence packs remain unique capabilities
This specification does NOT define integration with any specific vendor. It defines how SecurityV0 adopts industry patterns where applicable.
OAA Alignment [Deferred]
OAA export is a read-only projection layer. Implementation deferred until customer need. See ADR-009.
What OAA Provides
OAA (Open Authorization API) defines a standardized schema for representing authorization metadata:
| OAA Concept | SecurityV0 Internal Type | OAA Export Entity | Mapping Fidelity | Notes |
|---|---|---|---|---|
| Local User | identity | local_user | HIGH | Authenticating NHIs map directly to OAA users |
| Resource (automation) | automation | resource (type: automation) | HIGH | OAA resources support custom types |
| Resource (connection) | connection | resource (type: connection) | HIGH | Connection configs are resources in OAA's model |
| Custom property | credential | Custom property on local_user | MEDIUM | OAA has no first-class credential entity |
| Local User (human) | owner | local_user (type: human) | HIGH | Human owners map to OAA users with human type marker |
| Local Role | role | local_role | HIGH | Direct mapping |
| Custom Permission | permission | custom_permission | HIGH | OAA supports custom permission definitions |
| Resource | resource | resource | HIGH | Direct mapping |
| (not exported) | execution_evidence | (not exported) | N/A | OAA has no execution evidence concept |
What is Lost in OAA Export
| Internal Concept | OAA Equivalent | Loss |
|---|---|---|
| Execution chains | None | Full loss — OAA has no chain concept |
| Typed execution edges (CALLS, INVOKES, USES, AUTHENTICATES_AS) | Generic can_access | Semantic loss — edge types collapsed |
| Credential as first-class entity | Custom property | Structural loss — can't query credentials independently |
| Temporal tracking (first_seen, last_seen, drift) | None | Full loss — OAA is point-in-time |
| Evidence packs | None | Full loss — OAA has no evidence model |
What SecurityV0 Adds Beyond OAA
| Capability | OAA | SecurityV0 |
|---|---|---|
| Ownership hierarchy | Not modeled | Owner entity with decay tracking |
| Credential lifecycle | Not modeled | Credential entity (first-class) with rotation status |
| Execution chains | Not modeled | Typed chain: automation → connection → credential → identity |
| Temporal versioning | Snapshots only | Point-in-time queries, drift detection |
| Evidence artifacts | Not modeled | Sealed, immutable evidence packs |
| Automation classification | Resources only | Dedicated automation type with subtypes and execution_mode |
OAA Export Specification [Deferred]
OAA export is a read-only projection layer. Implementation deferred until customer need. See ADR-009.
Endpoint: List Applications [Deferred]
GET /api/v1/oaa/applications
Response:
{
"applications": [
{
"id": "app-uuid-1",
"application_type": "entra_id",
"name": "contoso-prod",
"description": "Contoso production Entra ID tenant",
"last_sync_at": "2026-02-06T10:30:00Z",
"entity_counts": {
"identities": 15,
"automations": 87,
"connections": 12,
"roles": 38,
"permissions": 512,
"resources": 89
}
}
],
"total": 1
}
Endpoint: Get Application Payload [Deferred]
GET /api/v1/oaa/applications/{id}
Response (OAA-compatible payload):
{
"application_type": "entra_id",
"name": "contoso-prod",
"description": "Contoso production Entra ID tenant",
"local_users": [
{
"id": "sp-uuid-1",
"name": "sp-hr-onboarding",
"email": null,
"is_active": true,
"created_at": "2025-03-10T00:00:00Z",
"last_login_at": "2026-02-06T10:15:00Z",
"user_type": "service_principal",
"identities": [
{
"identity_type": "azure_ad",
"identity_value": "sp-uuid-1"
}
],
"custom_properties": {
"sv0_identity_subtype": "service_principal",
"sv0_execution_mode": "autonomous"
}
}
],
"local_groups": [],
"local_roles": [
{
"id": "role-uuid-1",
"name": "Application.ReadWrite.All",
"permissions": ["perm-uuid-1", "perm-uuid-2"],
"custom_properties": {
"sv0_is_privileged": true
}
}
],
"permissions": [
{
"id": "perm-uuid-1",
"name": "Application.ReadWrite.All",
"permission_type": ["MetadataWrite"],
"apply_to_sub_resources": true,
"resource_types": ["application"],
"custom_properties": {
"sv0_canonical_type": "MetadataWrite",
"sv0_is_privileged": true,
"sv0_is_delegatable": false,
"sv0_raw_permission": "Application.ReadWrite.All"
}
}
],
"resources": [
{
"id": "resource-uuid-1",
"name": "All Applications",
"resource_type": "application",
"sub_resources": []
}
],
"identity_to_permissions": [
{
"identity": {
"id": "sp-uuid-1",
"identity_type": "local_user"
},
"apply_to_application": false,
"permission": "perm-uuid-1",
"resource": "resource-uuid-1"
}
],
"custom_properties": {
"sv0_tenant_id": "tenant-uuid-1",
"sv0_connector_id": "entra-connector-1",
"sv0_last_sync_at": "2026-02-06T10:30:00Z"
}
}
OAA Permission Type Mapping [Deferred]
OAA uses permission_type arrays. SecurityV0 maps canonical types:
| SecurityV0 Canonical Type | OAA permission_type |
|---|---|
| DataRead | DataRead |
| DataWrite | DataWrite |
| DataCreate | DataCreate |
| DataDelete | DataDelete |
| MetadataRead | MetadataRead |
| MetadataWrite | MetadataWrite |
| MetadataCreate | MetadataCreate |
| MetadataDelete | MetadataDelete |
| NonData | NonData |
| Uncategorized | Uncategorized |
SCIM 2.0 Specification [Planned]
SecurityV0 exposes a read-only SCIM 2.0 API for identity discovery by IGA and PAM tools.
Service Provider Configuration
GET /scim/v2/ServiceProviderConfig
Response:
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"],
"documentationUri": "https://docs.securityv0.io/scim",
"patch": {
"supported": false
},
"bulk": {
"supported": false
},
"filter": {
"supported": true,
"maxResults": 1000
},
"changePassword": {
"supported": false
},
"sort": {
"supported": true
},
"etag": {
"supported": true
},
"authenticationSchemes": [
{
"type": "oauthbearertoken",
"name": "OAuth Bearer Token",
"description": "Authentication via OAuth 2.0 Bearer Token"
}
]
}
Schema Discovery
GET /scim/v2/Schemas
Returns SecurityV0's SCIM schemas including:
urn:ietf:params:scim:schemas:core:2.0:User(standard)urn:ietf:params:scim:schemas:core:2.0:Group(standard)urn:securityv0:scim:schemas:extension:nhi:1.0(SecurityV0 NHI extension)
Resource Types
GET /scim/v2/ResourceTypes
Response:
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:ResourceType"],
"Resources": [
{
"id": "User",
"name": "User",
"endpoint": "/Users",
"schema": "urn:ietf:params:scim:schemas:core:2.0:User",
"schemaExtensions": [
{
"schema": "urn:securityv0:scim:schemas:extension:nhi:1.0",
"required": false
}
]
},
{
"id": "Group",
"name": "Group",
"endpoint": "/Groups",
"schema": "urn:ietf:params:scim:schemas:core:2.0:Group"
}
]
}
List Users (Identities)
GET /scim/v2/Users
GET /scim/v2/Users?filter=userType eq "service_principal"
GET /scim/v2/Users?filter=active eq true and userType eq "oauth_app"
Only entities of type
identityare exposed via SCIM/Users. Entities of typeautomation,connection, andcredentialare not SCIM users and are not returned by this endpoint.
Response:
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": 142,
"itemsPerPage": 100,
"startIndex": 1,
"Resources": [
{
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
"urn:securityv0:scim:schemas:extension:nhi:1.0"
],
"id": "sp-uuid-1",
"userName": "sp-hr-onboarding",
"displayName": "HR Onboarding Service Principal",
"userType": "service_principal",
"active": true,
"meta": {
"resourceType": "User",
"created": "2025-03-10T00:00:00Z",
"lastModified": "2026-02-06T10:30:00Z",
"version": "W/\"abc123\""
},
"urn:securityv0:scim:schemas:extension:nhi:1.0": {
"identitySubtype": "service_principal",
"executionMode": "autonomous",
"applicationId": "app-uuid-1",
"applicationName": "contoso-prod",
"lastActivityAt": "2026-02-06T10:15:00Z",
"ownershipStatus": "orphaned",
"findingCount": 2
}
}
],
"urn:ietf:params:scim:api:messages:2.0:cursorPagination": {
"nextCursor": "cursor-abc123",
"previousCursor": null
}
}
Get Single User
GET /scim/v2/Users/{id}
List Groups (Teams/Owners)
GET /scim/v2/Groups
Maps SecurityV0 Owner entities (team type) to SCIM Groups.
Write Operations
All write operations return HTTP 501 Not Implemented:
POST /scim/v2/Users → 501
PUT /scim/v2/Users/{id} → 501
PATCH /scim/v2/Users/{id} → 501
DELETE /scim/v2/Users/{id} → 501
Rationale: SecurityV0 is read-only toward source systems. It discovers and catalogs identities but does not provision or deprovision them.
NHI Extension Schema [Planned]
SecurityV0 defines a SCIM extension for NHI (Non-Human Identity) attributes:
Schema URI: urn:securityv0:scim:schemas:extension:nhi:1.0
| Attribute | Type | Description |
|---|---|---|
| identitySubtype | string | Subtype of the identity entity. Values: service_principal, oauth_app, machine_account, integration_user |
| executionMode | string | Execution mode of the identity. Values: autonomous, operator_assisted, human_triggered, unknown |
| applicationId | string | Reference to containing Application |
| applicationName | string | Human-readable application name |
| lastActivityAt | dateTime | Last execution timestamp |
| ownershipStatus | string | owned, degraded, orphaned |
| findingCount | integer | Number of active findings |
| credentialStatus | string | active, expired, expiring_soon |
| canonicalPermissions | string[] | List of canonical permission types held |
Non-identity entity types (
automation,connection,credential) are not exposed via SCIM/Users. These entities are not SCIM users. When SCIM resource discovery is needed, a future/ResourceTypesextension or separate resource endpoint would be required.
Pagination
SCIM Cursor Pagination (RFC 9865)
SecurityV0 implements cursor-based pagination for SCIM endpoints:
GET /scim/v2/Users?count=100
Response includes:
{
"totalResults": 5000,
"itemsPerPage": 100,
"Resources": [...],
"urn:ietf:params:scim:api:messages:2.0:cursorPagination": {
"nextCursor": "cursor-abc123",
"previousCursor": null
}
}
Next page:
GET /scim/v2/Users?cursor=cursor-abc123&count=100
OAA Pagination [Deferred]
OAA export uses offset-based pagination:
GET /api/v1/oaa/applications?offset=0&limit=100
Authentication
Both SCIM and OAA endpoints require authentication:
- OAuth 2.0 Bearer Token (recommended)
- API Key (via
X-API-Keyheader)
All requests must be tenant-scoped. The authenticated principal determines which Applications and Identities are visible.
Error Responses
SCIM Errors
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status": "401",
"scimType": "unauthorized",
"detail": "Invalid or expired token"
}
OAA Errors [Deferred]
{
"error": "not_found",
"message": "Application not found",
"application_id": "app-uuid-unknown"
}
Integration Examples
SailPoint IdentityNow
Configure SCIM source connector:
- Base URL:
https://api.securityv0.io/scim/v2 - Auth: OAuth 2.0 Bearer Token
- Filter:
userType eq "service_principal"
Saviynt EIC
Configure SCIM connector for NHI discovery:
- Endpoint:
https://api.securityv0.io/scim/v2/Users - Import non-human identities into Saviynt's identity warehouse
- Correlate with application accounts via
applicationId
OAA Consumer (Generic) [Deferred]
For tools that consume OAA-format payloads:
- Fetch application list:
GET /api/v1/oaa/applications - For each application, fetch full payload:
GET /api/v1/oaa/applications/{id} - Import identities, permissions, resources into authorization graph