Odd behavior between tenant and custom saas connector - is this normal?

I have created a custom SaaS connector and I’m currently testing it out, but I have noticed some odd behavior that I do not see with VA-based OOB connectors.

This post became very long so here are the different scenarios I’ve observed

  1. Access requests for identities without an account in the source send multiple duplicate provisioning requests to the connector after the original create/update request
  2. Access requests to revoke existing access get “thrown away” by the create-access-request API endpoint
  3. The tenant continually sends re-provisioning requests for existing access to the connector via “Identity Refresh” activities

It seems to me that somewhere the tenant “doesn’t know” the identity has that access, so it’s continually sending re-provisioning requests, which might explain why scenario 2 isn’t working. However, access can be removed successfully via a campaign. Happy to provide any code samples, as my suspicion is there’s some sort of issue with how the account response is being sent back to IdN

Here are the scenarios in detail

Scenario 1 - Access request for identity without account sends multiple duplicate std:account:update commands

Here is the connector log when this happens

[2024-03-21T08:24:36.510-05:00] INFO  | invokeCommand    ▶︎ Command execution started : std:account:create, for connector version 12.
[2024-03-21T08:24:36.516-05:00] INFO  | connectorMessage ▶︎ {"commandType":"std:account:create","invocationId":"ac796335-9e6e-4984-8ff1-44ba17f97004","message":"std:account:create","productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:36.516-05:00] INFO  | connectorMessage ▶︎ {"attributes":{"email_address":"[email protected]","full_name":"Alex L","groups":"133","status":"A","user_name":"Alex L"},"commandType":"std:account:create","invocationId":"ac796335-9e6e-4984-8ff1-44ba17f97004","key":{"simple":{}},"productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:37.538-05:00] INFO  | connectorMessage ▶︎ {"commandType":"std:account:create","invocationId":"ac796335-9e6e-4984-8ff1-44ba17f97004","message":"New Account Created for Alex L","productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:37.559-05:00] INFO  | commandOutcome   ▶︎ Command completed: std:account:create, for connector version 12.output_count=1 keep_alive_count=0 state_count=0. Elapsed time 1047ms
[2024-03-21T08:24:39.655-05:00] INFO  | invokeCommand    ▶︎ Command execution started : std:account:update, for connector version 12.
[2024-03-21T08:24:39.657-05:00] INFO  | connectorMessage ▶︎ {"commandType":"std:account:update","invocationId":"d065206c-dc74-4e27-b5c1-5d85ad54f700","message":"std:account:update","productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:39.660-05:00] INFO  | connectorMessage ▶︎ {"changes":[{"attribute":"groups","op":"Add","value":"133"}],"commandType":"std:account:update","identity":"307","invocationId":"d065206c-dc74-4e27-b5c1-5d85ad54f700","key":{"simple":{"id":"307"}},"productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:41.611-05:00] INFO  | commandOutcome   ▶︎ Command completed: std:account:update, for connector version 12.output_count=1 keep_alive_count=0 state_count=0. Elapsed time 1954ms
[2024-03-21T08:24:45.050-05:00] INFO  | invokeCommand    ▶︎ Command execution started : std:account:update, for connector version 12.
[2024-03-21T08:24:45.051-05:00] INFO  | connectorMessage ▶︎ {"commandType":"std:account:update","invocationId":"31d7ddff-d49a-4fe8-8c44-f10ddf1f10eb","message":"std:account:update","productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:45.054-05:00] INFO  | connectorMessage ▶︎ {"changes":[{"attribute":"groups","op":"Add","value":"133"}],"commandType":"std:account:update","identity":"307","invocationId":"31d7ddff-d49a-4fe8-8c44-f10ddf1f10eb","key":{"simple":{"id":"307"}},"productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:45.875-05:00] INFO  | connectorMessage ▶︎ {"commandType":"std:account:update","invocationId":"31d7ddff-d49a-4fe8-8c44-f10ddf1f10eb","message":"Not sending a provisioning request for Alex L into group id 133 since user already has access assigned","productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:46.443-05:00] INFO  | commandOutcome   ▶︎ Command completed: std:account:update, for connector version 12.output_count=1 keep_alive_count=0 state_count=0. Elapsed time 1392ms
[2024-03-21T08:24:50.280-05:00] INFO  | invokeCommand    ▶︎ Command execution started : std:account:update, for connector version 12.
[2024-03-21T08:24:50.282-05:00] INFO  | connectorMessage ▶︎ {"commandType":"std:account:update","invocationId":"77d2dad5-cdbf-4867-bc3f-ba04d849b4d5","message":"std:account:update","productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:50.285-05:00] INFO  | connectorMessage ▶︎ {"changes":[{"attribute":"groups","op":"Add","value":"133"}],"commandType":"std:account:update","identity":"307","invocationId":"77d2dad5-cdbf-4867-bc3f-ba04d849b4d5","key":{"simple":{"id":"307"}},"productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:51.123-05:00] INFO  | connectorMessage ▶︎ {"commandType":"std:account:update","invocationId":"77d2dad5-cdbf-4867-bc3f-ba04d849b4d5","message":"Not sending a provisioning request for Alex L into group id 133 since user already has access assigned","productFlags":["ACCESS_REQUEST","CERTIFICATION","PROVISIONING","SOD"],"version":12}
[2024-03-21T08:24:51.692-05:00] INFO  | commandOutcome   ▶︎ Command completed: std:account:update, for connector version 12.output_count=1 keep_alive_count=0 state_count=0. Elapsed time 1410ms

Here is what see command-wise

  1. std:account:create with a bundled std:account:update command, seemingly for the account create and the provisioning. However, the StdAccountCreateInput object includes any entitlements that need to be provisioned, so I don’t understand why the separate update command is sent
  2. There is a separate std:account:update command sent afterwards. You’ll see in the log entries saying “not sending a provisioning request since user already has acces assigned” because this particular app will throw a 400 if you try and provision access that already exists. So in order to avoid that, I had it run a check to see if the access is already provisioned before sending the request
const assignUserGroup = async (account: Account, group: string) => {
        //double-check access isn't already assigned to avoid a unique constraint error
        const access_response = await httpClient.getUserGroupRel(account.identity,group)
        if(access_response.data.header.data_rows == 0){
            await httpClient.assignUserGroup(account.identity, group)
        }
        else{
            logger.info(`Not sending a provisioning request for ${account.attributes.full_name} into group id ${group} since user already has access assigned`)
        }
    }

You can actually see that the tenant sent three separate std:account:update requests after the original std:account:create/std:account:update commands in the account activities table. The “duplicate” requests appear to be of type “Identity Refresh” whereas the create/update is of type “appRequest”

[
    {
        "completed": "2024-03-21T13:24:52.346Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f823574275b5",
            "name": "Alex L"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "91e8c9d57ce04872a6fc05b51d9a67a9",
                "name": "91e8c9d57ce04872a6fc05b51d9a67a9",
                "requested": "2024-03-21T13:24:52.015Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "307",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "04dc636ef1ae47abababe385774cec95",
        "name": "04dc636ef1ae47abababe385774cec95",
        "created": "2024-03-21T13:24:52.016Z",
        "modified": "2024-03-21T13:24:52.365Z"
    },
    {
        "completed": "2024-03-21T13:24:47.435Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f823574275b5",
            "name": "Alex L"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "cd723185532c48768141bde01ff8fd99",
                "name": "cd723185532c48768141bde01ff8fd99",
                "requested": "2024-03-21T13:24:46.970Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "307",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "90e642cfe40e4ae19ffc0d327aadefd4",
        "name": "90e642cfe40e4ae19ffc0d327aadefd4",
        "created": "2024-03-21T13:24:46.973Z",
        "modified": "2024-03-21T13:24:47.459Z"
    },
    {
        "completed": "2024-03-21T13:24:42.104Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f823574275b5",
            "name": "Alex L"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "ec04a67fc21c45c6b49bfbfa72bce526",
                "name": "ec04a67fc21c45c6b49bfbfa72bce526",
                "requested": "2024-03-21T13:24:41.788Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "307",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "5bd6113f92f94b27b547fd448732da76",
        "name": "5bd6113f92f94b27b547fd448732da76",
        "created": "2024-03-21T13:24:41.790Z",
        "modified": "2024-03-21T13:24:42.109Z"
    },
    {
        "completed": "2024-03-21T13:24:44.392Z",
        "completionStatus": "SUCCESS",
        "type": "appRequest",
        "requesterIdentitySummary": {
            "id": "2c91808c6d788165016d888db43b3948",
            "name": "chk_admin"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f823574275b5",
            "name": "Alex L"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "12747411c0f44b768fbac6443da47478",
                "name": "12747411c0f44b768fbac6443da47478",
                "requested": "2024-03-21T13:24:24.684Z",
                "approvalStatus": "FINISHED",
                "provisioningStatus": "FINISHED",
                "requesterComment": {
                    "commenterId": "2c91808c6d788165016d888db43b3948",
                    "commenterName": "chk_admin",
                    "body": "Needed for land stuff",
                    "date": "2024-03-21T13:24:24.685Z"
                },
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": null,
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": {
                    "requestedObjectId": "7d45b7fe37d14e6bb5e795c045c6d05e",
                    "requestedObjectName": "LA Mineral Acquisition",
                    "requestedObjectType": "ENTITLEMENT"
                },
                "clientMetadata": null,
                "removeDate": null
            },
            {
                "id": "38de2efdd3144995aa78a21140874d4f",
                "name": "38de2efdd3144995aa78a21140874d4f",
                "requested": "2024-03-21T13:24:35.894Z",
                "approvalStatus": "FINISHED",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "CREATE",
                "attribute": null,
                "value": null,
                "nativeIdentity": null,
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            },
            {
                "id": "3a686b815e0e4a1bb087b144b2a5b696",
                "name": "3a686b815e0e4a1bb087b144b2a5b696",
                "requested": "2024-03-21T13:24:35.889Z",
                "approvalStatus": "FINISHED",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "email_address",
                "value": "[email protected]",
                "nativeIdentity": null,
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            },
            {
                "id": "5e67d6816f8d495497fe3bc7229c1372",
                "name": "5e67d6816f8d495497fe3bc7229c1372",
                "requested": "2024-03-21T13:24:35.884Z",
                "approvalStatus": "FINISHED",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "user_name",
                "value": "Alex L",
                "nativeIdentity": null,
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            },
            {
                "id": "ae647e7e76c241a1a4d480ee5a7d9d51",
                "name": "ae647e7e76c241a1a4d480ee5a7d9d51",
                "requested": "2024-03-21T13:24:35.892Z",
                "approvalStatus": "FINISHED",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "status",
                "value": "A",
                "nativeIdentity": null,
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            },
            {
                "id": "ec144d3bd0b54cce98068cc5f5ed658a",
                "name": "ec144d3bd0b54cce98068cc5f5ed658a",
                "requested": "2024-03-21T13:24:35.887Z",
                "approvalStatus": "FINISHED",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "full_name",
                "value": "Alex L",
                "nativeIdentity": null,
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "fe28d1f448a24bc7bca2cbd1808f3620",
        "name": "fe28d1f448a24bc7bca2cbd1808f3620",
        "created": "2024-03-21T13:24:24.685Z",
        "modified": "2024-03-21T13:24:44.392Z"
    }
]

Why is it attempting all these “retries”? This seems odd

Scenario 2 - Access requests to revoke existing access get “thrown away” by the create-access-request API endpoint

I sent the following API request to remove access and no account activity was ever generated. I’m not sure why

{
    "requestedFor": [
        "2c91808670f4c5dd0170f82242d871a5"
    ],
    "requestType": "REVOKE_ACCESS",
    "requestedItems": [
        {
            "id": "7d45b7fe37d14e6bb5e795c045c6d05e",
            "type": "ENTITLEMENT",
            "comment": "No longer needed for land stuff"
        }
    ]
}

Scenario 3 - The tenant continually sends re-provisioning requests for existing access to the connector via “Identity Refresh” activities

Let’s take a user I provisioned yesterday. Here is that account activity

{
    "completed": "2024-03-20T20:56:12.336Z",
    "completionStatus": "SUCCESS",
    "type": "appRequest",
    "requesterIdentitySummary": {
        "id": "2c91808c6d788165016d888db43b3948",
        "name": "chk_admin"
    },
    "targetIdentitySummary": {
        "id": "2c91808670f4c5dd0170f8222dbd7164",
        "name": "Ben R"
    },
    "errors": null,
    "warnings": null,
    "items": [
        {
            "id": "0308af58d95f420692ec983efedaadd5",
            "name": "0308af58d95f420692ec983efedaadd5",
            "requested": "2024-03-20T20:55:51.909Z",
            "approvalStatus": "FINISHED",
            "provisioningStatus": "FINISHED",
            "requesterComment": {
                "commenterId": "2c91808c6d788165016d888db43b3948",
                "commenterName": "chk_admin",
                "body": "Needed for land stuff",
                "date": "2024-03-20T20:55:51.910Z"
            },
            "reviewerIdentitySummary": null,
            "reviewerComment": null,
            "operation": "ADD",
            "attribute": "groups",
            "value": "133",
            "nativeIdentity": null,
            "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
            "accountRequestInfo": {
                "requestedObjectId": "7d45b7fe37d14e6bb5e795c045c6d05e",
                "requestedObjectName": "LA Mineral Acquisition",
                "requestedObjectType": "ENTITLEMENT"
            },
            "clientMetadata": null,
            "removeDate": null
        },
        {
            "id": "08b881c8294745839cc6b857f1c3a419",
            "name": "08b881c8294745839cc6b857f1c3a419",
            "requested": "2024-03-20T20:56:03.208Z",
            "approvalStatus": "FINISHED",
            "provisioningStatus": "FINISHED",
            "requesterComment": null,
            "reviewerIdentitySummary": null,
            "reviewerComment": null,
            "operation": "CREATE",
            "attribute": null,
            "value": null,
            "nativeIdentity": null,
            "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
            "accountRequestInfo": null,
            "clientMetadata": null,
            "removeDate": null
        },
        {
            "id": "494f408de12a47a8ac2976d3149dff21",
            "name": "494f408de12a47a8ac2976d3149dff21",
            "requested": "2024-03-20T20:56:03.198Z",
            "approvalStatus": "FINISHED",
            "provisioningStatus": "FINISHED",
            "requesterComment": null,
            "reviewerIdentitySummary": null,
            "reviewerComment": null,
            "operation": "ADD",
            "attribute": "user_name",
            "value": "Ben R",
            "nativeIdentity": null,
            "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
            "accountRequestInfo": null,
            "clientMetadata": null,
            "removeDate": null
        },
        {
            "id": "c1ca5a56b1884673bf52f84fe4c53ea4",
            "name": "c1ca5a56b1884673bf52f84fe4c53ea4",
            "requested": "2024-03-20T20:56:03.203Z",
            "approvalStatus": "FINISHED",
            "provisioningStatus": "FINISHED",
            "requesterComment": null,
            "reviewerIdentitySummary": null,
            "reviewerComment": null,
            "operation": "ADD",
            "attribute": "email_address",
            "value": "[email protected]",
            "nativeIdentity": null,
            "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
            "accountRequestInfo": null,
            "clientMetadata": null,
            "removeDate": null
        },
        {
            "id": "c4bf270c32d34125aac65931d41c632c",
            "name": "c4bf270c32d34125aac65931d41c632c",
            "requested": "2024-03-20T20:56:03.201Z",
            "approvalStatus": "FINISHED",
            "provisioningStatus": "FINISHED",
            "requesterComment": null,
            "reviewerIdentitySummary": null,
            "reviewerComment": null,
            "operation": "ADD",
            "attribute": "full_name",
            "value": "Ben R",
            "nativeIdentity": null,
            "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
            "accountRequestInfo": null,
            "clientMetadata": null,
            "removeDate": null
        },
        {
            "id": "eb348924ec8c4ceda19a6f4fd0bbfb1a",
            "name": "eb348924ec8c4ceda19a6f4fd0bbfb1a",
            "requested": "2024-03-20T20:56:03.206Z",
            "approvalStatus": "FINISHED",
            "provisioningStatus": "FINISHED",
            "requesterComment": null,
            "reviewerIdentitySummary": null,
            "reviewerComment": null,
            "operation": "ADD",
            "attribute": "status",
            "value": "A",
            "nativeIdentity": null,
            "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
            "accountRequestInfo": null,
            "clientMetadata": null,
            "removeDate": null
        }
    ],
    "executionStatus": "COMPLETED",
    "clientMetadata": null,
    "id": "c3f5ddf8e3694563b72b9ffb5d5a6adc",
    "name": "c3f5ddf8e3694563b72b9ffb5d5a6adc",
    "created": "2024-03-20T20:55:51.910Z",
    "modified": "2024-03-20T20:56:12.337Z"
}

You can see from the account activities here, there have been 9 separate account activities asking to provision the same access. This has happened in less than 24 hours

[
    {
        "completed": "2024-03-21T13:11:04.460Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f8222dbd7164",
            "name": "Ben Russ"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "a545d0eb30cc4668bc723293c5a1ccb4",
                "name": "a545d0eb30cc4668bc723293c5a1ccb4",
                "requested": "2024-03-21T13:11:04.019Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "306",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "12df10c4a8214e8b93e452f59ea0180c",
        "name": "12df10c4a8214e8b93e452f59ea0180c",
        "created": "2024-03-21T13:11:04.022Z",
        "modified": "2024-03-21T13:11:04.485Z"
    },
	{
        "completed": "2024-03-21T13:10:59.076Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f8222dbd7164",
            "name": "Ben Russ"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "39878b315b504c15b15164ba11014e97",
                "name": "39878b315b504c15b15164ba11014e97",
                "requested": "2024-03-21T13:10:58.673Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "306",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "0d055bdaa96243b48a81a9edc8b19aad",
        "name": "0d055bdaa96243b48a81a9edc8b19aad",
        "created": "2024-03-21T13:10:58.674Z",
        "modified": "2024-03-21T13:10:59.104Z"
    },
    {
        "completed": "2024-03-21T13:10:54.794Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f8222dbd7164",
            "name": "Ben Russ"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "055002138f5940cb9c5a884a447d5dfe",
                "name": "055002138f5940cb9c5a884a447d5dfe",
                "requested": "2024-03-21T13:10:54.369Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "306",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "b264d0510e014e678bab9a5aca77902a",
        "name": "b264d0510e014e678bab9a5aca77902a",
        "created": "2024-03-21T13:10:54.371Z",
        "modified": "2024-03-21T13:10:54.819Z"
    },
    {
        "completed": "2024-03-21T01:13:31.305Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f8222dbd7164",
            "name": "Ben Russ"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "f6b3346f7bf741629826218ef533af1a",
                "name": "f6b3346f7bf741629826218ef533af1a",
                "requested": "2024-03-21T01:13:30.928Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "306",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "0e004285e8734e7697b9d3040c3482d6",
        "name": "0e004285e8734e7697b9d3040c3482d6",
        "created": "2024-03-21T01:13:30.929Z",
        "modified": "2024-03-21T01:13:31.330Z"
    },
    {
        "completed": "2024-03-21T01:13:25.478Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f8222dbd7164",
            "name": "Ben Russ"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "d816c24efc8640c690f5625445eab98e",
                "name": "d816c24efc8640c690f5625445eab98e",
                "requested": "2024-03-21T01:13:25.091Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "306",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "c14fcb967e4c448ba2fdfbe390540615",
        "name": "c14fcb967e4c448ba2fdfbe390540615",
        "created": "2024-03-21T01:13:25.094Z",
        "modified": "2024-03-21T01:13:25.499Z"
    },
    {
        "completed": "2024-03-21T01:13:19.466Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f8222dbd7164",
            "name": "Ben Russ"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "31ec2c92e26a494ba43c368a64c0ddbb",
                "name": "31ec2c92e26a494ba43c368a64c0ddbb",
                "requested": "2024-03-21T01:13:18.947Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "306",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "04e453f8ae5f49c6a817a58305b8e6a6",
        "name": "04e453f8ae5f49c6a817a58305b8e6a6",
        "created": "2024-03-21T01:13:18.950Z",
        "modified": "2024-03-21T01:13:19.495Z"
    },
    {
        "completed": "2024-03-20T20:56:20.905Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f8222dbd7164",
            "name": "Ben Russ"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "5cfc7a597c6346d4bd25bea4db02debb",
                "name": "5cfc7a597c6346d4bd25bea4db02debb",
                "requested": "2024-03-20T20:56:20.575Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "306",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "9b4a24a5465f429bac32f5617d048d09",
        "name": "9b4a24a5465f429bac32f5617d048d09",
        "created": "2024-03-20T20:56:20.577Z",
        "modified": "2024-03-20T20:56:20.920Z"
    },
    {
        "completed": "2024-03-20T20:56:15.713Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f8222dbd7164",
            "name": "Ben Russ"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "a74bc72462d94e9bb2153cec3b7c8b57",
                "name": "a74bc72462d94e9bb2153cec3b7c8b57",
                "requested": "2024-03-20T20:56:15.375Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "306",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "838c0dc2f2af49b0bcb319ccc97535e6",
        "name": "838c0dc2f2af49b0bcb319ccc97535e6",
        "created": "2024-03-20T20:56:15.378Z",
        "modified": "2024-03-20T20:56:15.728Z"
    },
    {
        "completed": "2024-03-20T20:56:10.299Z",
        "completionStatus": "SUCCESS",
        "type": "Identity Refresh",
        "requesterIdentitySummary": {
            "id": "2c91808471514f25017156064bb25b44",
            "name": "SYSTEM"
        },
        "targetIdentitySummary": {
            "id": "2c91808670f4c5dd0170f8222dbd7164",
            "name": "Ben Russ"
        },
        "errors": null,
        "warnings": null,
        "items": [
            {
                "id": "0ec8d5a134e7478b9ae5c9d04b192427",
                "name": "0ec8d5a134e7478b9ae5c9d04b192427",
                "requested": "2024-03-20T20:56:09.983Z",
                "approvalStatus": "PENDING",
                "provisioningStatus": "FINISHED",
                "requesterComment": null,
                "reviewerIdentitySummary": null,
                "reviewerComment": null,
                "operation": "ADD",
                "attribute": "groups",
                "value": "133",
                "nativeIdentity": "306",
                "sourceId": "b495eee9c8fa4dcda52c714e3f9abd3e",
                "accountRequestInfo": null,
                "clientMetadata": null,
                "removeDate": null
            }
        ],
        "executionStatus": "COMPLETED",
        "clientMetadata": null,
        "id": "b6d9bdf6e3b84e9c9dc6253743b1871d",
        "name": "b6d9bdf6e3b84e9c9dc6253743b1871d",
        "created": "2024-03-20T20:56:09.986Z",
        "modified": "2024-03-20T20:56:10.303Z"
    }
]

Here is the relevant code

export const connector = async () => {
  const readAccount = async (id: string): Promise < Account > => {
    const account_response: AxiosResponse = await httpClient.getAccount(id)

    const account: Account = new Account(account_response.data.data[0])

    const groups_response: AxiosResponse = await httpClient.getUserGroups(id)
    const groups = groups_response.data.data.map((x: {
      group_id: any
    }) => x.group_id)
    account.attributes.groups = groups

    return account
  }

  const assignUserGroup = async (account: Account, group: string) => {
    //double-check access isn't already assigned to avoid a unique constraint error
    const access_response = await httpClient.getUserGroupRel(account.identity, group)
    if (access_response.data.header.data_rows == 0) {
      await httpClient.assignUserGroup(account.identity, group)
    } else {
      logger.info(`Not sending a provisioning request for ${account.attributes.full_name} into group id ${group} since user already has access assigned`)
    }
  }
  return createConnector()
    .stdAccountCreate(
      async (context: Context, input: StdAccountCreateInput, res: Response < StdAccountCreateOutput > ) => {
        logger.info('std:account:create')
        logger.info(input)

        const user = {
          ...input.attributes,
          ...{
            groups: undefined
          }
        }
        const account_response = await httpClient.createAccount(user)

        const account = await readAccount(account_response.data.user_id)

        logger.info(`New Account Created for ${account.attributes.full_name}`)
        res.send(account)
      }
    )
    .stdAccountUpdate(async (context: Context, input: StdAccountUpdateInput, res: Response < StdAccountUpdateOutput > ) => {
      logger.info('std:account:update')
      logger.info(input)

      for (let change of input.changes) {
        const values = [].concat(change.value)
        for (let value of values) {
          const account = await readAccount(input.identity)
          switch (change.op) {
            case AttributeChangeOp.Add:
              await assignUserGroup(account, value)
              break
            case AttributeChangeOp.Remove:
              await removeUserGroup(account, value)
              break
            default:
              throw new ConnectorError(`Operation not supported: ${change.op}`)
          }
        }
      }
      const account = await readAccount(input.identity)
      res.send(account)
    })
}

@developer_advocates IDK which one of you wrote this comment in the discourse saas connector, but I remembered reading it when looking through the code and it dawned on me that the API I’m interacting with returns group ids as an integer and I wasn’t converting it into a string. After I did that, the issues I described above have gone away. :grin:

tl;dr
make sure the account/entitlement ids that you send back to IdN are strings and not numbers or it makes it very unhappy

2 Likes