implementing-scim-provisioning
SCIM Provisioning with Scalekit
Adds automated user lifecycle management (create, update, deactivate) via Scalekit's Directory API and real-time webhooks.
Workflow
Copy and track progress:
SCIM Implementation Progress:
- [ ] Step 1: Detect stack and install SDK
- [ ] Step 2: Configure environment credentials
- [ ] Step 3: Initialize Scalekit client
- [ ] Step 4: Add Directory API sync (polling/on-demand)
- [ ] Step 5: Add webhook endpoint (real-time)
- [ ] Step 6: Register webhook in Scalekit dashboard
- [ ] Step 7: Map directory events to local user operations
- [ ] Step 8: Validate end-to-end
Step 1: Detect stack and install SDK
Detect the project's language/framework from existing files (package.json, requirements.txt, go.mod, pom.xml) and install accordingly:
| Stack | Install command |
|---|---|
| Node.js | npm install @scalekit-sdk/node |
| Python | pip install scalekit-sdk |
| Go | go get github.com/scalekit/scalekit-go |
| Java | Add com.scalekit:scalekit-sdk to pom.xml or build.gradle |
Step 2: Environment credentials
Add to .env (never hardcode):
SCALEKIT_ENVIRONMENT_URL='https://<your-env>.scalekit.com'
SCALEKIT_CLIENT_ID='<CLIENT_ID>'
SCALEKIT_CLIENT_SECRET='<CLIENT_SECRET>'
SCALEKIT_WEBHOOK_SECRET='<WEBHOOK_SECRET>'
Credentials are found in Dashboard > Developers > Settings > API Credentials. Webhook secret is found in Dashboard > Webhooks after registering an endpoint.
Step 3: Initialize the Scalekit client
Insert initialization near the app's startup or service layer — match the project's existing patterns (singleton, DI, module export, etc.).
Node.js:
import { ScalekitClient } from '@scalekit-sdk/node';
const scalekit = new ScalekitClient(
process.env.SCALEKIT_ENVIRONMENT_URL,
process.env.SCALEKIT_CLIENT_ID,
process.env.SCALEKIT_CLIENT_SECRET
);
Python:
from scalekit import ScalekitClient
scalekit_client = ScalekitClient(
env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),
client_id=os.getenv("SCALEKIT_CLIENT_ID"),
client_secret=os.getenv("SCALEKIT_CLIENT_SECRET")
)
For Go and Java patterns, see REFERENCE.md.
Step 4: Directory API (on-demand sync)
Use for scheduled jobs, onboarding flows, or bulk imports. Integrate into existing user service/repository layer — do not create a parallel user management path.
Fetch users and sync:
// Node.js
const { directory } = await scalekit.directory.getPrimaryDirectoryByOrganizationId(orgId);
const { users } = await scalekit.directory.listDirectoryUsers(orgId, directory.id);
for (const user of users) {
await upsertUser({ email: user.email, name: user.name, orgId });
}
# Python
directory = scalekit_client.directory.get_primary_directory_by_organization_id(org_id)
users = scalekit_client.directory.list_directory_users(org_id, directory.id)
for user in users:
upsert_user(email=user.email, name=user.name, org_id=org_id)
Group sync for RBAC:
const { groups } = await scalekit.directory.listDirectoryGroups(orgId, directory.id);
for (const group of groups) {
await syncGroupPermissions(group.id, group.name);
}
Plug upsertUser / syncGroupPermissions into the project's existing user/role management functions — identify them by searching for createUser, updateUser, or equivalent patterns in the codebase.
Step 5: Webhook endpoint (real-time provisioning)
Add a new route to the existing HTTP server/router. Match the framework pattern already in use (Express, FastAPI, Spring Boot, net/http, etc.).
ALWAYS verify the signature before processing. Return 400 on failure.
Node.js (Express):
app.post('/webhooks/scalekit', async (req, res) => {
try {
await scalekit.verifyWebhookPayload(
process.env.SCALEKIT_WEBHOOK_SECRET,
req.headers,
req.body
);
} catch {
return res.status(400).json({ error: 'Invalid signature' });
}
const { type, data } = req.body;
try {
await handleDirectoryEvent(type, data);
res.status(201).json({ status: 'processed' });
} catch (err) {
res.status(500).json({ error: 'Processing failed' });
}
});
Python (FastAPI):
@app.post("/webhooks/scalekit")
async def scalekit_webhook(request: Request):
body = await request.json()
valid = scalekit_client.verify_webhook_payload(
secret=os.getenv("SCALEKIT_WEBHOOK_SECRET"),
headers=request.headers,
payload=json.dumps(body).encode()
)
if not valid:
raise HTTPException(status_code=400, detail="Invalid signature")
await handle_directory_event(body.get("type"), body.get("data", {}))
return JSONResponse(status_code=201, content={"status": "processed"})
For Go and Java, see REFERENCE.md.
Step 6: Event handler
Create a single dispatcher that routes to existing user operations. Map events to the project's existing create/update/deactivate functions:
async function handleDirectoryEvent(type, data) {
switch (type) {
case 'organization.directory.user_created':
return createUser(data.email, data.name, data.organization_id);
case 'organization.directory.user_updated':
return updateUser(data.email, data.name);
case 'organization.directory.user_deleted':
return deactivateUser(data.email); // prefer deactivate over hard delete
case 'organization.directory.group_created':
case 'organization.directory.group_updated':
return syncGroup(data);
default:
console.log(`Unhandled event: ${type}`);
}
}
Prefer deactivation over deletion for user_deleted events unless the project explicitly hard-deletes users.
Step 7: Dashboard registration checklist
After deploying the webhook endpoint:
- Go to Dashboard > Webhooks > +Add Endpoint
- Enter the public HTTPS URL:
https://your-app.com/webhooks/scalekit - Subscribe to events:
organization.directory.user_createdorganization.directory.user_updatedorganization.directory.user_deletedorganization.directory.group_createdorganization.directory.group_updated
- Copy the webhook secret into
SCALEKIT_WEBHOOK_SECRET - Share the SCIM setup guide with the customer's IT admin for their IdP-specific directory sync steps.
Guardrails
- Never hardcode credentials — always
process.env/os.getenv/System.getenv - Idempotent operations —
upsertUsermust handle duplicate events safely - Return 2xx quickly — offload heavy processing to a queue if needed; Scalekit retries on non-2xx with exponential backoff (up to 8 attempts over ~10 hours)
- Validate signatures — every webhook request, every time
- Deactivate, don't delete — unless codebase explicitly hard-deletes users
Reference files
- Full Go/Java SDK examples → REFERENCE.md
- Webhook event payload schemas → EVENTS.md
- RBAC group-to-role mapping patterns → RBAC.md
More from scalekit-inc/skills
setup-scalekit
Use when a developer is new to Scalekit and needs guidance on where to start, doesn't know which auth plugin or skill to choose, wants to connect an AI agent or agentic workflow to third-party services (Gmail, Slack, Notion, Google Calendar), needs OAuth or tool-calling auth for agents, wants to add authentication to a project but hasn't chosen an approach yet, or needs to install the Scalekit plugin for their AI coding tool (Claude Code, Codex, Copilot CLI, Cursor, or other agents).
11implementing-scalekit-fsa
Implements Scalekit full-stack authentication (FSA) including sign-up, login, logout, and secure session management using JWT tokens. Use when building or integrating user authentication with the Scalekit SDK across Node.js, Python, Go, or Java — or when the user asks about auth flows, OAuth callbacks, token refresh, or session handling with Scalekit.
4integrating-agent-auth
Integrates Scalekit Agent Auth into a project to handle OAuth flows, token storage, and automatic refresh for third-party services (Gmail, Slack, Notion, Calendar). Use when a user needs to connect to an external service, authorize OAuth access, fetch access or refresh tokens, or execute API calls on behalf of a user.
4adding-mcp-oauth
Guides users through adding OAuth 2.1 authorization to Model Context Protocol (MCP) servers using Scalekit. Use when setting up MCP servers, implementing authentication for AI hosts like Claude Desktop, Cursor, or VS Code, or when users mention MCP security, OAuth, or Scalekit integration.
3modular-sso
Implements complete SSO and authentication flows using Scalekit. Handles modular SSO, IdP-initiated login, user session management, and enterprise customer onboarding. Use when adding authentication, SSO, SAML, OIDC, or user login to applications.
3sk-actions-custom-provider
Create or review Scalekit custom providers/connectors for proxy-only usage. Use this skill when the task is to gather API docs, infer whether a connector is OAuth, Basic, Bearer, or API Key, determine required tracked fields like domain or version, generate provider JSON, check for existing custom providers, show update diffs, run approved create or update curls, and print resolved delete curls.
3