Back to SSO docs

SCIM 2.0 reference

RFC 7644

Mnueron implements the SCIM 2.0 User resource. Use it from any RFC 7644-compliant client — Okta, Microsoft Entra ID, OneLogin, JumpCloud, or your own provisioning script. Groups are on the roadmap (most IdPs survive without them).

Authentication

Bearer token in the Authorization header:

Authorization: Bearer scim_<token>

Mint tokens at /dashboard/settings/sso (Mnueron admin only). Each token is scoped to a single org and is shown raw exactly once at creation — store it in your IdP's secret vault immediately. Tokens are SHA-256 hashed at rest.

Discovery endpoint

SCIM clients hit ServiceProviderConfig first to learn capabilities. No auth required (per RFC).

curl https://www.mnueron.com/scim/v2/ServiceProviderConfig

Returns supported features: PATCH yes, bulk no, filter yes (maxResults 200), sort no, etag no. Bearer auth scheme.

Users endpoints

MethodPathPurpose
GET/scim/v2/UsersList or search
POST/scim/v2/UsersCreate user
GET/scim/v2/Users/{id}Read
PUT/scim/v2/Users/{id}Full replace
PATCH/scim/v2/Users/{id}Partial update (RFC 7644)
DELETE/scim/v2/Users/{id}Deactivate (soft delete)

Filtering

We support the canonical lookup-by-email pattern that every IdP uses:

GET /scim/v2/Users?filter=userName eq "user@example.com"

More complex filter expressions return a SCIM error. Pagination via count (max 200) and startIndex (1-based).

Curl recipes

Create a user

curl -X POST https://www.mnueron.com/scim/v2/Users \
  -H "Authorization: Bearer scim_xxxxxxxx" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "alex@example.com",
    "name": { "formatted": "Alex Doe" },
    "active": true
  }'

Look up by email

curl -G https://www.mnueron.com/scim/v2/Users \
  -H "Authorization: Bearer scim_xxxxxxxx" \
  --data-urlencode 'filter=userName eq "alex@example.com"'

Deactivate

curl -X PATCH https://www.mnueron.com/scim/v2/Users/<id> \
  -H "Authorization: Bearer scim_xxxxxxxx" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [
      { "op": "replace", "path": "active", "value": false }
    ]
  }'

Reactivate

curl -X PATCH https://www.mnueron.com/scim/v2/Users/<id> \
  -H "Authorization: Bearer scim_xxxxxxxx" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [
      { "op": "replace", "path": "active", "value": true }
    ]
  }'

Behavior notes

  • Soft delete only.DELETE doesn't remove the row — it stamps deactivated_at so audit trails and foreign keys stay intact. Reactivate via PATCH if needed.
  • Email is the unique key.POST with an existing email returns 200 (linked) instead of 201 (created), and the existing user is added to the SCIM token's org if not already a member.
  • JIT-friendly. A user created via SCIM gets a random unguessable password hash; they can sign in via SAML SSO or run /reset-password to set a real password.
  • externalId is round-tripped.Your IdP's own user identifier is stored on the user and returned in every SCIM response.
  • Every mutation is audited. The scim_audit table appends a row for every POST/PUT/PATCH/DELETE with method, payload, response status, and timestamp. Surfaced in the org admin audit view.

Errors

All errors return SCIM-shaped JSON per RFC 7644 §3.12:

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
  "status": "401",
  "detail": "Bearer token missing or invalid"
}
StatusCause
400Malformed JSON, missing userName, or invalid filter
401Bearer token missing, expired, or revoked
404User not in this token's org
500Internal — check Mnueron status page

For IdP-specific click-paths, see the Okta guide or the Entra ID guide.