# Custom Application with SCIM (OAA)

### Overview

Veza can automate user provisioning and de-provisioning for any application that uses the Open Authorization API (OAA) for data gathering and authorization modeling, and exposes SCIM-compliant endpoints for user and group management.

This enables organizations to:

* Use your application's existing SCIM endpoints for automated provisioning operations
* Model complex authorization structures using OAA's flexible templates (applications, resources, permissions, custom properties) for Access Graph visibility, Access Reviews, and other Veza features.
* Gather authorization metadata using a variety of methods (custom connectors, APIs, manual JSON payloads, CSV files)

### Supported Actions

| Action Type               | Supported | Description                                                                   |
| ------------------------- | :-------: | ----------------------------------------------------------------------------- |
| **Sync Identities**       |     ✅     | Create new users or update existing user attributes in the target application |
| **Manage Relationships**  |     ✅     | Add or remove users from groups                                               |
| **De-provision Identity** |     ✅     | Deactivate user accounts (sets active=false in SCIM)                          |
| **Delete Identity**       |     ✅     | Permanently delete user accounts from the target application                  |
| **Create Entitlement**    |     ✅     | Create new groups in the target application                                   |

See [Supported Actions](#supported-actions) for details on each action type.

### Enabling Lifecycle Management for Custom Applications (OAA SCIM)

#### Prerequisites

1. Administrative access in Veza to configure the integration
2. An existing [OAA custom application](/4yItIzMvkpAvMVFAamTf/developers/api/oaa.md) integration in Veza with at least one successful extraction
3. Your custom application must expose SCIM 2.0-compliant endpoints; see [Required SCIM 2.0 Endpoints](#required-scim-20-endpoints) below
4. SCIM connection details for the custom application (URL, authentication credentials)

#### Configuration Steps

To enable the integration:

1. In Veza, go to the **Integrations** overview
2. Search for your custom OAA application integration
3. Check the box to **Enable usage for Lifecycle Management**

To verify the configuration:

1. Open **Lifecycle Management** > **Integrations**
2. Search for the integration and click to view details
3. In the **Properties** panel, verify **Lifecycle Management Enabled** is active

### Lifecycle Management and Access Requests with Open Authorization API

There are several potential ways to integrate a custom application for automated lifecycle management and access requests:

1. **External SCIM for Open Authorization API**: You may build your OAA integration using the custom application template and leverage dedicated SCIM endpoints for user and group management. This is useful when you need full control over how authorization metadata is represented in the Veza Access Graph:
   * Your application supports SCIM, and you want to model a wider range of authorization entities and metadata (e.g., credentials, resources) than the Veza SCIM integration supports.
   * You already have a custom OAA integration and want to add provisioning capabilities using SCIM.
2. **Full SCIM Connector**: Use the built-in SCIM connector for both basic data gathering and lifecycle management. This will provide visibility into supported SCIM entities and relationships with schedulable extractions, but not for the full range of entities and metadata that might be modeled using the Application Template such as roles and resources.
3. **Custom REST API Actions**: Actions in Veza may directly call any external API and capture the response in audit trails. This can enable Lifecycle Management and Access Requests for any target system, provided it has appropriate endpoints for managing users and access controls.

| Aspect                     | External OAA with SCIM Write-Back                                          | Built-In SCIM Connector           |
| -------------------------- | -------------------------------------------------------------------------- | --------------------------------- |
| **Extraction Method**      | You build the OAA push payload directly                                    | Auto-discovery via SCIM endpoints |
| **Authorization Modeling** | Full OAA Application support (roles, permissions, resources)               | Users and groups only             |
| **Lifecycle Management**   | Via SCIM endpoints                                                         | Via SCIM endpoints                |
| **Use Case**               | Complex custom applications where visibility or access reviews are needed. | Standard SaaS with SCIM support   |

This document describes how to enable External SCIM for an Open Authorization API integration, and supported actions.

### How It Works

**Data Gathering (OAA):**

You will need to design and build a custom integration to publish information about the application to the Veza Access Graph:

* The payload can include local users, groups, permissions, resources, and complex authorization relationships
* Data can be gathered from any source: APIs, databases, configuration files, etc.

See the rest of the Open Authorization API documentation for examples and best practices when designing and deploying custom integrations.

**Lifecycle Management (SCIM):**

You can enable the SCIM connection at the custom provider level:

* Setting `provisioning: true` and `external_lifecycle_management_type: SCIM` for the custom provider enables Veza to use your application's SCIM endpoints for provisioning
* Provide SCIM connection information and credentials (`configuration_json`)
* Veza maps lifecycle actions to SCIM operations (`POST /Users`, `PATCH /Users/{id}`, etc.)

**Important:** When configuring a custom application for SCIM integration, the OAA payload structure (Application template) and SCIM configuration serve different purposes:

* The **OAA Payload** (`push_application()` or API push) defines local users, groups, permissions, and resources used for visibility and authorization modeling in Veza, and can be updated independently.
* The **SCIM Configuration** (`configuration_json`) for the custom provider defines how to connect to SCIM endpoints (including authentication, URL, and endpoint paths), and is used only for lifecycle management and access request operations.

Both must be consistent (describe and contain the same users and groups), but are configured separately.

#### Required SCIM 2.0 Endpoints

Your application must expose SCIM 2.0 compliant endpoints with the following operations:

User Management:

* `GET /Users` - List and filter users
* `GET /Users?filter=userName eq "{username}"` - Query users by userName
* `POST /Users` - Create new users
* `GET /Users/{id}` - Retrieve specific user by ID
* `PATCH /Users/{id}` - Update user attributes
* `DELETE /Users/{id}` - Delete user (required if using Delete Identity action)

**Group Management:**

* `GET /Groups` - List groups
* `GET /Groups/{id}` - Retrieve specific group by ID
* `POST /Groups` - Create new groups
* `PATCH /Groups/{id}` - Update group membership
* `DELETE /Groups/{id}` - Delete group (optional)

> Note: If the Users and Groups APIs are not at the standard `/Users` and `/Groups` paths, you can specify alternate endpoint paths in the configuration.

#### Authentication

Your SCIM API must support one of the following authentication methods:

* **Bearer Token**: API token passed in Authorization: Bearer {token} header
* **Basic HTTP Authentication**: Username and password passed in Authorization: Basic {credentials} header

The authentication credentials must have both read and write permissions to the SCIM endpoints.

#### Optional: Extension Attributes

To synchronize custom attributes beyond the standard SCIM user schema:

* Expose a `GET /Schemas` endpoint that returns SCIM schema definitions
* Enable schema fetching in your configuration (see Configuration section)

### Configuration

External SCIM for Lifecycle Management is configured via the Veza REST API.

#### Create Custom Provider with External SCIM

Create a Custom Provider that uses external SCIM endpoints specifically for lifecycle management:

```sh
curl -X POST "https://{VEZA_URL}/api/v1/providers/custom" \
  -H "authorization: Bearer {API_KEY}" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "MyCustomApp",
    "custom_template": "application",
    "provisioning": true,
    "external_lifecycle_management_type": "SCIM",
    "configuration_json": "{\"scim_url\":\"https://api.myapp.com/scim/v2\",\"scim_token\":\"your-bearer-token\"}"
  }'
```

**Required Fields**

| Field                                | Required | Description                                                                  |
| ------------------------------------ | -------- | ---------------------------------------------------------------------------- |
| `name`                               | Yes      | Display name for the Custom Provider in Veza                                 |
| `custom_template`                    | Yes      | OAA template type ("application")                                            |
| `provisioning`                       | Yes      | Must be set to true to enable Lifecycle Management                           |
| `external_lifecycle_management_type` | Yes      | Lifecycle management mode (use "SCIM" to enable SCIM-based provisioning)     |
| `configuration_json`                 | Yes      | JSON-encoded string containing SCIM connection details (see structure below) |

**Configuration JSON Parameters**

The `configuration_json` field contains SCIM endpoint connection details used **only for provisioning operations**. It does not affect your OAA payload structure.

| Configuration Key        | Required | Description                                                         | Example Value                     |
| ------------------------ | -------- | ------------------------------------------------------------------- | --------------------------------- |
| `scim_url`               | Yes      | Base URL for SCIM API (without /Users or /Groups path)              | "<https://api.myapp.com/scim/v2>" |
| `scim_token`             | No\*     | Bearer token for authentication                                     | "eyJhbGci..."                     |
| `username`               | No\*     | Username for basic authentication                                   | "scim-admin"                      |
| `password`               | No\*     | Password for basic authentication                                   | "secure-password"                 |
| `users_endpoint`         | No       | Users endpoint path (defaults to Users if not specified)            | "Users"                           |
| `groups_endpoint`        | No       | Groups endpoint path (defaults to Groups if not specified)          | "Groups"                          |
| `scim_extension_schemas` | No       | Fetch SCIM schemas for extension attribute support (default: false) | true                              |
| `ca_certificate`         | No       | Custom CA certificate for SSL verification (PEM format)             | "-----BEGIN CERTIFICATE-----..."  |

\* One of `scim_token` or the username/password pair is required for authentication.

Example Configuration with Bearer Token:

```json
{
  "scim_url": "https://api.customerportal.internal.com/scim/v2",
  "scim_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "scim_extension_schemas": true
}
```

Example Configuration with Basic Authentication:

```json
{
  "scim_url": "https://legacy.mycompany.com/api/scim",
  "username": "scim-service-account",
  "password": "secure-password-here"
}
```

#### Push OAA Payload

Push the OAA Application Payload as normal. See the [Getting Started Guide](/4yItIzMvkpAvMVFAamTf/developers/api/oaa/getting-started.md) for details.

### Entity Types and Identity Mapping

Veza creates entities in Access Graph based on the OAA payload, which can be targeted in lifecycle management operations:

* `local_users` in your Application template → Users to provision via SCIM
* `local_groups` in your Application template → Groups to manage via SCIM

Entity types are named according to the following pattern:

* **User Entity Type**: `OAA.{application_type}.User`
* **Group Entity Type**: `OAA.{application_type}.Group`

Where {application\_type} is the value you specify in your OAA Application template when building the payload. For example, if the application is defined:

```python
custom_app = CustomApplication(
    name="CustomerPortal",           # Display name
    application_type="CustomerPortal" # This determines entity types!
)
```

The resulting entity types are:

* `OAA.CustomerPortal.User`
* `OAA.CustomerPortal.Group`

### Attribute Synchronization

#### Mapping OAA to SCIM

When Veza provisions users via SCIM, transformers can map attributes from your policy source of identity to SCIM properties:

| Veza Attribute (in Policy) | SCIM Property       | Type   | Required | Description                              |
| -------------------------- | ------------------- | ------ | -------- | ---------------------------------------- |
| `user_name`                | `userName`          | String | Yes      | Unique username                          |
| `emails`                   | `emails`            | Array  | No       | Email addresses                          |
| `display_name`             | `displayName`       | String | No       | User's display name                      |
| `title`                    | `title`             | String | No       | Job title                                |
| `nick_name`                | `nickName`          | String | No       | Casual name                              |
| `external_id`              | `externalId`        | String | No       | External system identifier               |
| `phone_numbers`            | `phoneNumbers`      | Array  | No       | Phone numbers (JSON array)               |
| `addresses`                | `addresses`         | Array  | No       | Physical addresses (JSON array)          |
| `ims`                      | `ims`               | Array  | No       | Instant messaging addresses (JSON array) |
| `photos`                   | `photos`            | Array  | No       | Photo URLs (JSON array)                  |
| `locale`                   | `locale`            | String | No       | User's locale                            |
| `preferred_language`       | `preferredLanguage` | String | No       | Preferred language                       |
| `profile_url`              | `profileUrl`        | String | No       | Profile page URL                         |
| `timezone`                 | `timezone`          | String | No       | User's timezone                          |
| `user_type`                | `userType`          | String | No       | User classification                      |
| `formatted_name`           | `name.formatted`    | String | No       | Full formatted name                      |
| `family_name`              | `name.familyName`   | String | No       | Last name                                |
| `given_name`               | `name.givenName`    | String | No       | First name                               |
| `middle_name`              | `name.middleName`   | String | No       | Middle name                              |

#### Extension Attributes

If the SCIM service exposes a `/Schemas` endpoint and you enable `scim_extension_schemas: true`, Veza can synchronize custom extension attributes beyond the standard SCIM user schema. Extension attributes are mapped using the schema URN as defined by your SCIM implementation.

### Provisioning Operations

The following SCIM operations are performed when Lifecycle Management actions execute:

#### Sync Identities (Create User)

Create a new user in the target application.

SCIM Operation:

```sh
POST /Users
Content-Type: application/scim+json
```

```json
{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "userName": "jane.doe",
  "name": {
    "givenName": "Jane",
    "familyName": "Doe",
    "formatted": "Jane Doe"
  },
  "emails": [
    {"value": "jane.doe@company.com", "primary": true}
  ],
  "active": true
}
```

The SCIM endpoint creates the user and returns the user object with an assigned id.

#### Sync Identities (Update User)

Updates an existing user's attributes (one-time or continuously).

SCIM Operations:

1. Query for existing user:

   ```sh
   GET /Users?filter=userName eq "jane.doe"
   ```
2. Update the user:

   ```sh
   PATCH /Users/{id}
   Content-Type: application/scim+json
   ```

   ```json
   {
     "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
     "Operations": [
       {"op": "replace", "path": "displayName", "value": "Jane Smith"}
     ]
   }
   ```

#### De-provision Identity

Remove access when a user leaves the organization or changes roles. The user account is deactivated, but data is preserved.

**SCIM Operation:**

```sh
PATCH /Users/{id}
Content-Type: application/scim+json
```

```json
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    {"op": "replace", "path": "active", "value": false}
  ]
}
```

Deprovision sets `active=false`, which disables login but preserves the user record.

#### Delete Identity

Permanently remove a user account.

**SCIM Operation:**

```sh
DELETE /Users/{id}
```

#### Manage Relationships (Add User to Group)

Grant a user access via group membership.

**SCIM Operations:**

1. Retrieve group details:

   ```sh
   GET /Groups/{groupId}
   ```
2. Add user to group:

   ```sh
   PATCH /Groups/{groupId}
   Content-Type: application/scim+json
   ```

   ```json
   {
     "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
     "Operations": [
       {
         "op": "add",
         "path": "members",
         "value": [{"value": "{userId}"}]
       }
     ]
   }
   ```

#### Manage Relationships (Remove User from Group)

Revoke a user's access by removing group membership.

**SCIM Operation:**

```sh
PATCH /Groups/{groupId}
Content-Type: application/scim+json
```

```json
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    {
      "op": "remove",
      "path": "members",
      "value": [{"value": "{userId}"}]
    }
  ]
}
```

#### Create Entitlement (Create Group)

Creates a new group so that it can be granted as an entitlement.

**SCIM Operation:**

```sh
POST /Groups
Content-Type: application/scim+json
```

```json
{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
  "displayName": "Engineering Team"
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.veza.com/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/integrations/oaa-scim.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
