Erreurs et limites
Les enveloppes d'erreur de chaque surface d'API, les codes d'erreur courants, les limites de débit, le verrouillage de compte et les plafonds de la plateforme.
Obexal a trois surfaces d'API, et chacune utilise la convention d'erreur attendue par son protocole. Cette page liste les formes, les codes stables et toutes les limites appliquées.
Formats d'erreur
API JSON (tout ce qui est sous /v1/) : une enveloppe unique sur chaque réponse non-2xx. code est une chaîne machine stable ; message est lisible par un humain et peut changer.
{"error": {"code": "rate_limited", "message": "too many requests"}}Endpoints OAuth (/oauth/*) : la forme RFC 6749, avec des champs snake_case au premier niveau.
{"error": "invalid_grant", "error_description": "code invalide, expiré ou déjà utilisé"}Sur /oauth/authorize, les erreurs sont redirigées vers le client en paramètres de requête error, error_description et state une fois la redirect_uri validée ; avant cela, la réponse est un 400 direct (jamais de redirection ouverte). Un échec d'authentification client_secret_basic renvoie 401 avec un en-tête WWW-Authenticate: Basic. /oauth/userinfo renvoie 401 avec un en-tête WWW-Authenticate: Bearer error="invalid_token" (son corps utilise l'enveloppe JSON).
SCIM (/scim/v2/*) : le corps d'erreur SCIM standard, voir la référence SCIM.
{"schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"], "status": "404", "detail": "utilisateur introuvable"}Codes d'erreur courants de l'API
| Code | Statut HTTP | Signification |
|---|---|---|
invalid_request | 400 | Corps malformé ou paramètres invalides |
unauthenticated | 401 | Session absente, expirée ou révoquée |
invalid_credentials | 401 | E-mail ou mot de passe erroné |
unauthorized | 401 | Jeton d'API d'administration absent, invalide, expiré ou révoqué |
forbidden | 403 | Permission manquante (RBAC deny-by-default, ou hors des scopes du jeton) |
csrf_failed | 403 | En-tête X-CSRF-Token absent ou différent sur une mutation authentifiée par cookie |
step_up_required | 403 | Une action sensible exige une vérification fraîche du second facteur (POST /v1/mfa/step-up) |
mfa_enrollment_required | 403 | Le tenant exige la MFA et aucun facteur n'est enrôlé (mode strict) |
not_found | 404 | Ressource absente de votre tenant |
conflict | 409 | La ressource existe déjà |
payload_too_large | 413 | Corps de requête au-dessus de la limite |
rate_limited | 429 | Trop de tentatives, réessayez plus tard |
account_locked | 429 | Compte verrouillé après des échecs de connexion répétés |
internal_error | 500 | Erreur serveur inattendue |
Des codes propres à chaque fonctionnalité existent aussi (par exemple slug_taken, email_taken, invalid_invite, password_expired) : traitez le statut HTTP comme la classe et le code comme la raison précise.
Codes d'erreur OAuth
| Code | Cause typique |
|---|---|
invalid_request | Paramètre absent ou malformé (code manquant, code_verifier manquant, URN de type de jeton non supporté) |
invalid_client | Client inconnu, client_secret erroné ou expiré (401 quand présenté en Basic) |
invalid_grant | Code ou refresh token invalide, expiré, rejoué ou lié à un autre client ; agent désactivé ou expiré ; tenant suspendu |
unauthorized_client | Type de grant non activé pour ce client |
unsupported_grant_type | Valeur de grant_type inconnue |
unsupported_response_type | Autre chose que code |
invalid_scope | Scope demandé hors de l'ensemble autorisé (scopes du client, scopes du sujet, plafond de l'agent ou autorisation de l'utilisateur) |
access_denied | L'utilisateur ou la frontière de tenant a refusé la requête |
login_required, consent_required | Interaction nécessaire mais prompt=none l'interdit |
invalid_target | resource n'est pas une URI absolue ou ne figure pas dans les audiences autorisées de l'agent (RFC 8693/8707) |
invalid_dpop_proof | Preuve DPoP absente, malformée ou rejouée |
server_error | Erreur serveur inattendue |
Limites de débit
Les flux sensibles sont limités par fenêtres fixes, par e-mail et par IP cliente indépendamment. Deux familles existent ; leurs valeurs par défaut figurent dans la référence de configuration :
| Famille | Flux couverts |
|---|---|
Connexion (RATE_LIMIT_LOGIN_*) | Connexion par mot de passe, passwordless, défis MFA et renvois, connexion par passkey |
Compte (RATE_LIMIT_SIGNUP_*) | Inscription, création d'organisation, demandes de réinitialisation de mot de passe |
Les flux de vérification d'e-mail, de changement d'e-mail, d'invitation et de connexion sociale sont limités par les mêmes mécanismes. Dépasser une limite renvoie 429 rate_limited et l'évènement est consigné dans le journal d'audit.
Verrouillage de compte
Indépendamment des limites par IP, les échecs répétés de mot de passe verrouillent le compte lui-même, ce qui résiste à la rotation d'IP (LOGIN_LOCKOUT_MAX, LOGIN_LOCKOUT_WINDOW, LOGIN_LOCKOUT_DURATION) ; les valeurs par défaut figurent dans la référence de configuration. La réponse est 429 account_locked. Un administrateur peut lever le verrou avec POST /v1/admin/users/unlock.
Les codes à usage unique ont leurs propres plafonds : les OTP par e-mail autorisent 5 tentatives et expirent après 10 minutes ; les défis MFA autorisent 5 tentatives et expirent après 5 minutes (défauts).
Plafonds de la plateforme
| Limite | Valeur |
|---|---|
| Corps de requête (API JSON) | 1 Mio |
Pagination des listes (?limit) | Défaut 100, maximum 500 |
Export d'audit (GET /v1/admin/audit/export) | 10000 évènements par appel ; la réponse positionne truncated: true au-delà |
Recherche d'audit (?q) | 200 caractères |
| Versions de politique d'accès conservées | Les 50 plus récentes |
| Échantillon de simulation de politique | Connexions des 30 derniers jours, jusqu'à 1000 IP distinctes |
| Pays par règle d'accès conditionnel | 250 |
| Page de liste SCIM | 200 ressources |
Ces plafonds sont appliqués côté serveur ; les clients doivent paginer plutôt que chercher à les relever.