Prérequis
- Plan Enterprise (vérifié sur la route
/api/auth/sso/[tenantSlug]— les autres plans retournent 403) - Domaine configuré (white-label optionnel mais recommandé)
- Accès administrateur à l'IdP (Okta, Azure AD, Google Workspace, Ping, OneLogin, etc.)
SAML 2.0
Configuration
Settings > SSO > Add Provider > SAML
Champs :
- Display name — nom affiché sur le bouton "Sign in with..."
- Metadata XML URL OU Metadata XML collé — fourni par l'IdP
- SP-initiated ou IdP-initiated — Studeia supporte les deux
- Allowed domains — restreint les emails (anti-shadow accounts)
Endpoints exposés
- ACS (Assertion Consumer Service) :
/api/auth/sso/[tenantSlug]/saml/callback - SP metadata :
/api/institution/sso/metadata
Validation
La réponse SAML est validée via node-saml :
- Vérification de la signature XML (anti-tampering)
- Validation des namespaces XML SAML (anti-XXE)
- Vérifications NotBefore/NotOnOrAfter
- Restriction d'audience
OIDC
Configuration
Settings > SSO > Add Provider > OIDC
Champs :
- Discovery URL —
https://idp.com/.well-known/openid-configuration(auto-fetch) - Client ID + Client Secret (chiffré AES-256-GCM)
- Scopes — par défaut :
openid profile email - PKCE — toujours activé (méthode S256 challenge)
Flux
- L'apprenant clique sur "Sign in with [IdP]" →
/api/auth/sso/[tenantSlug]/oidc - Redirection vers l'IdP avec PKCE challenge + state signé HMAC + nonce dans Redis (TTL 15min anti-replay)
- L'IdP authentifie → callback
/api/auth/sso/[tenantSlug]/oidc/callback - Studeia valide le state + nonce, échange le code contre des tokens (PKCE verifier)
- Endpoint Userinfo → JIT provisioning (crée l'User s'il n'existe pas) → session Supabase
SCIM 2.0
14 endpoints RFC 7644
GET /api/scim/v2/ServiceProviderConfig
GET /api/scim/v2/ResourceTypes
GET /api/scim/v2/Schemas
GET /api/scim/v2/Users (list, avec filter)
POST /api/scim/v2/Users (create)
GET /api/scim/v2/Users/{id}
PUT /api/scim/v2/Users/{id} (replace complet)
PATCH /api/scim/v2/Users/{id} (partiel — compatible Microsoft Graph)
DELETE /api/scim/v2/Users/{id} (soft-delete : User.status=suspended)
GET /api/scim/v2/Groups (list)
POST /api/scim/v2/Groups
GET /api/scim/v2/Groups/{id}
PUT /api/scim/v2/Groups/{id}
PATCH /api/scim/v2/Groups/{id}
DELETE /api/scim/v2/Groups/{id}
Configuration dans Azure AD (exemple)
- Azure Portal > Enterprise Applications > Studeia > Provisioning
- Provisioning Mode : Automatic
- Tenant URL :
https://votreapp.studeia.com/api/scim/v2 - Secret Token : généré dans Studeia via Settings > SSO > SCIM Token (Bearer, chiffré en base de données)
- Test Connection
- Mappings : attributs par défaut (compatible Microsoft Graph)
- Settings > Scope : "Sync only assigned users and groups"
- Start provisioning
Group → Course mapping
Permet l'inscription automatique lorsque l'IdP ajoute un utilisateur à un groupe :
- Configurez le mapping dans Settings > SSO > Groups
- Pour chaque SsoGroup, choisissez le Course cible
- Lorsque SCIM ajoute un membre au groupe → Studeia crée une Enrollment active au cours
- Lorsqu'il le retire → annulation de l'inscription (status=cancelled)
- Grands groupes (>50 membres) : traitement via BullMQ (queue
scim-group-sync), réponse 202 + jobId
Sécurité
Tokens
- Bearer token SCIM : chiffré AES-256-GCM dans
TenantSsoConfig.scimToken— JAMAIS en texte clair - Tokens OAuth (intégration Google Workspace) : même standard
- State OAuth : HMAC-SHA256 avec
OAUTH_STATE_SECRET+ nonce Redis (TTL 15min)
JIT provisioning
allowedDomainsvalide l'email avant de créer l'utilisateur- Attributs de l'IdP mappés via
SsoAttributeMapping - Rôle par défaut configurable (
studentouteacher)
Audit
ScimAuditLog enregistre :
- Toute opération SCIM (Create/Update/Delete) avec timestamp + IP + acteur (IdP) + utilisateur/groupe affecté + payload (redacted)
- AdminAuditLog pour les modifications de SsoConfig par un administrateur institutionnel
Limitations
- LDAP direct (sans SAML/OIDC) non supporté nativement — roadmap
- Just-in-time deprovisioning via SAML SLO (Single Logout) partiel — il est recommandé d'utiliser SCIM pour un déprovisionnement fiable
- Authentification multi-facteurs déléguée à l'IdP (Studeia ne gère pas son propre MFA lorsque le SSO est actif)
- Group nesting (groupes imbriqués) partiellement supporté — il est recommandé de les aplatir dans l'IdP