SCIM Connector Platform
Status
In Development
Maturity
Production-oriented lab
Evidence
Architecture diagram added · Sanitized demo views added · Repo pending
Next
Add protected demo walkthrough
Problem
Enterprises using Okta, Entra ID, or Auth0 need reliable automated provisioning to downstream SaaS and internal platforms. Manual provisioning creates stale accounts, audit gaps, and inconsistent access states across systems.
What Was Built
A multi-tenant SCIM v2 connector platform. Customers self-service create tenants and connectors. Each connector receives a unique Bearer token used by the IdP to authenticate SCIM requests. Bearer tokens are hashed with PBKDF2-SHA256 using 600,000 iterations and a random per-token salt. Plaintext tokens are displayed only once and never stored.
Architecture Diagram
Identity Providers
SCIM Connector Platform
Data & Operations
- Tenant Store
- Audit Log
- Metrics Collector
Admin & Ops
- Admin Console
- Operator Dashboard
- Customer Portal
Target Applications
Request Flow
- 1IdP sends SCIM request: Authorization: Bearer <token> header
- 2Token Validator computes PBKDF2-SHA256 hash (600k iterations), looks up tenant store — plaintext never stored
- 3Tenant Router directs request to correct tenant namespace
- 4SCIM v2 Handler processes operation (create / update / delete / patch)
- 5Audit event written: actor=connector_id, resource=user|group, action, outcome, timestamp
- 6HTTP 200/201/204 returned to IdP; failures return RFC 7643 / RFC 7644-compliant error body
SCIM Endpoints Implemented
| Method | Endpoint | Operation |
|---|---|---|
| GET | /scim/v2/Users | List users (supports filter) |
| POST | /scim/v2/Users | Create user |
| GET | /scim/v2/Users/{id} | Get user by ID |
| PUT | /scim/v2/Users/{id} | Replace user |
| PATCH | /scim/v2/Users/{id} | Partial update |
| DELETE | /scim/v2/Users/{id} | Deprovision user |
| GET | /scim/v2/Groups | List groups |
| POST | /scim/v2/Groups | Create group |
| GET | /scim/v2/Groups/{id} | Get group |
| PATCH | /scim/v2/Groups/{id} | Update group membership |
| DELETE | /scim/v2/Groups/{id} | Remove group |
| GET | /scim/v2/ServiceProviderConfig | Advertise capabilities |
| GET | /scim/v2/Schemas | Schema discovery |
| GET | /scim/v2/ResourceTypes | Resource type discovery |
Security Controls
- ▸Bearer token protection: PBKDF2-SHA256 hashing with 600,000 iterations, random per-token salt, display-once plaintext handling, and timing-safe verification.
- ▸Plaintext never stored — display-once at creation
- ▸Tenant isolation: token scoped to exactly one tenant namespace
- ▸Admin MFA enforced on dashboard
- ▸Rate limiting per connector
Operational Controls
- ▸Health check endpoint — liveness probe
- ▸Readiness check endpoint — verifies DB connectivity and downstream dependencies
- ▸Metrics endpoint — Prometheus-compatible counters for provisioned count, error rate, and latency
- ▸Structured JSON audit log per event
- ▸Admin/operator dashboard: tenant list, connector status, recent events
Failure Handling
- ▸Token not found → 401 Unauthorized + failed_auth audit event
- ▸User already exists → 409 Conflict (RFC 7643 / RFC 7644)
- ▸Malformed payload → 400 Bad Request with detail
- ▸Downstream unavailable → 503 with retry guidance
- ▸All failures logged with request ID
Design Trade-offs
- 1.Stateless token validation chosen over session auth for IdP compatibility
- 2.DB-level tenant namespacing rather than separate DB per tenant — cost vs isolation trade-off
- 3.Display-once token pattern prioritises security over operator convenience
Platform Views
⚠Sanitized demo views — production data redacted. Real screenshots will replace these when live deployment is available.
Tenant
Connector Name
SCIM Base URL
⚠ Bearer Token — shown once only, never retrievable
Plaintext value redacted. Copy before closing this dialog.
| Timestamp (UTC) | Connector | Action | Resource | Outcome |
|---|---|---|---|---|
| 2026-05-16 14:32:01 | conn-[redacted] | user.created | user@[redacted] | success |
| 2026-05-16 14:31:58 | conn-[redacted] | user.updated | user@[redacted] | success |
| 2026-05-16 09:15:22 | conn-[redacted] | user.deprovisioned | user@[redacted] | success |
| 2026-05-16 09:14:55 | conn-[redacted] | auth.failed | — | failed_auth |
# HELP scim_requests_total Total SCIM requests by tenant and status
# TYPE scim_requests_total counter
scim_requests_total{tenant="[redacted]",method="POST",status="201"} 1423
scim_requests_total{tenant="[redacted]",method="GET",status="200"} 8891
scim_requests_total{tenant="[redacted]",method="PATCH",status="204"} 346
scim_requests_total{tenant="[redacted]",method="POST",status="409"} 12
# HELP scim_request_duration_seconds Request latency histogram
# TYPE scim_request_duration_seconds histogram
scim_request_duration_seconds{quantile="0.5",tenant="[redacted]"} 0.021
scim_request_duration_seconds{quantile="0.99",tenant="[redacted]"} 0.187
# HELP scim_health_status Liveness probe result (1 = healthy)
# TYPE scim_health_status gauge
scim_health_status 1Employer Value
Risk reduced
Orphaned accounts, access drift, provisioning audit gaps
Operational value
Automated lifecycle management across IdP and SaaS fleet
IAM domain
SCIM v2, identity lifecycle, multi-tenant SaaS architecture
Seniority signal
End-to-end platform design — not just SCIM client usage
Evidence Roadmap
Architecture and sanitized demo views are included above. Screenshots, repository, and walkthrough will be added as the project matures.
Architecture Diagram
[ Included above ]
Platform Views
[ Sanitized demo views added above ]
GitHub Repository
[ Repo pending ]
Protected Demo Walkthrough
[ Walkthrough pending ]