User Provisioning Guide

Conceptual guide covering how user provisioning works in the Calimatic Auth platform, the three provisioning methods, organization membership, auto-licensing, and password handling.


Prerequisites

  • Familiarity with the Calimatic Auth platform concepts (organizations, roles, app clients)
  • For API-based provisioning: a registered app client or API key with org:users:manage permission
  • For organization provisioning: org:manage permission on the app client or API key

Overview

User provisioning is the process of creating user accounts, assigning them to organizations, granting app licenses, and setting up their credentials. The Calimatic Auth platform provides three methods for provisioning users, each suited to different use cases.

                    +-----------------+
                    | User Provisioned |
                    +-----------------+
                           |
           +---------------+---------------+
           |               |               |
      Admin UI         API Call         SCIM Sync
      (manual)       (programmatic)   (automated)
           |               |               |
           v               v               v
    +------------------------------------------+
    |         Keycloak (Identity Store)         |
    +------------------------------------------+
           |               |               |
           v               v               v
    +------------------------------------------+
    |      Platform DB (Org, Roles, Licenses)   |
    +------------------------------------------+

The Three Provisioning Methods

1. Admin UI

Manual provisioning through the Calimatic Auth admin dashboard.

Best for: One-off user creation, small teams, initial setup.

How it works:

  1. Admin navigates to Admin > Users > Create User or Invite User
  2. Fills in email, name, role, and selects apps to assign
  3. User is created in Keycloak and the platform database simultaneously
  4. An invitation email is sent with a link to set their password

Capabilities:

  • Create individual users
  • Invite users to organizations
  • Assign roles and app licenses
  • Set temporary passwords
  • Suspend, deactivate, or reactivate users

2. API (Provisioning API)

Programmatic provisioning via HTTP API calls.

Best for: Application-initiated user creation, bulk imports, migration, automation scripts.

Key endpoints:

EndpointUse Case
POST /api/v1/organizationsCreate an organization (apps must create orgs first)
GET /api/v1/organizations?slug=<slug>Look up an organization by slug
POST /api/v1/users/provisionCreate or provision a single user
POST /api/v1/users/provision/bulkBulk provision up to 500 users
POST /api/v1/users/importImport existing users (migration-friendly defaults)

Authentication methods:

  • App client credentials (x-client-id + x-client-secret) -- for app-initiated provisioning
  • API key (x-api-key) -- for server-to-server automation
  • Session -- for internal tools using the admin's session

For detailed API documentation, see the User Management API Reference.

3. SCIM (System for Cross-domain Identity Management)

Automated provisioning via the SCIM 2.0 protocol, driven by an external identity provider.

Best for: Enterprise customers using Azure AD, Okta, OneLogin, or other identity providers that support SCIM.

How it works:

  1. The enterprise customer configures their IdP to point to the Calimatic SCIM endpoint
  2. When users are assigned to the Calimatic app in the IdP, they are automatically created
  3. When users are unassigned or removed, they are automatically deactivated
  4. Profile changes in the IdP are synced to Calimatic Auth

For SCIM endpoint documentation, see the SCIM API Reference.


How Provisioning Works Internally

Regardless of the method used, every user provisioning operation follows the same internal flow:

Step 0: Organization Creation (Required First)

Organizations must exist on the auth platform before users can be provisioned into them. Organizations originate at the app level -- when a customer subscribes to an app, the app creates the org on the auth platform.

API endpoint: POST /api/v1/organizations

{
  "name": "Acme Corp",
  "slug": "acme-corp",
  "type": "customer"
}

When called by an app client, the calling app is automatically enabled for the new organization. The endpoint is idempotent -- if the slug already exists, it returns the existing org with a 409 status.

This step is a prerequisite for all user provisioning. The provisioning API will return a 404 ORG_NOT_FOUND error if you try to provision a user into a non-existent organization.

Step 1: Keycloak User Creation

The user is created in Keycloak (the identity store). Keycloak handles:

  • Credential storage (passwords, social login links)
  • Email verification
  • Required actions (UPDATE_PASSWORD, VERIFY_EMAIL)
  • Authentication flows

If the user already exists in Keycloak (matched by email), the existing Keycloak account is reused.

Step 2: Platform Identity Creation

A user_identities record is created in the platform database. This record stores:

  • Platform-specific profile data (display name, avatar, phone, timezone, locale)
  • Organization memberships
  • User type (customer_admin, customer_teacher, etc.)
  • Status (active, suspended, deactivated)
  • Source tracking (how the user was created)
  • External IDs for cross-referencing with other systems

Step 3: Organization Membership

If an organization is specified, the user is added as a member:

  • A membership entry is added to organizationMemberships (JSONB array on the identity)
  • The specified role (or member by default) is assigned
  • If the user has no primary organization, the specified org becomes their primary

Step 4: App License Assignment

App licenses are assigned based on the request:

  • If the caller is an app client, the calling app's license is auto-included
  • If specific apps are requested, only enabled apps on the org are assigned
  • If no apps are specified and no app client context exists, all enabled org apps are assigned
  • Licenses are recorded in the user_app_licenses table

Step 5: Email / Notification

Depending on configuration:

  • Invite email (sendInviteEmail: true): A password setup email is sent with a 72-hour expiry link
  • Temporary password (temporaryPassword): The password is set in Keycloak with the UPDATE_PASSWORD required action
  • No action: User account is created but no notification is sent (common for migration)

Step 6: Audit and Webhooks

  • An audit log entry is created (USER_CREATED event type)
  • A user.created webhook event is dispatched to all subscribed webhooks

Auto-Licensing Behavior

The platform follows a three-layer licensing model inspired by Okta:

Layer 1: App Registration
  The app is registered as an OAuth client with the platform.
  (admin creates via POST /api/v1/admin/app-clients, or dynamic registration)

Layer 2: Org Enablement
  The app is enabled for a specific organization.
  (organization_app_access record with isEnabled: true)

Layer 3: User Assignment
  Individual users are granted a license for the app.
  (user_app_licenses record)

Auto-Assignment Rules

ScenarioBehavior
App client provisions a userCalling app's license is automatically assigned
Explicit applications array providedOnly those apps (if enabled on org) are assigned
No apps specified, no app client contextAll enabled org apps are assigned
App not enabled on orgSilently filtered out (no error)

Example

A Partners Portal app client (application: "partners") invites a user to an organization that has three enabled apps: edtech, partners, and scheduler.

  • The user automatically gets a partners license (calling app)
  • If the request includes applications: ["edtech"], the user also gets edtech
  • If no applications array is provided, the user gets partners only (from the app client context)

Organization Membership Model

Users can belong to multiple organizations simultaneously. This supports:

  • Consultants managing multiple schools
  • Internal employees with cross-org access
  • Users transitioning between organizations

Membership Structure

Each membership is stored as a JSONB entry:

{
  "organization_id": "uuid-of-org",
  "role": "admin",
  "permissions": [],
  "joined_at": "2025-01-15T10:00:00.000Z"
}

Primary Organization

Each user has a primaryOrganizationId that determines:

  • Default organization context in OIDC claims
  • Which organization's branding they see on login
  • The default org used when no explicit org is provided in API calls

The first organization a user is added to becomes their primary. This can be changed later.

Adding to Additional Organizations

When a user is provisioned for an organization they already exist in, the provisioning system:

  1. Checks if the user is already a member of the target org
  2. If not, adds a new membership entry
  3. Assigns app licenses for the new org
  4. Does not change the user's primary org (unless they had none)

Password Handling

The platform supports multiple password strategies depending on the use case:

Invite Email (Default)

When sendInviteEmail: true (the default for single provisioning):

  1. The user is created in Keycloak with VERIFY_EMAIL and UPDATE_PASSWORD required actions
  2. A platform-managed invite email is sent with a secure link
  3. The link directs the user to a password setup page
  4. The link expires after 72 hours
  5. After setting their password, the user can log in normally

Temporary Password

When temporaryPassword is provided:

  1. The password is set in Keycloak as a temporary credential
  2. Keycloak adds the UPDATE_PASSWORD required action
  3. On first login, the user is prompted to choose a new password
  4. No invite email is sent (unless sendInviteEmail is also true)

Password Hash Migration (Seamless)

When passwordHash is provided:

  1. The bcrypt or PBKDF2 hash is stored directly in the platform database
  2. No invite email is sent -- the user is ready to log in immediately
  3. No password reset is required
  4. For PBKDF2 hashes, automatic upgrade to bcrypt happens on first successful login
  5. This is the recommended approach for migrating existing users from apps that use compatible password hashing
{
  "email": "jane@example.com",
  "firstName": "Jane",
  "lastName": "Smith",
  "passwordHash": "$2b$12$...",
  "sendInviteEmail": false
}

Supported formats:

  • bcrypt ($2b$, $2a$) -- stored as-is, verified directly
  • PBKDF2 (Keycloak JSON format) -- transparently upgraded to bcrypt on login

SSO (No Password)

When the organization has SSO configured (Google Workspace, Microsoft 365, SAML, OIDC):

  1. Users do not need a password at all
  2. They authenticate via their organization's identity provider
  3. The platform detects the SSO configuration and redirects accordingly
  4. This is the preferred approach for enterprise customers

Password Reset

For users who need to reset their password after initial setup:

  • POST /api/v1/users/{id}/reset-password sends a Keycloak-managed password reset email
  • POST /api/v1/users/{id}/set-password sets a new temporary password directly

Password Requirements

The platform enforces Keycloak's password policy for the calimatic-customers realm:

  • Minimum 8 characters
  • At least 1 digit

For the calimatic-internal realm (internal employees):

  • Minimum 12 characters
  • At least 1 uppercase, 1 lowercase, 1 digit, 1 special character
  • Cannot be the same as the last 5 passwords
  • Cannot contain the username

Provisioning Across the Four App Categories

Category 1: New Calimatic Apps

  • Create your organization via POST /api/v1/organizations first
  • Use the Provisioning API to create users
  • App client auto-licensing handles license assignment
  • Send invite emails for new users
  • See New Calimatic App Guide

Category 2: Existing Calimatic Apps

  • Use the Import API for bulk migration
  • Set sendInviteEmails: false and skipExisting: true
  • Migrate password hashes directly via passwordHash for seamless login, or use reset emails as a fallback
  • See Migrating Calimatic App Guide

Category 3: New Third-Party Apps

  • Use the Provisioning API for creating users in Calimatic orgs
  • Set up webhooks to receive user lifecycle events
  • Consider SCIM for enterprise customer provisioning
  • See Integrate Third-Party Guide

Category 4: Existing Third-Party Apps

  • Use the Import API to bring existing users into Calimatic Auth
  • Create organizations on the auth platform via POST /api/v1/organizations
  • Preserve external IDs for cross-referencing (externalId field)
  • Set up webhooks for ongoing sync
  • See Migrate Existing Users Guide

Deduplication

The provisioning system deduplicates by email address:

  • Email addresses are normalized (lowercased, trimmed) before comparison
  • If a user with the same email exists in the platform database, the existing user is returned/updated
  • If a user with the same email exists in Keycloak but not in the platform database, the Keycloak account is linked

This ensures that users who exist across multiple organizations or apps always have a single identity.


Webhook Events

All provisioning operations dispatch webhook events:

OperationEvent
User createduser.created
User updated (added to org)user.updated
Bulk import completeduser.created (per user)
Password reset triggereduser.password_reset
Temporary password setuser.password_reset

See the Webhooks API Reference for details on subscribing to events.


Related Documentation