Microapps

Configure User providers

Configure user providers increases administration efficiency by removing the need to replicate and synchronize user groups created and maintained in your System of Record’s (SoR) identity providers configuration settings.

Microapps admins can configure user providers to collect user and user group data from your SoR and use this data to manage microapp subscriptions in all integrations. To configure user providers, your application SoR must provide APIs that expose users/user groups, for example ServiceNow, Salesforce, Jira, and so on.

Create user provider

You can either create a new user provider manually or import a user provider that is already configured.

Follow these steps:

  1. From the Microapp Integrations page, select the User Providers tab in the top bar.

    User providers tab

  2. Choose a user provider type. Select Create a new user provider from your HTTP web service to configure this user provider manually. You can also Import a previously configured user provider. For more information on importing, see Import.
  3. Enter a User provider name for the connection.
  4. Enter the user provider Base URL.
  5. Select an Icon for the user provider from the Icon Library, or leave this as the default icon.
  6. Select the Service authentication method, and complete all required details based on the authentication method that you use. For more information on authentication methods, see Set up Service Authentication.
  7. (Optional) Enable the Enable request rate limiting toggle if needed and enter a Number of requests and a Time interval.
  8. (Optional) Enter a value for Request timeout if needed.
  9. Select Add to finish creating the user provider.

    User providers config screen

    Now you import a script to finish.

Import script

Using the User provider script capability in Microapps, you need to upload a script to finish the user provider setup. We’ve provided script requirements and a JavaScript model below. See Prepare your script. For general information about scripting, see HTTP integration scripting.

After you added the user provider (in the previous procedure), the page opens with a view of your user providers. Follow these steps to add the script.

  1. Select Add script under Status.
  2. Select Import script.
  3. Drag your script onto the import pop-up, or browse for the file. The script must be a .js file no larger than 1 MB.

    The script is parsed and validated.

  4. Select Import to finish.

    You can see scripting details under Script handlers in the User provider script view of the user provider. To see requests made by the script, select the menu next to the user provider entry and select Sync log.

Your new user provider is now available when assigning subscribers. For more information, see Manage subscribers.

User provider in subscriptions

Prepare your script

When preparing your script, consider the following requirements:

  • The import script must start by loading the built-in library microapp-user-groups. This library defines the objects that must be stored in the database: const { User, Group, UserGroupMapping } = library.load("microapp-user-groups");
  • Objects have the following structure/properties:

    • User(accountName, displayName, email, domain, userPrincipalName, userId) Email addresses must be unique within user provider
    • Group(accountName, displayName, domain, userPrincipalName, groupId, parentGroupId) Group hierarchy is also defined using parentGroupId
    • UserGroupMapping(userId, groupId) Maps users to groups
  • All properties are of data type STRING.
  • User.email has to match the email of a user logged in to Citrix Workspace.

Model script

Use the following JavaScript code as a model.

Note

The following model is written specifically for the ServiceNow SoR. This script is not compatible with other services.

    const { User, Group, UserGroupMapping } = library.load("microapp-user-groups");

    function fullSync(params) {
      fullSyncUsers(params);
      fullSyncGroups(params);
      fullSyncUserGroupMapping(params);
    }

    function fullSyncUsers({ client, dataStore }) {
      let offset = 0;
      do {
        const response = client.fetchSync(
          `/api/now/table/sys_user?sysparm_fields=sys_domain_path%2Cname%2C%20sys_id%2Cuser_name%2Cemail&sysparm_query=emailISNOTEMPTY^active%3Dtrue&sysparm_limit=100&sysparm_offset=${offset}`
        );
        if (!response.ok) {
          console.log("Error status:", response.status, response.statusText);
          console.log("Error body:", response.textSync());
          throw new Error("Network response was not ok");
        }
        console.log("fetch done");

        const users = response.jsonSync().result;
        console.log("users");

        users.map((user) =>
          console.log(
            user.user_name,
            user.name,
            user.email,
            user.sys_domain_path,
            user.name,
            user.sys_id
          )
        );
        dataStore.save(
          User.tableModel,
          users.map(
            (user) =>
              new User(
                user.user_name,
                user.name,
                user.email,
                user.sys_domain_path,
                user.user_name,
                user.sys_id
              )
          )
        );

        offset = offset + 100;
        console.log(`offset: ${offset}`);
      } while (offset < 300);
    }

    function fullSyncGroups({ client, dataStore }) {
      let offset = 0;
      do {
        const response = client.fetchSync(
          `/api/now/table/sys_user_group?sysparm_query=active%3Dtrue&sysparm_limit=100&sysparm_offset=${offset}`
        );
        if (!response.ok) {
          console.log("Error status:", response.status, response.statusText);
          console.log("Error body:", response.textSync());
          throw new Error("Network response was not ok");
        }

        const groups = response.jsonSync().result;
        groups.map((group) =>
          console.log(
            group.name,
            group.name,
            "/",
            group.name,
            group.sys_id,
            group.parent.value
          )
        );
        dataStore.save(
          Group.tableModel,
          groups.map(
            (group) =>
              new Group(
                group.name,
                group.name,
                "/",
                group.name,
                group.sys_id,
                group.parent.value
              )
          )
        );
        offset = offset + 100;
        console.log(`offset: ${offset}`);
      } while (offset < 400);
    }

    function fullSyncUserGroupMapping({ client, dataStore }) {
      let offset = 0;
      do {
        const response = client.fetchSync(
          `/api/now/table/sys_user_grmember?&sysparm_limit=100&sysparm_offset=${offset}`
        );
        if (!response.ok) {
          console.log("Error status:", response.status, response.statusText);
          console.log("Error body:", response.textSync());
          throw new Error("Network response was not ok");
        }

        const mappings = response.jsonSync().result;
        mappings.map((mapping) =>
          console.log(mapping.user.value, mapping.group.value)
        );
        dataStore.save(
          UserGroupMapping.tableModel,
          mappings.map(
            (mapping) =>
              new UserGroupMapping(mapping.user.value, mapping.group.value)
          )
        );
        offset = offset + 100;
        console.log(`offset: ${offset}`);
      } while (offset < 400);
    }

    integration.define({
      synchronizations: [
        {
          name: "snowUserGroups", // Logical name
          fullSyncFunction: fullSync,
        },
      ],
      model: {
        tables: [User.tableModel, Group.tableModel, UserGroupMapping.tableModel],
      },
    });
<!--NeedCopy-->
Configure User providers