From modular-scim
Implements SCIM user provisioning using Scalekit's Directory API and webhooks. Use when the user asks to add SCIM, directory sync, user provisioning, deprovisioning, or lifecycle management to their existing application.
How this skill is triggered — by the user, by Claude, or both
Slash command
/modular-scim:modular-scimThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Adds automated user lifecycle management (create, update, deactivate) via Scalekit's Directory API and real-time webhooks.
Adds automated user lifecycle management (create, update, deactivate) via Scalekit's Directory API and real-time webhooks.
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
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 |
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.
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.
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.
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.
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.
After deploying the webhook endpoint:
https://your-app.com/webhooks/scalekitorganization.directory.user_createdorganization.directory.user_updatedorganization.directory.user_deletedorganization.directory.group_createdorganization.directory.group_updatedSCALEKIT_WEBHOOK_SECRETprocess.env / os.getenv / System.getenvupsertUser must handle duplicate events safelynpx claudepluginhub scalekit-inc/claude-code-authstack --plugin modular-scimImplements a SCIM 2.0 API endpoint and integrates with Okta for automated user lifecycle management, including provisioning, deprovisioning, profile updates, and group management.
Implements SCIM 2.0 provisioning with Okta for automated user lifecycle management including creation, updates, deprovisioning, and group sync.
Implements SCIM 2.0-compliant API endpoints for automated user/group provisioning, deprovisioning, updates, and management with Okta IdP using Python Flask/FastAPI.