> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/connector-configuration/microsoft/13-successfactors.md).

# SuccessFactors connector

This page describes how to install and configure SuccessFactors connector in OpenIAM

The SuccessFactors connector lets OpenIAM provision and read **user accounts** in SAP SuccessFactors over its OData API. It is the one connector in this section that does not integrate a Microsoft application — it is here because it is built the same way, in .NET and PowerShell, and runs as a Windows service.

It provisions **users and nothing else**. Every operation refuses any other object type with a message saying so.

| Operation                     | Supported                                          |
| ----------------------------- | -------------------------------------------------- |
| Create / update a user (Save) | ✅                                                  |
| Search                        | ✅                                                  |
| Suspend                       | ✅ — sets the user's `status` to `f` (inactive)     |
| Resume                        | ✅ — sets `status` to `t` (active)                  |
| Reset password                | ✅ — **and re-activates the user**, see below       |
| Delete                        | ❌ **Refused.** SuccessFactors has no user deletion |
| Test connection               | ✅                                                  |

{% hint style="danger" %}
**Do not configure DELETE as the deprovisioning operation.** SuccessFactors does not delete users — the User entity supports no delete operation, and SAP's own SCIM integration maps DELETE to deactivation. The connector refuses the request outright rather than silently deactivating, so a deprovisioning policy that sends DELETE fails and the leaver keeps their account. **Use SUSPEND: deactivation is what removal means here.** Erasing the data itself is the tenant administrator's DRTM purge, outside the API.
{% endhint %}

{% hint style="warning" %}
**Resetting a password re-activates a suspended user.** `RESET_PASSWORD` writes `status: "t"` alongside the new password, so running it against a deactivated leaver brings the account back. Suspend again afterwards, or keep password resets out of any workflow that touches deactivated users.
{% endhint %}

## Use cases

* **SuccessFactors as the HR source of truth** — reading joiners, movers and leavers into OpenIAM, with their organizational data, and letting OpenIAM provision the rest of the estate from it.
* **Writing an identity back** — most often the corporate email address OpenIAM generated, returned to the employee record.
* **Deactivating leavers** in SuccessFactors as part of a wider deprovisioning run.

## Versions and compatibility

The end application is **SAP SuccessFactors**, reached over its **OData API** — so what matters is the API and the tenant's datacentre, not a product version. The connector authenticates with OAuth 2.0 using a SAML bearer assertion signed by a private key.

## Prerequisites

The operating system, `.NET Framework` and PowerShell requirements are the same for every .NET/PowerShell connector and are listed once in [Installing PowerShell connectors](/connector-configuration/microsoft/1-powershellconnectorinstallation.md#basic-requirements). Beyond those, the connector needs an **API user in SuccessFactors** with the right permissions.

SuccessFactors needs to have below permissions to do API operations.

* SF API user Security roles:
  * Administrator Permissions -> Employee Central API -> Employee Central HRIS OData API (editable).
  * Administrator Permissions -> Employee Central API -> Employee Central HRIS SOAP API.
  * To get permissions related to groups and roles, it is needed to add an API user in the section below.

## Installing the connector

Every .NET/PowerShell connector installs the same way. See [Installing PowerShell connectors](/connector-configuration/microsoft/1-powershellconnectorinstallation.md).

## Starting, stopping, and restarting

The installer registers a pair of Windows services named after the connector name you supply. See [Installing PowerShell connectors](/connector-configuration/microsoft/1-powershellconnectorinstallation.md#starting-stopping-and-restarting).

## Command-line parameters and properties

The connector takes no command-line parameters. Queue names, concurrency, logging, simulation mode and the RabbitMQ settings live in `Connector.config`, documented for the whole family in [Using PowerShell connectors](/connector-configuration/microsoft/2-powershellconnectorsusage.md#working-with-the-connector-configuration).

## Verifying the connector is running

{% stepper %}
{% step %}
Confirm the connector's Windows services are running on the host.
{% endstep %}

{% step %}
Check that the connector's request queue in RabbitMQ has a consumer.
{% endstep %}

{% step %}
Run **Test Connection** on the managed system. It performs a real authentication against the tenant and fails the test if the token cannot be obtained, so a pass means the datacentre URL, company id, API user, client id and private key all line up.
{% endstep %}

{% step %}
Run a search to prove the path end to end.
{% endstep %}
{% endstepper %}

## Troubleshooting

Troubleshooting for the whole family is in [Using PowerShell connectors](/connector-configuration/microsoft/2-powershellconnectorsusage.md). What follows is specific to this connector.

| Symptom                                                                                                              | Likely cause                                                                                                                   | Resolution                                                                            |
| -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| `SFSF does not support deleting user accounts`                                                                       | A DELETE was sent, and SuccessFactors has no delete                                                                            | Configure the deprovisioning policy to use SUSPEND instead                            |
| `SAVE routing addresses the SFSF User entity by its userId key, but this request arrived with principal attribute …` | The managed system's principal attribute is not `userId`                                                                       | Change it to `userId`, or point both save handlers at one script to bypass the lookup |
| `The request carries originalIdentityValue … differing from identityValue — a rename`                                | SuccessFactors user keys are immutable, so the built-in save cannot rename. Writing under the new key would create a duplicate | Change the key in SuccessFactors rather than through the connector                    |
| `The SAVE request carries no writable attribute`                                                                     | The attribute map produced nothing to create the user from                                                                     | Map at least one writable attribute in the policy map                                 |
| `… supports USER objects only, but the request arrived for type …`                                                   | The managed system's object type is not USER, and this connector provisions nothing else                                       | Set the object type to USER                                                           |

## Registering the connector in OpenIAM

The connector's request queue name in OpenIAM has to match the queue in the connector's own `Connector.config` exactly. Getting the connection parameters out of OpenIAM and into the installer is covered in [Installing PowerShell connectors](/connector-configuration/microsoft/1-powershellconnectorinstallation.md#getting-connection-parameters-with-openiam).

## Configuring the managed system

To make an OData API connection observe the required items from SuccessFactors. They are given in the table below.

| Field on the managed system | What goes in it                                                                                   |
| --------------------------- | ------------------------------------------------------------------------------------------------- |
| **Host URL**                | Your tenant's datacentre API address, for example `https://<your-datacenter>.successfactors.com/` |
| **Login Id**                | The SuccessFactors API user                                                                       |
| **Token URL**               | The OAuth token endpoint, `https://<your-datacenter>.successfactors.com/oauth/token`              |
| **Grant Type**              | `urn:ietf:params:oauth:grant-type:saml2-bearer` for the private-key flow                          |
| **Client Id**               | The registered OAuth client's id                                                                  |
| **Company Id**              | Your tenant's company id                                                                          |

Four of those — Token URL, Grant Type, Client Id and Company Id — are fields of their own on the managed system form, marked required:

<figure><img src="https://2965242200-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0uHWHRgcad6P03ehqgmX%2Fuploads%2Fgit-blob-0c3f101367a88441aad84b6ce8a839e126773ee7%2F13-successfactors-01-managed-system.png?alt=media" alt="The managed system form for the SuccessFactors connector, showing the Host URL and Login Id together with the Token URL, Grant Type, Client Id and Company Id fields, each marked required"><figcaption></figcaption></figure>

### Choosing the authentication method

The connector supports two ways of authenticating, chosen by the **`auth_method`** attribute on the managed system. Add it in the **Attributes** panel — it is not one of the named fields.

| `auth_method` | Authenticates with                                     | Attributes it needs                                                                   |
| ------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| `private_key` | An OAuth SAML bearer assertion signed by a private key | `token_url`, `private_key`                                                            |
| `ias`         | SAP Cloud Identity Services                            | `password`, `ias_client_id`, `ias_client_secret`, `ias_client_url`, `ias_application` |

{% hint style="warning" %}
**Set `auth_method` explicitly.** If the attribute is absent, every authenticating operation except the email write-back refuses the request with a message saying so. Only that one legacy path falls back to the private-key method on its own.
{% endhint %}

The **private key itself is an attribute**, not a form field: add `private_key` in the Attributes panel alongside `auth_method`. The same applies to the five `ias_*` attributes when that method is chosen.

The **principal attribute must be `userId`**. Save addresses the User entity by that key, and a request arriving with any other principal is refused.

### Custom handlers

Any operation can be routed to a script of your own, placed in the connector's installation folder.

{% hint style="info" %}
**The attribute names are not spelled consistently in this connector.** Two are upper case with underscores and five are camel case — `ADD_HANDLER`, `MODIFY_HANDLER`, `searchHandler`, `deleteHandler`, `passwordHandler`, `suspendHandler` and `resumeHandler`. Copying a handler configuration from another connector, where all seven are upper case, produces a setting the connector never reads and no error.
{% endhint %}

`ADD_HANDLER` and `MODIFY_HANDLER` replace the create and update halves of save. Pointing **both at the same script** has a special meaning: the connector skips the existence lookup entirely and runs the script directly, applying none of its built-in rules. That is the shape used for a write-back, where the create-or-update distinction does not matter and the API user needs no permission to read users.

A `deleteHandler` still runs before the delete refusal, so a script can define what deprovisioning means if suspension is not enough.

## Attribute mapping and policy map

**The lookup decides what save does, not the request.** On every save the connector looks the user up by `userId` first and creates the account when it is absent, updates it when it is found. The request's own add-or-update field is not consulted. The lookup deliberately includes **suspended** users, because suspension is this connector's deprovisioning — without that, every deactivated user would look absent and be created again. A lookup that fails stops the request rather than falling through to a blind create that would overwrite an existing user, password included.

Three rules apply to the built-in save path, though not to a handler-routed one:

| Rule                                                                                                      | Why                                                                                                                |
| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **It cannot rename.** A request whose `originalIdentityValue` differs from its `identityValue` is refused | SuccessFactors user keys are immutable, so writing under the new key would create a duplicate rather than rename   |
| **`password` is ignored on update.** It is written only when the account is created                       | Changing an existing user's password is what `RESET_PASSWORD` is for. The connector logs that it dropped the value |
| **Every mapped attribute is read as a single value**                                                      | Nothing in the User entity is multi-valued here                                                                    |

A create with no writable attribute beyond the key is refused — there is nothing to build the account from. An update in the same position is a legitimate no-op and reports success without sending an empty write.

User entity in SFSF requires some information. The table below gives the data for required fields and filterable fields.

| Field name           | Required | Filterable |
| -------------------- | -------- | ---------- |
| addressLine1         | false    | false      |
| addressLine2         | false    | false      |
| addressLine3         | false    | false      |
| businessPhone        | false    | false      |
| cellPhone            | false    | false      |
| citizenship          | false    | false      |
| city                 | false    | false      |
| companyExitDate      | false    | false      |
| country              | false    | false      |
| dateOfBirth          | false    | false      |
| dateOfPosition       | false    | false      |
| department           | false    | true       |
| division             | false    | true       |
| email                | false    | false      |
| empId                | false    | false      |
| fax                  | false    | false      |
| firstName            | false    | true       |
| gender               | false    | false      |
| hireDate             | false    | false      |
| homePhone            | false    | false      |
| jobCode              | false    | true       |
| jobTitle             | false    | false      |
| lastModified         | false    | true       |
| lastModifiedDateTime | false    | true       |
| lastName             | false    | true       |
| location             | false    | true       |
| manager              | false    | true       |
| hr                   | false    | true       |
| married              | false    | false      |
| mi                   | false    | false      |
| nationality          | false    | false      |
| ssn                  | false    | false      |
| timeZone             | false    | false      |
| title                | false    | false      |
| userId               | true     | true       |
| status               | true     | true       |
| username             | false    | true       |
| password             | false    | false      |
| zipCode              | false    | false      |

**Note:** Last Modified fields are not for save and update.

## Reconciliation and synchronization

How synchronization and reconciliation work in general is covered in the Administration guide — see [*Synchronize and import data*](/administration-guide/lifecycle/synchronize-and-import-data.md) and [*Configure reconciliation*](/administration-guide/lifecycle/configure-reconciliation.md).

Set the search string in the ***SQL Query / Directory Filter*** field on the synchronization page. The connector runs it as written, after checking that it is one pipeline that only reads, and the query decides everything the search returns.

**Filter examples**

| To find                         | Filter                                  |
| ------------------------------- | --------------------------------------- |
| One user by name                | `username eq 'sfadmin'`                 |
| Every active user               | `status eq 't'`                         |
| Everything changed since a date | `lastModified ge '2022-01-01T00:00:00'` |

The quoted values are SuccessFactors' own syntax and the quotes are part of the filter — `status eq t` without them is not the same query.

## Data access and privacy

This section explains what the connector actually reads from SAP SuccessFactors, how it authenticates, and — most importantly — **where the controls that limit its access are enforced**.

It is here because the most common question raised when connecting an identity management platform to SuccessFactors is not a functional one. It is a governance question: an integration should not be trusted to police itself. A statement that the connector "only queries the attributes it needs" describes the integration's intent; it is not a control that an HR or security team can audit or enforce.

That objection is correct, and this section answers it by separating two things:

* **What the connector does.** It authenticates with an OAuth 2.0 SAML bearer assertion, issues HTTP `GET` requests against a fixed set of OData v2 entities, selects an explicit configured field list, and returns only those fields to OpenIAM. There is no bulk export and no access to modules outside the entities listed below.
* **What constrains it.** SuccessFactors Role-Based Permissions (RBP) assigned to the dedicated API account. RBP restricts that account at the entity level, the field level and the target-population level, and it is enforced by SuccessFactors when the request is served — independently of anything the connector asks for. If a field is not permitted, SuccessFactors does not return it.

{% hint style="info" %}
The recommended posture is to rely on RBP, not on the connector's configuration. Grant the API account only the fields and population the integration needs, and the connector cannot exceed that boundary regardless of how it is configured.
{% endhint %}

### How the integration works

#### Direction of flow

In an HR-driven identity lifecycle, SuccessFactors is the system of record and OpenIAM is the consumer. The default configuration is one-directional:

{% code overflow="wrap" %}

```
SuccessFactors (OData v2, HTTPS)  --read-->  OpenIAM connector  -->  OpenIAM identity store  -->  AD / Entra ID / applications
```

{% endcode %}

OpenIAM reads worker records on a schedule, detects joiners, movers and leavers, and provisions or de-provisions accounts in downstream systems.

Write-back to SuccessFactors — for example returning a generated corporate email address to the worker record — is a separate, optional capability. It is disabled unless explicitly configured, and it cannot be enabled unilaterally: it requires edit permission on the API account in RBP. If only read permission is granted, SuccessFactors rejects the write.

#### Authentication

The connector uses the OAuth 2.0 SAML bearer assertion flow, SAP's recommended method for API integrations:

1. An OAuth client is registered in **Admin Center → Manage OAuth2 Client Applications**, with an X.509 certificate generated or uploaded.
2. The connector builds a SAML assertion for the designated API user, signs it with the private key, and exchanges it at the token endpoint (`/oauth/token`) for a short-lived bearer token.
3. The token authorizes subsequent OData requests and is refreshed as it expires. It is held in memory for the duration of the run and is not persisted.

The connection parameters themselves are listed under [Configuring the managed system](#configuring-the-managed-system) above; none of them is a user password.

This has several consequences that matter in a security review:

* **No SuccessFactors user password is stored by OpenIAM.** The credential is an X.509 private key held encrypted in the connector's configuration store.
* **Access can be revoked by the customer at any time** by deleting the OAuth client in Admin Center — no OpenIAM involvement, and no waiting for a password change.
* **The API account is a service account.** It should have no UI access, no manager or HR administrator role, and no target population beyond what the integration requires.
* Deployments that front SuccessFactors with SAP Cloud Identity Services (IAS) are also supported; in that pattern the token is obtained from IAS and exchanged for a SuccessFactors assertion.

#### Query pattern

Every read is an HTTP `GET` against a named OData v2 entity with an explicit `$select` list, an optional `$filter`, and server-side paging:

{% code overflow="wrap" %}

```
GET /odata/v2/User?$select=userId,username,status,firstName,lastName,email,department,manager/userId
    &$filter=lastModifiedDateTime ge '2026-08-01T00:00:00'&$top=200&$skip=0&$format=JSON
```

{% endcode %}

Three properties of this pattern are relevant to a privacy assessment:

* **Explicit projection.** `$select` is built from the attribute mapping configured in OpenIAM. Fields not in the mapping are not requested and are not present in the response payload.
* **Delta-based.** After the initial load, scheduled runs filter on `lastModifiedDateTime` (or the equivalent on `EmpJob`), so an incremental run touches only changed records.
* **Paged.** Results are retrieved 200 records at a time. This is a throughput control rather than a security control, but it makes the integration's load on the tenant predictable and visible in the SuccessFactors API audit log.

### Entities the connector can access

The connector is not a generic OData browser. It calls a fixed set of endpoints; anything not in this table is never called.

| OData endpoint                                  | Purpose                                                                                                                                                                   | Used when                                              |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| `User`                                          | Core worker identity attributes: `userId`, `username`, `status`, name, email, organizational assignment, manager and HR business partner references.                      | Always                                                 |
| `EmpJob` (with employment / person navigations) | Employment and job data driving lifecycle events: employment status, start and end dates, job title, department, division, business unit, cost center, location, manager. | Employee Central deployments                           |
| `User/$count`                                   | Returns a record count so the connector can page correctly.                                                                                                               | Always                                                 |
| `getUserRolesByUserId`                          | Returns the SuccessFactors permission roles held by a user, for certification.                                                                                            | Only if role import is enabled                         |
| `getDynamicGroupsByUser`                        | Returns the permission groups a user belongs to, for the same purpose.                                                                                                    | Only if group import is enabled                        |
| `Photo`                                         | Worker photograph, where photos are synchronized to the corporate directory.                                                                                              | Only if explicitly enabled                             |
| `upsert`                                        | The single write endpoint, used only for optional write-back (for example `PerEmail`).                                                                                    | Only if write-back is enabled **and** permitted in RBP |

**Not accessed:** compensation and pay, performance and goals, succession and talent, recruiting and candidate data, learning records, benefits, time and attendance, payroll, absence, and document attachments. These modules have their own OData entities which this connector does not call, and to which the API account should not be granted permission.

### Attributes required for identity lifecycle

The list below is the working baseline for a joiner-mover-leaver integration. Every line can be challenged; the integration functions with a reduced set at the cost of the capability noted.

| Attribute                                            | Why it is needed                                                                                 | Sensitivity             |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------- |
| `userId` / `personIdExternal`                        | Immutable key tying a SuccessFactors worker to an OpenIAM identity across the lifecycle.         | Identifier              |
| `username`                                           | Basis for the corporate login name where the two are aligned.                                    | Low                     |
| `status` / employment status                         | Drives enable, disable and de-provision. The single most important attribute for leaver control. | Low                     |
| `firstName`, `lastName`, middle initial              | Account naming, display name, directory entry.                                                   | Low — business identity |
| `email` (business)                                   | Correlation with existing accounts, notification routing.                                        | Low — business contact  |
| `employeeId`                                         | Correlation key used by downstream systems.                                                      | Identifier              |
| `hireDate` / `startDate`                             | Schedules account creation ahead of day one.                                                     | Low                     |
| `endDate` / termination date                         | Schedules disablement at the right moment rather than after the fact.                            | Low                     |
| `jobTitle`, `jobCode`                                | Directory attributes and role-assignment rules.                                                  | Low                     |
| `department`, `division`, business unit, cost center | Organizational placement; drives birthright entitlement rules.                                   | Low                     |
| `location`, `country`                                | Regional routing rules and data-residency handling.                                              | Low                     |
| `manager` (userId), HR business partner (userId)     | Approval routing for access requests and certification campaigns.                                | Low — reference only    |
| `lastModifiedDateTime`                               | Delta detection so scheduled runs read only changed records.                                     | Metadata                |

#### Attributes to exclude

The connector can read a wider set of fields because different deployments need different things. For a standard identity deployment, leave the following out of both the attribute mapping and the API account's field permissions:

* National identifiers (SSN, national ID, tax ID)
* Date of birth, gender, marital status, nationality, citizenship
* Home address, personal phone numbers, personal email
* Compensation, performance ratings, disciplinary or medical information

If a downstream requirement genuinely needs one of these, it should be raised explicitly, justified, and permitted individually rather than arriving as part of a broad grant.

### Where the controls are enforced

Controls exist in three layers. Only the first is enforced by SuccessFactors itself, and it is the one that should be relied on.

#### Layer 1 — SuccessFactors Role-Based Permissions

RBP is owned, configured and audited by the customer. It cannot be circumvented by the connector because SuccessFactors applies it when serving the request.

| Control               | How it is applied                                                                                                                                                                                                                             |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Entity-level access   | Grant the API permission role only the OData API permissions the integration needs — typically **Employee Central HRIS OData API (read-only)**. Withhold edit unless write-back is agreed, and withhold every other module's API permission.  |
| Field-level access    | Under **User Permissions → Employee Data**, grant `View` on only the agreed fields. A field that is not granted is not returned to this API account, whatever it asks for. This is the enforced equivalent of the connector's `$select` list. |
| Target population     | Assign the permission role to a permission group whose target population is limited to the workers in scope — for example a single legal entity or country during a proof of concept.                                                         |
| Credential revocation | The OAuth client can be deleted or its certificate rotated at any time in Admin Center, immediately cutting access.                                                                                                                           |
| Network restriction   | API access for the account can be restricted to defined source IP addresses (login exceptions in **Password & Login Policy Settings**), making the credential unusable from anywhere else.                                                    |
| Audit                 | Calls made by the account appear in the SuccessFactors API audit facilities, showing what was called and when — independent of OpenIAM's own logs.                                                                                            |

{% hint style="success" %}
**Recommended verification step.** Before go-live, authenticate as the API account and issue a deliberately over-broad query — request a field that is not on the agreed list. The request should fail or the field should be absent. That single test converts the assurances in this section into evidence produced by the customer's own team.
{% endhint %}

#### Layer 2 — Connector configuration

* The attribute mapping is explicit configuration, not code. It can be exported and reviewed, and changes to it are visible.
* The `$select` list is generated from that mapping, so the request itself carries the restriction.
* Filters can restrict the population further (for example `status eq 't'` combined with a specific company code).
* Write-back, role import and group import are separate switches, off by default.

This layer is defense in depth and a description of intent. It is not a substitute for Layer 1 and should not be accepted as one.

#### Layer 3 — Handling of data once it reaches OpenIAM

| Question                  | Answer                                                                                                                                                                                                                                                    |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Where is the data stored? | In the OpenIAM identity store. For an on-premises or customer-cloud deployment, that database sits inside the customer's own infrastructure and network boundary.                                                                                         |
| What is stored?           | Only the mapped attributes, held as the current state of each identity. Raw API responses are not retained.                                                                                                                                               |
| Is the data encrypted?    | TLS 1.2 or higher for every call in transit. At rest, the deployment uses the database and storage encryption applied to that platform; sensitive configuration values such as the private key are held encrypted in the connector's configuration store. |
| Who can see it?           | Access is governed by OpenIAM's role model and delegated administration; administrators see only identities within their scope, and administrative actions are logged.                                                                                    |
| What appears in logs?     | Operational logs record the operation, record counts and outcomes. Attribute values are not written at normal log levels; debug-level tracing is for troubleshooting only and should be disabled afterwards.                                              |
| Deletion and retention    | Identity records follow the retention rules configured for the deployment. A worker removed from scope is de-provisioned and can then be purged according to policy.                                                                                      |

### Deployment patterns

Where policy does not permit direct API access to the production tenant, two alternatives are supported. Neither requires a change to the connector.

| Aspect                | A. Direct, RBP-restricted                                                                                              | B. Dedicated tenant                                                                                            | C. CPI intermediary                                                                     |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| How it works          | The connector calls the production tenant using an API account whose RBP grants only the agreed fields and population. | A separate SuccessFactors tenant is populated with only the agreed attributes; the connector points at it.     | Data is exchanged through SAP Integration Suite, which projects only the agreed fields. |
| Control sits with     | HR/SF team, via RBP configuration.                                                                                     | HR/SF team, via what they choose to replicate.                                                                 | Integration team, via the CPI iFlow.                                                    |
| Data freshness        | Real time, delta-driven.                                                                                               | Depends on the replication schedule; adds latency.                                                             | Near real time, depending on iFlow design.                                              |
| Effort to build       | Low — permission configuration only.                                                                                   | High — tenant provisioning, licensing, and a replication process to build and operate.                         | Medium to high — iFlow design, testing and lifecycle ownership.                         |
| Ongoing burden        | Minimal; permission changes only when the attribute list changes.                                                      | Permanent — the replication job becomes production infrastructure that must be monitored.                      | Permanent — the iFlow is another component to version, monitor and support.             |
| Failure mode to watch | Over-granting permissions by habit; mitigated by periodic review of the API role.                                      | Divergence between tenants: a leaver processed in production but not replicated leaves access live downstream. | Silent iFlow failure produces the same stale-data risk.                                 |
| Change to OpenIAM     | None.                                                                                                                  | None — standard connector.                                                                                     | None — standard connector, or file/API handoff.                                         |

**Recommendation.** Pattern A, with RBP configured tightly, gives the strongest combination of security and operational reliability: enforcement sits in SuccessFactors under HR's control, and there is a single source of truth. Every additional hop introduced by patterns B and C is a place where identity data can silently go stale, and stale identity data is itself a security problem — a leaver de-provisioned late is a larger exposure than an over-broad read that was never exercised.

Where patterns B or C are chosen, settle the replication or iFlow schedule and the alerting on its failure early. The connector cannot detect a leaver whose termination never reached the tenant it reads.

### Configuration checklist

| #  | Step                                                                                                                                      | Owner             |
| -- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| 1  | Agree the final attribute list; remove anything not justified by a downstream requirement.                                                | Joint             |
| 2  | Create a dedicated API service account with no UI access and no HR administrator role.                                                    | SF team           |
| 3  | Create a permission role for the integration. Grant Employee Central HRIS OData API read-only; withhold edit unless write-back is agreed. | SF team           |
| 4  | Under Employee Data, grant `View` on only the agreed fields. Confirm sensitive fields are not granted.                                    | SF team           |
| 5  | Create a permission group for the API account and set its target population to the in-scope workers.                                      | SF team           |
| 6  | Register an OAuth2 client application and generate or upload the X.509 certificate.                                                       | SF team           |
| 7  | Restrict API login for the account to the connector's source IP addresses.                                                                | SF team           |
| 8  | Provide the API URL, company ID, API user name, client ID and private key through a secure channel.                                       | SF team → OpenIAM |
| 9  | Configure the connector's attribute mapping and filter to match the agreed list exactly.                                                  | OpenIAM           |
| 10 | Run the negative test: query a non-permitted field with the API credential and confirm it is refused.                                     | SF team           |
| 11 | Run an initial load against the restricted population and reconcile record counts on both sides.                                          | Joint             |
| 12 | Review the SuccessFactors API audit log after the first week and confirm the calls match this section.                                    | SF team           |
| 13 | Review the API permission role periodically — at least annually, and whenever the attribute list changes.                                 | SF team           |

### Frequently asked questions

**Can the connector read our entire employee database?** Only if the API account is permitted to. The connector requests a defined field list from the entities above, but the boundary that matters is the one set in RBP. Grant `View` on fifteen fields for one legal entity and that is the maximum the credential can return — including if the connector's configuration were changed.

**How do we know it stays read-only?** Grant the API permission role read access only and withhold edit. SuccessFactors will then reject any write, including the optional write-back endpoint. That is an enforced control that survives configuration changes and version upgrades on the OpenIAM side.

**A query-level restriction isn't a real control. What is?** Agreed. The enforced controls are RBP field-level and target-population permissions on the API account, IP restriction on the credential, and the SuccessFactors API audit log. All of them are configured by the customer.

**Does the connector access compensation, performance or payroll data?** No. Those modules use different OData entities which the connector never calls. Withholding the corresponding permissions from the API account makes it structurally impossible rather than merely unintended.

**Does personal data leave the customer environment?** For an on-premises or customer-cloud deployment, no — the connector and identity store run inside the customer's infrastructure. For an OpenIAM-hosted deployment, the hosting region and applicable data protection terms are set out in the contract.

**What credentials does OpenIAM hold?** A registered OAuth client ID, an X.509 private key held encrypted in the connector's configuration store, and the API user name. No SuccessFactors user password is stored.

**Can the connector create or modify workers in SuccessFactors?** Not unless edit permission is granted. Write-back is optional, off by default, and requires an RBP grant that only the customer can make.

**How often does it run, and what load does it place on the tenant?** Typically once or twice daily for a full reconciliation and every 15 to 60 minutes for delta runs; the schedule is configurable. Delta runs read only changed records, so steady-state volume is small.

**Can the integration be limited to a subset of employees during a proof of concept?** Yes, and it is recommended. Restrict the API account's target population in RBP to one legal entity, country or division, and scope the connector's `$filter` to the same population so both sides agree.

**Can we see exactly what the connector requested?** Yes, from two independent sides: the SuccessFactors API audit facilities show the calls made by the API account, and OpenIAM's synchronization logs show each run, the query issued, record counts and results. The SuccessFactors side is the authoritative record because it is entirely customer-controlled.

**How do we roll back?** Delete the OAuth client in Admin Center. Access stops immediately with no dependency on OpenIAM. A read-only integration alters nothing in SuccessFactors, so there is nothing to unwind.

## Additional notes

If API users will not have required permissions, then nothing will work. Before starting, please make sure API users will have all the required permissions as mentioned above.

Additionally, one need to consider the following when working with suspend users in SuccessFactors:

### Search after suspend

**Q. A search right after a SUSPEND returns nothing. Why?**

I’m trying to get a user after sending SUSPEND - I got an empty value. In SFSF if the user is inactive, it will not appear in the query. Is it the limit of SuccessFactors? Why cannot we return a user with status = f?

**A.** This is a SFSF limitation.

Search is used to detect whether a user exists before saving.

### Provisioning a new user in OpenIAM

SuccessFactors have user with userId = test01 and status =f (suspended)

OpenIAM has no such user. A new user is created with userId = test01 and sent provision to the connector.

Question: What are connector actions for this? Got an error? Override suspended users in SuccessFactors?

*Answer*: It will be active because the user ID is already there and the status is sent = t means 'make him active'.

3. Synchronization

Question: We search users in SuccessFactors and create users in OpenIAM. We can't synchronize a suspended user. And in OpenIAM their status was not changed (We don't know if their status is suspended or such user does not exist).

*Answer*: Nothing can be said here due to SFSF limitations.

4. Reconciliation

Question: We have different action for different cases, for example:

* Users exist in OpenIAM and SuccessFactors - one action (for example update user on OpenIAM from SuccessFactors or update user in SuccessFactors from OpenIAM.)
* Users exist in OpenIAM but do not exist in SuccessFactors - other actions.

Do we create users in SuccessFactors, or delete users in OpenIAM?

We need to have information if a user exists but has a disabled status.

*Answer*: Nothing can be said here due to SFSF limitations.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/connector-configuration/microsoft/13-successfactors.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
