If an Okta user is assigned to a SCIM app that already exists in the SCIM server with the same username, it is expected that the user will be reactivated or updated (based on context). However, if Okta attempts to create that user (by sending a POST /User request) instead, there is an issue that needs to be resolved.
Please see the meaning of the variables used in this article:
-
ScimServerBaseUrl - SCIM Server base URL, for example,
https://example.service.com/scim/v2. -
externalIdInOkta - Unique ID of user in SCIM database that is returned by SCIM server and is stored as the External ID field in the user's app profile in Okta.
- SCIM
- externalId
There is an issue where the SCIM server has (mistakenly) returned a response to Okta that indicates the user does not exist in the SCIM server, thus, Okta is sending a create user request for an already existing user.
When Okta attempts to create a user with a username that already exists in the SCIM Server database, the following scenarios can happen:
-
A user with the same username was created in the SCIM database first.
-
The user was assigned to the SCIM app in Okta and then unassigned. Therefore, it's trying to reassign the user.
In each case, the following sequence of requests should be sent to the SCIM server:
-
In this case user already exists in the SCIM database before being assigned to the SCIM app in Okta. In such case, Okta sends:
-
GET ${ScimServerBaseUrl}/User?filter=username eq "username". -
SCIM Server returns a list response with a matching (Okta username) user object.
-
Okta receives the user object and uses the Id as External Id of that user's app profile in Okta.
-
Since the user was (probably) already, Okta sent it
GET ${ScimServerBaseUrl}/User/{externalIdInOkta}followed by PUT${ScimServerBaseUrl}/User/{externalIdInOkta} to sync the profile.
-
-
Since it is a reassignment, the user was created by Okta in the first assignment and is deactivated (active=false) due to the last unassignment. Therefore, Okta sends:
-
GET ${ScimServerBaseUrl}/User?filter=username eq "username, -
SCIM Server returns a list response with a matching (Okta username) user object i.e., active=false for this use case.
-
Okta receives a deactivated user (active=false), therefore, it sends PATCH ${ScimServerBaseUrl}/User/{externalIdInOkta} to activate the user.
-
Okta sends GET ${ScimServerBaseUrl}/User/{externalIdInOkta} followed by PUT ${ScimServerBaseUrl}/User/{externalIdInOkta} to sync profiles,
-
In either case, the first request that is sent out is GET ${ScimServerBaseUrl}/User?filter=username eq "username", (this request is always sent out whenever the user is assigned to the SCIM app). In case when there is an attempt to create an existing user again, the SCIM server receives POST ${ScimServerBaseUrl}/User request to create this user instead of PATCH ${ScimServerBaseUrl}/User/{externalIdInOkta} or GET ${ScimServerBaseUrl}/User/{externalIdInOkta} to deactivate or update user respectively.
In the case of an existing user in the SCIM server, the response to GET ${ScimServerBaseUrl}/User?filter=username eq "jane.doe@example.com", should return:
{ "Resources": [ { "active": false, "id": 1, "meta": { "location": "http://scim-server.example.com/scim/v2/Users/1"", "resourceType": "User" }, "name": { "familyName": "Doe", "givenName": "Jane", "middleName": null }, "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "userName": "jane.doe@example.com" } ], "itemsPerPage": 1, "schemas": [ "urn:ietf:params:scim:api:messages:2.0:ListResponse" ], "startIndex": 0, "totalResults": 1}
This tells Okta that a single user with the username jane.doe@example.com exists and needs to be updated. If active: false, the user will be reactivated, however, generally speaking, the following three responses will cause the Okta to read that the user does not exist, therefore sending a create user request.
-
HTTP 404 - Not Found
-
Using string data type for the value of totalResults, instead of integer. For example,
{ "Resources": [ { "active": false, "id": 1, "meta": { "location": "http://scim-server.example.com/scim/v2/Users/1"", "resourceType": "User" }, "name": { "familyName": "Doe", "givenName": "Jane", "middleName": null }, "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "userName": "jane.doe@example.com" } ], "itemsPerPage": 1, "schemas": [ "urn:ietf:params:scim:api:messages:2.0:ListResponse" ], "startIndex": 0, "totalResults": "1"}
-
Or, setting the totalResults to be 0, despite including a user object in the Resources array:
{ "Resources": [ { "active": false, "id": 1, "meta": { "location": "http://scim-server.example.com/scim/v2/Users/1"", "resourceType": "User" }, "name": { "familyName": "Doe", "givenName": "Jane", "middleName": null }, "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:User" ], "userName": "jane.doe@example.com" } ], "itemsPerPage": 1, "schemas": [ "urn:ietf:params:scim:api:messages:2.0:ListResponse" ], "startIndex": 0, "totalResults": 0}
-
In general, altering totalResults, by skipping it altogether or using it wrong such as TotalResults or totalresults etc, can cause issues, such as returning responses in any way that would indicate the user does not exist. If this happens, please check SCIM specifications and Okta SCIM documentation for correct or expected responses.
