RFDs/0016

SCIM provisioning

State
published
Authors
Darwin D Wu
Discussion
renga-dcim/renga#168
Labels
rengaaccountsauthenticationsecuritysoftware
Implemented
0%Checklist

Goal

Let an organization’s identity provider keep its Renga roster current: add people, change their roles, and remove them the moment the provider does. RFD 15 only learns about a person when they sign in, so an offboarded person keeps access until their provider session lifetime runs out, and an administrator cannot see who the provider has assigned to Renga before each of them signs in.

Renga accepts provisioning requests from the identity provider: it exposes a SCIM 2.0 API (RFC 7643 and RFC 7644), and the identity provider calls it whenever someone is assigned, changed, or removed. Renga never polls the identity provider. In SCIM’s own terms Renga is the service provider and the identity provider is the client. Everywhere else in this RFD, "provider" means the identity provider, as in RFD 15.

Connections

An organization owner creates a SCIM connection for their organization. The first release has no entitlement dependency: every active organization may use SCIM unless the operator disables it deployment-wide. A connection has:

  • the organization it manages; a connection never reaches another organization;

  • the ID of an RFD 15 oidc provider visible to the organization whose identities it describes. RFD 15 currently defines deployment providers; an organization provider is also eligible if RFD 15 is amended to define one, and only for the same organization. GitHub identities cannot be provisioned because GitHub has no SCIM client;

  • the correlation claim, the ID token claim whose value the provider sends as each user’s SCIM externalId (sub by default; oid for Microsoft Entra ID, whose sub is pairwise per application);

  • an optional default role for every active provisioned user, and a mapping from SCIM groups to Renga roles;

  • up to two bearer tokens, so a token can be rotated without downtime.

The provider’s trusted configuration declares which correlation claims are eligible. Renga always permits sub; it permits another claim only when that configuration identifies it as a stable, unique, non-reassignable identifier within the provider’s issuer namespace. Correlation accepts only a nonempty string and compares it exactly, without case folding or type coercion. A missing, malformed, or ambiguous value never links an entry or grants SCIM access, though the sign-in may continue under RFD 15.

The provider and correlation claim cannot be retargeted in place. Changing either requires a replacement connection, with the old connection disabled and its grants reconciled before the replacement becomes active. If RFD 15 later adds organization providers, its provider-visibility checks remain an authorization boundary: a connection context rechecks that the provider belongs to its organization, and provider removal disables the connection.

Tokens follow RFD 3 intake keys: Renga generates them, shows each once, and stores only a hash. The organization owner can revoke a token at any time. SCIM requests authenticate only with these tokens; a browser session never reaches the SCIM endpoints, and a SCIM token never reaches anything else. Token values are redacted from request logs, diagnostics, and audit payloads.

An organization has at most one external membership authority: either one RFD 15 claim mapping or one SCIM connection. Two sources writing the same roster would fight, and the first release does not define a merge.

Endpoints

The SCIM base URL is /scim/v2; the bearer token selects the connection and so the organization, so one URL serves every organization. Renga implements:

  • ServiceProviderConfig, ResourceTypes, and Schemas;

  • Users: create, read, replace, patch, delete, and list;

  • Groups: create, read, replace, patch (including member add and remove), delete, and list.

Listing supports startIndex and count pagination with a maximum page size, and filters of the form attribute eq "value" on userName, externalId, displayName, and id, which is what the major identity providers send. Bulk operations, sorting, ETags, and password changes are not supported. ServiceProviderConfig reports only capabilities that resource defines, such as PATCH, filtering, bulk, and authentication schemes. /Me is documented separately and returns a SCIM 501 error.

Requests are bounded in size and rate limited per connection. Errors use the SCIM error schema. A duplicate userName or externalId within one connection is a 409 with scimType uniqueness. Per-connection externalId uniqueness is a deliberate Renga restriction, not a guarantee made by the SCIM schema.

Providers differ in small ways, such as PATCH operation names in different cases, booleans sent as strings, and value-filtered paths like members[value eq "…​"]. Renga accepts these forms for the attributes it supports. The strings "true", "false", "True", and "False" are normalized to booleans before applying the write rules below; no other string is. Compatibility with Okta and Microsoft Entra ID is tested against recorded request fixtures.

Directory entries

A provisioned SCIM user is a directory entry belonging to its connection, not a Renga account. A new scim_users table holds the connection, a Renga-assigned SCIM id, the externalId, userName, display name, primary email, active, supported attributes and extensions declared by Renga’s Schemas resources, and an optional link to the specific RFD 15 user_identity that proved the correlation. The account is reached through that identity; an entry never stores an account-only binding. scim_groups and their memberships hold groups the same way. Undeclared extension data is not retained.

The SCIM password attribute is never persisted, logged, audited, or returned. Renga accepts and discards a password sent incidentally on user creation so Okta provisioning remains compatible. A PUT or PATCH that attempts to change a password returns a SCIM 400 error with scimType invalidValue.

The authorization-relevant write semantics are explicit rather than delegated to provider-specific PUT behavior:

Attribute POST PUT PATCH

User externalId

An omitted, null, or empty value creates an unlinked entry. A nonempty string must be unique in the connection.

An omitted, null, or empty value clears it. Changing or clearing it also clears the identity binding before grants are reconciled.

Adding or replacing it follows PUT’s binding rule; removing it clears the binding.

User active

Omission defaults to true; null or any value other than a boolean or its accepted string form is invalidValue.

Omission preserves the current value. An explicit accepted boolean value replaces it; null or any other value is invalidValue.

Only an explicit accepted boolean value may replace it.

Group members

Omission creates an empty group.

Omission replaces the membership set with empty. Supplied members replace it whole after every referenced user is validated in the same connection.

Add and remove change only the named members. User groups is read-only.

Renga does not create accounts from SCIM. An organization’s provider is authoritative for that organization, not for the account a person may also use in other organizations, so a SCIM request never sets or changes a Renga user’s email, name, credentials, or other memberships. Not creating accounts also means a connection cannot reserve an email address for an account its owner never signs in to.

A directory entry links to the RFD 15 identity when that identity signs in or reauthenticates through the connection’s provider and the validated ID token’s correlation claim exactly equals the entry’s nonempty externalId. Renga refuses to reassign an entry already bound to another identity. If the person has no Renga account yet, the active directory entry permits RFD 15 provider sign-up for them even when the provider otherwise disallows sign-up. RFD 15's rules still hold: Renga never links by email, and an email collision with an existing account is refused until the person signs in to that account and links the provider from their settings, which then links the entry too.

Changing or clearing externalId, unlinking the RFD 15 identity, or removing its provider clears the entry’s binding and reconciles its grant immediately. A later sign-in with valid correlation evidence may establish a new binding; neither the old account link nor a successful sign-in through another identity can carry the SCIM authority forward.

Organization owners and admins can see directory entries in the organization’s member list, including entries not yet linked to an account, so they can tell who the provider has assigned and who has not signed in yet.

Memberships

A linked, active directory entry produces a membership grant for its organization. The role is the highest of the connection’s default role and the roles mapped from the entry’s SCIM groups; with neither, the entry grants nothing. Groups name organizations implicitly, because the connection belongs to exactly one organization, so the mapping only names roles (owner, admin, member, viewer).

Mappings identify a group by its Renga-assigned, connection-scoped SCIM id, not by mutable displayName or provider-supplied externalId. Renaming a group therefore preserves its mapping. Deleting and recreating one produces a new id and never inherits the deleted group’s authority.

Like RFD 15 claim-mapped grants, SCIM grants record the connection that issued them and are valid only while that source is: the connection and provider are enabled, the entry is active and linked to an existing identity, and the connection’s current default role and group mappings produce the recorded role. A membership granted by hand takes precedence over a SCIM grant for the same user and organization and is never changed or revoked by SCIM.

Renga reconciles a linked entry after every relevant mutation: user creation, replacement, patch, activation, deactivation, or deletion; identity binding or unlinking; group membership or mapping changes; group deletion; default-role changes; and connection or provider disablement or deletion. It recomputes the highest resulting SCIM role and creates, upgrades, downgrades, or removes the source-bound grant before acknowledging the change. It then applies manual membership precedence to determine the effective role.

Because the provider pushes every change, SCIM grants do not expire on a timer. RFD 15's provider session lifetime still applies to the sessions themselves.

Authorization changes

Every grant reduction takes effect before the triggering SCIM or administrative request completes. This includes a complete removal and a downgrade caused by leaving one group while a default role or another mapped group remains.

Authorization always evaluates the reconciled effective role, regardless of whether the browser session was created with this provider, another provider, a password, or a magic link. HTTP requests recheck it normally. Renga also pushes the change to connected LiveViews and Channels scoped to the organization so they stop unauthorized data delivery and mutations immediately. A LiveView returns to organization selection only when the user loses effective membership; an independent manual membership keeps its role and unrelated organizations remain available.

Long-lived privileged operations are reauthorized too. In particular, an RFD 13 terminal whose organization membership or terminal grant is no longer sufficient is ended and its PTY process group is killed; the same rule applies to any later Channel or leased operation whose authorization no longer holds.

Renga does not expire the linked identity’s provider session in response to an organization-scoped SCIM change. One identity and browser session may serve other organizations, and disabling access in one must not suspend the others. Conversely, successful OIDC reauthentication cannot recreate a deleted entry, activate an inactive entry, restore a removed role, or reuse a stale binding. It may establish a fresh binding to an otherwise eligible entry only with valid correlation evidence, after which normal reconciliation determines its grant.

Removing SCIM authority never deletes the Renga account, which may still belong to other organizations or hold its own credentials. Deleting a directory entry removes the entry and its group memberships; its activity history stays attributed to the user.

Audit

Every SCIM change records the connection, the token used, the request ID, the directory entry or group, and the resulting grant change. Token creation, rotation, and revocation and mapping changes record the owner who made them. These records are kept with the organization so an owner can review why a person gained or lost access.

Future work

  • Push-based account updates that are safe across organizations, if Renga later supports organizations that own their members' accounts outright.

  • SCIM-managed organization creation, once an operator-level SCIM client is needed.