Skip to main content

SSO & SCIM Provisioning

WorldFlow AI supports enterprise identity management through SSO (OIDC and SAML) and SCIM automated user provisioning. This guide covers the full lifecycle: creating connections, verifying domains, activating SSO, and configuring SCIM tokens for your identity provider.

Prerequisites

  • A valid JWT token with workspace-admin privileges
  • Base URL for your WorldFlow AI deployment (examples use https://api.worldflowai.com)
  • Access to your identity provider's admin console (Okta, Azure AD, Google Workspace, etc.)

SSO Connections

An SSO connection represents a link between your WorldFlow AI workspace and an identity provider. Each connection uses either OIDC or SAML and can have one or more verified domains.

Create an OIDC Connection

curl -X POST https://api.worldflowai.com/api/v1/sso/connections \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Okta OIDC",
"protocol": "oidc",
"oidcConfig": {
"issuerUrl": "https://your-org.okta.com",
"clientId": "0oa1abc2def3ghijk",
"clientSecret": "your-client-secret",
"scopes": ["openid", "profile", "email"]
},
"jitProvisioning": true,
"defaultRole": "viewer"
}'

The connection is created in inactive status. You must test and activate it before users can sign in.

Create a SAML Connection

curl -X POST https://api.worldflowai.com/api/v1/sso/connections \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Azure AD SAML",
"protocol": "saml",
"samlConfig": {
"entityId": "https://sts.windows.net/{tenant-id}/",
"ssoUrl": "https://login.microsoftonline.com/{tenant-id}/saml2",
"certificate": "-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----",
"signRequests": true,
"attributeMapping": {
"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
}
},
"jitProvisioning": false,
"defaultRole": "member"
}'

Request body fields:

FieldTypeRequiredDescription
namestringyesConnection name (max 128 chars)
protocolstringyesoidc or saml
oidcConfigobjectif OIDCOIDC configuration (see below)
samlConfigobjectif SAMLSAML configuration (see below)
jitProvisioningbooleannoAuto-create users on first login (default: false)
defaultRolestringnoRole assigned to JIT-provisioned users (default: viewer)

OIDC config fields: issuerUrl, clientId, clientSecret (encrypted at rest), discoveryUrl, scopes

SAML config fields: entityId, ssoUrl, certificate (PEM), signRequests, attributeMapping

List SSO Connections

curl "https://api.worldflowai.com/api/v1/sso/connections?protocol=oidc&status=active" \
-H "Authorization: Bearer $TOKEN"
ParameterDescription
protocolFilter: oidc or saml
statusFilter: active, inactive, testing, error
namePartial name match
page / pageSizePagination (max 100 per page)

Get a Connection

curl https://api.worldflowai.com/api/v1/sso/connections/{id} \
-H "Authorization: Bearer $TOKEN"

Returns the full connection including associated domains.

Update a Connection

curl -X PUT https://api.worldflowai.com/api/v1/sso/connections/{id} \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"oidcConfig": {
"clientSecret": "new-rotated-secret"
}
}'

Only provided fields are updated.

Delete a Connection

curl -X DELETE https://api.worldflowai.com/api/v1/sso/connections/{id} \
-H "Authorization: Bearer $TOKEN"

Soft-deletes the connection. Users who authenticated via this connection retain their accounts but must use a different login method.


Connection Testing & Activation

Before activating a connection, test it to verify that your IdP configuration is correct.

Test a Connection

curl -X POST https://api.worldflowai.com/api/v1/sso/connections/{id}/test \
-H "Authorization: Bearer $TOKEN"

For OIDC, this validates discovery and JWKS endpoints. For SAML, it validates the certificate and metadata. On success the connection status changes to testing; on failure it changes to error.

Response:

{
"success": true,
"details": {
"discoveryValid": true,
"jwksValid": true,
"latencyMs": 142
}
}

Activate a Connection

curl -X POST https://api.worldflowai.com/api/v1/sso/connections/{id}/activate \
-H "Authorization: Bearer $TOKEN"

Changes the connection status to active. Users matching a verified domain can now sign in through this connection.

Deactivate a Connection

curl -X POST https://api.worldflowai.com/api/v1/sso/connections/{id}/deactivate \
-H "Authorization: Bearer $TOKEN"

Changes the status back to inactive. Existing sessions are not terminated, but new logins are blocked.


Domain Verification

Each SSO connection requires at least one verified domain. Domain verification proves that you control the email domain that will be routed to this connection.

Add a Domain

curl -X POST https://api.worldflowai.com/api/v1/sso/connections/{id}/domains \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com",
"verificationMethod": "dns-txt"
}'
FieldValuesDescription
domainany domainThe email domain (e.g., example.com)
verificationMethoddns-txt, https-fileVerification approach

Response includes a dnsRecord object with the TXT record you must add:

{
"domain": {
"id": "dom-uuid",
"domain": "example.com",
"status": "pending",
"verificationToken": "worldflow-verify=abc123..."
},
"dnsRecord": {
"recordType": "TXT",
"name": "_worldflow-verify.example.com",
"value": "worldflow-verify=abc123..."
}
}

Verify a Domain

After adding the DNS record, trigger verification:

curl -X PUT https://api.worldflowai.com/api/v1/sso/connections/{id}/domains/{domain_id}/verify \
-H "Authorization: Bearer $TOKEN"

Returns success: true and updates the domain status to verified. If the TXT record is not found, the domain status becomes failed.

Set Primary Domain

curl -X POST https://api.worldflowai.com/api/v1/sso/connections/{id}/domains/{domain_id}/set-primary \
-H "Authorization: Bearer $TOKEN"

The primary domain is used as the default for JIT-provisioned users.

Remove a Domain

curl -X DELETE https://api.worldflowai.com/api/v1/sso/connections/{id}/domains/{domain_id} \
-H "Authorization: Bearer $TOKEN"

SAML Service Provider Metadata

When configuring your IdP for SAML, you need the WorldFlow AI SP metadata:

curl https://api.worldflowai.com/api/v1/sso/sp-metadata \
-H "Authorization: Bearer $TOKEN"

Response:

{
"entityId": "https://api.worldflowai.com/saml/metadata",
"acsUrl": "https://api.worldflowai.com/saml/acs",
"metadataXml": "<?xml version=\"1.0\"?>..."
}

Copy the entityId and acsUrl into your IdP's SAML application configuration, or import the metadataXml directly.


SCIM Provisioning

SCIM (System for Cross-domain Identity Management) automates user and group synchronization from your identity provider. WorldFlow AI acts as a SCIM service provider.

Create a SCIM Token

Your IdP needs a bearer token to authenticate SCIM requests. The plain token value is returned exactly once at creation.

curl -X POST https://api.worldflowai.com/api/v1/scim/tokens \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Okta SCIM Token",
"scopes": ["users:read", "users:write", "groups:read", "groups:write"],
"expiresInDays": 365
}'

Request body fields:

FieldTypeRequiredDescription
namestringyesToken name (max 128 chars)
scopesstring[]noPermitted scopes (default: users:read, users:write)
expiresInDaysintegernoExpiration in days (null = never)

Available scopes: users:read, users:write, groups:read, groups:write

Response (save the plainValue immediately):

{
"token": {
"id": "tok-uuid",
"name": "Okta SCIM Token",
"maskedValue": "scim_abc1...****",
"status": "active",
"scopes": ["users:read", "users:write", "groups:read", "groups:write"],
"createdAt": "2025-01-15T10:00:00Z"
},
"plainValue": "scim_abc1def2ghi3jkl4mno5pqr6stu7vwx8"
}

List SCIM Tokens

curl "https://api.worldflowai.com/api/v1/scim/tokens?status=active" \
-H "Authorization: Bearer $TOKEN"
ParameterDescription
statusFilter: active, revoked, expired
nameSearch by name
page / pageSizePagination (max 100)

Get a Token

curl https://api.worldflowai.com/api/v1/scim/tokens/{id} \
-H "Authorization: Bearer $TOKEN"

The plain value is never returned after creation. Only the maskedValue prefix is visible.

Revoke a Token

curl -X POST https://api.worldflowai.com/api/v1/scim/tokens/{id}/revoke \
-H "Authorization: Bearer $TOKEN"

Immediately prevents further SCIM operations with this token.

Delete a Token

curl -X DELETE https://api.worldflowai.com/api/v1/scim/tokens/{id} \
-H "Authorization: Bearer $TOKEN"

Permanently removes the token and its associated activity logs.


SCIM Activity Logs

Monitor what your IdP is doing through SCIM:

curl "https://api.worldflowai.com/api/v1/scim/activities?operation=create&resourceType=user&status=success" \
-H "Authorization: Bearer $TOKEN"
ParameterDescription
operationFilter: create, update, delete
resourceTypeFilter: user, group
statusFilter: success, error
startDate / endDateISO 8601 date range
page / pageSizePagination (max 100)

Each activity entry includes the operation type, resource type, resource ID, status, error message (if any), details object, and timestamp.


SCIM Statistics

Get a summary of SCIM sync health:

curl https://api.worldflowai.com/api/v1/scim/statistics \
-H "Authorization: Bearer $TOKEN"

Response:

{
"totalUsers": 847,
"totalGroups": 23,
"usersAdded24h": 12,
"usersRemoved24h": 1,
"groupsAdded24h": 0,
"groupsRemoved24h": 0,
"lastSyncAt": "2025-01-15T14:30:00Z",
"errorCount24h": 0,
"activeTokens": 2
}

Typical Setup Flow

  1. Create an SSO connection (OIDC or SAML) with your IdP details
  2. Add and verify a domain so the system knows which users to route
  3. Test the connection to validate IdP configuration
  4. Activate the connection to allow sign-ins
  5. Create a SCIM token and configure it in your IdP for automated provisioning
  6. Monitor SCIM activity to confirm users and groups sync correctly

Error Responses

All endpoints return errors in a consistent format:

{
"error": {
"type": "validation_error",
"message": "Connection name is required"
}
}
CodeMeaning
400Validation error
401Authentication required
403Insufficient permissions
404Resource not found
409Conflict (duplicate name)