SCIM Connector with Azure APIM – Synchronization succeeds, but provisioning fails due to missing subscription key

Hi everyone,

In our project, we are using the SCIM connector to integrate with SAP CIS, with Azure API Management (APIM) serving as the API gateway. In our configuration, APIM requires an Ocp-Apim-Subscription-Key to be included in every request header, regardless of the endpoint or HTTP operation. Authentication is handled via Basic Authentication using a provided username and password.

During the endpoint configuration wizard in OneIM, we successfully passed the required subscription key as a query parameter in the URL. Additionally, we defined a custom header for the Ocp-Apim-Subscription-Key. With this setup, we were able to complete the synchronization from the SCIM provider through APIM to both the UCI and CSM tables using:

  • a SCIM-based synchronization project and

  • a follow-up sync project using the UCI connector.

This configuration allowed us to successfully read users, groups, and memberships into OneIM 9.2.1 — everything worked as expected during synchronization.

However, an issue arises during provisioning, specifically when attempting to add memberships. While the memberships are initially written into the CSM layer and correctly passed to UCI, the provisioning to SAP CIS via the API gateway fails. The related job (UCI_UCIGroup_Update) freezes and throws an error indicating that the Ocp-Apim-Subscription-Key was not provided, even though the same header worked reliably for all previous GET operations. The exact error message of the frozen jobs states:


[1777018] Error running synchronization project (SAP CIS (HTTPS://DEV.API.XXX.COM))'s workflow (Provisioning).

[1777124] Error running synchronization step (Group) of synchronization configuration (Provisioning (Provisioning)).

[1777004] Method (Update object (Update)) could not be run successfully.

[System.Exception] Error returned: { "statusCode": 401, "message": "Access denied due to missing subscription key. Make sure to include subscription key when making requests to an API." }

Error returned: ...

HTTP request returned the "ProtocolError" state. This state shows processing errors. URI : dev.api.XXX.com/.../6f9606a6-7ea1-4242-96e9-7c4a8c9eea57

Error returned: The remote server returned an error: (401) Unauthorized.

Sending data {

  "displayName": "SCIM-DEV-1",

  "members": [

    {

      "$ref": "https://XXX.com/scim/Users/1f814d14-a136-4b80-83a4-1591d6436ab8",

      "type": "User",

      "value": "1f814d14-a136-4b80-83a4-1591d6436ab8"

    },

    {

      "type": "User",

      "value": "0018db4f-ee38-4ddd-9e16-84cabf30428e"

    }

  ],

  "schemas": [

    "urn:ietf:params:scim:schemas:core:2.0:Group"

  ]

}

Sending PUT request using URI dev.api.XXX.com/.../6f9606a6-7ea1-4242-96e9-7c4a8c9eea57

Sending GET request using URI dev.api.XXX.com/.../6f9606a6-7ea1-4242-96e9-7c4a8c9eea57

Method OnCommitObject called.



   at VI.Projector.JobComponent.ProjectorComponent._AdHocProjection()

   at VI.Projector.Database.ProjectorExecutor.Project(ISession session, IProjectionConfiguration configuration, ProjectionOption options, ISystemObject adHocObject, CancellationToken cancellationToken)

   at VI.Projector.Projection.Extensions.Execute(IProjectorEngine engine, IProjectionConfiguration configuration, ProjectionOption options, ISystemObject adHocObject, CancellationToken cancellationToken)

   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)

   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)

   ---- Start of Inner Exception ----

   at VI.Projector.Projection.ProjectorEngine.d__3.MoveNext()

   ---- Start of Inner Exception ----

   at VI.Projector.Projection.ProjectorEngine.d__3.MoveNext()

   ---- Start of Inner Exception ----

   at VI.Projector.Projection.ProjectorEngine.d__3.MoveNext()

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

--- End of stack trace from previous location where exception was thrown ---

   at VI.Projector.Projection.ProjectionStrategy.d__3.MoveNext()

   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

--- End of stack trace from previous location where exception was thrown ---

   at VI.Projector.Projection.ProjectionStrategyBase.d__6.MoveNext()

   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

--- End of stack trace from previous location where exception was thrown ---

   at VI.Projector.Projection.ProjectionStrategyBase.d__22.MoveNext()

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

--- End of stack trace from previous location where exception was thrown ---

   at VI.Projector.Projection.ProjectionStrategyBase.d__26.MoveNext()

   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

--- End of stack trace from previous location where exception was thrown ---

   at System.Threading.Tasks.Task.Execute()

   at System.Threading.Tasks.Task`1.InnerInvoke()

   at VI.Projector.Projection.ProjectionStrategyBase.<>c__DisplayClass26_0.b__13()

   at VI.Projector.Projection.ProjectionStrategyBase._ExecuteMethods(IProjectionStep step, SystemObjectMatchingSet matchingSet, ISystemConnection connection, ISchemaMethodAssignment[] methodAssignments, IList`1 systemObjectPairs, SystemMappingSide side, ProjectionDirection projectionDirection, Boolean forceReloadObject, Boolean ignoreQuotas)

   at VI.Projector.Projection.ProjectionStrategyBase._ExecuteMethodNative(ISystemConnection connection, SystemObjectMatchingSet matchingSet, ISchemaMethod method, IReadOnlyCollection`1 objectsWithAncestryToExecute, Boolean reloadObjects, Boolean isImport)

   at VI.Projector.Connection.Connections.BottleNeckConnection._Redirect[T](Func`1 redirection)

   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)

   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)

   ---- Start of Inner Exception ----

   at VI.Projector.Connection.Connections.BottleNeckConnectionTask.Execute()

   at VI.Projector.Connection.SystemConnection.ExecuteMethod(ISchemaMethod method, IEnumerable`1 systemObjects, ExecuteMethodOptions option)

   ---- Start of Inner Exception ----

   at VI.Projector.Connection.SystemConnection.ExecuteMethod(ISchemaMethod method, IEnumerable`1 systemObjects, ExecuteMethodOptions option)

   at VI.Projector.Connection.SystemConnection._EvaluateResult(SystemConnectorResult result, ExceptionHandling exceptionHandling)

Synchronization ended with errors.

You can find more detailed information in the log from Dienstag, 20. Mai 2025.

To support the use of PATCH (instead of PUT) during provisioning, we configured the connector to read the SCIM settings dynamically from the /ServiceProviderConfig endpoint. As expected, this resulted in a slightly different error message — indicating that a PATCH request was attempted — however, the core issue remained: a 401 Unauthorized response.

To rule out any misconfiguration, we reverted to the default SCIM configuration (by emptying all endpoint configurations), which uses PUT. This fallback behavior is confirmed by the error message, which now explicitly references the PUT operation. Despite restoring this default behavior and ensuring that authentication credentials, endpoint URLs, and the custom header (Ocp-Apim-Subscription-Key) were correctly configured, the issue persists.

It’s important to note that we did not modify any other settings in the SCIM connector wizard beyond:

  • providing Basic Authentication credentials,

  • using the default endpoint setup, and

  • configuring the custom header.

Current open question:

Is it possible that custom headers configured in the SCIM connector only apply to synchronization operations, but not to provisioning tasksAny insights into whether additional configuration is required for custom headers to be applied during provisioning, or whether this is a limitation of the current connector implementation, would be greatly appreciated.

Parents Reply Children