Skip to content
InsightsKlef Team

SCIM vs. HRIS-Driven Provisioning

Photo by Matthew Henry on Unsplash

In the process of automating JML (Joiner-Mover-Leaver), you might come across SCIM. It's often misunderstood as an alternative to solutions like Klef. It is not.

SCIM is a protocol (RFC 7643 and RFC 7644) for creating, updating, and deactivating users and groups from one system to another. Its purpose is to keep a system's users in sync with another system, most commonly an IdP like Entra ID.

But it has no concept of the worker's record. It doesn't know when a worker's assignment starts and ends, when that worker changes departments, or what licenses that worker needs. It doesn't keep track of changes made to that worker, nor can it handle notifications relating to worker changes.

In short, SCIM is one protocol Klef uses for JML automation.

SCIM/IdP-Based Solutions

With SCIM, the IdP decides who gets an account and SCIM relays that downstream.

  • It doesn't start from the employment record: The IdP relays whatever comes through it. Someone or something still has to put the right people into the right groups when HR hires, promotes, or terminates someone. Often that's handled by IT through a ticket.

  • It has no concept of lifecycle: A SCIM user is active or inactive. There is no way to say "exists but switched off until the start date", "disabled during parental leave", or "leaves on Friday, so notify their manager now".

  • The schema isn't tailored to the downstream system: Any system-specific fields aren't in the SCIM schema (e.g. Slack channels, license SKUs, Oracle Fusion work relationships, default expenses accounts). SCIM is very limited in what it can change downstream.

HRIS-Driven Solutions

HRIS-driven JML automation begins at the HR system (ADP, Gusto, etc.). A worker's employment record decides what their accounts should look like in every downstream system. That could include the IdP itself.

Klef falls in this category. Klef makes those decisions from the HR record, then writes the result with whatever each system offers.

For example, Slack members in Klef are provisioned through SCIM, but their channels are managed through Slack's API. Oracle Fusion roles go through SCIM to Oracle, but work relationships are managed through Oracle's HCM API. And Entra is written through Microsoft Graph.

A policy describes each system using a combination of that system's SCIM and API-defined fields:

policy "Finance access" {
  category = "Finance"
  applies  = segment.finance

  stage active {
    target microsoft_entra.user {
      userPrincipalName = worker.business_email
      mailNickname      = worker.employee_id
      displayName       = worker.display_name
      jobTitle          = worker.job.name
      accountEnabled    = true
      licenses          = ["SPE_E5"]
      groups            = ["All Employees", "Finance"]
    }

    target oracle_fusion.worker {
      personNumber    = worker.employee_id
      firstName       = worker.legal_name.given
      lastName        = worker.legal_name.family
      legislationCode = "US"

      workRelationships = [
        {
          legalEmployerName = "Acme Logistics LLC"
          hireDate          = worker.hire_date

          assignments = each worker.assignments
                as assignment where assignment.status == "Active" {
            assignmentNumber = assignment.source_id
            assignmentName   = assignment.job.name
            businessUnitName = assignment.business_unit.name
            primaryFlag      = assignment.is_primary
          }
        },
      ]
    }

    target slack.user {
      userName = worker.business_email
      active   = true
      channels = ["general", "finance"]
    }
  }

  stage leave {
    target microsoft_entra.user {
      userPrincipalName = worker.business_email
      mailNickname      = worker.employee_id
      displayName       = worker.display_name
      accountEnabled    = false
      groups            = unmanaged
    }
  }

  stage departing {
    notify email {
      subject = "{{ worker.display_name }} leaves on {{ worker.end_date }}"
      body    = "Please plan the handover before their last day."
      to      = [manager(1)]
    }
  }
}

Several things in that policy fall outside what SCIM can do on its own:

  • Licenses: An E5 license is assigned.
  • Oracle Assignments: For each active assignment in the HRIS, an active assignment is added to Oracle.
  • Slack Channels: Slack channels are set.
  • Leave Management: Login is deactivated while on leave.
  • Notifications: The manager is emailed on a worker's last day.

Every run also produces a plan. You can see what will change in each system before anything is wrote to that system.