API Utilisateurs
L’Users API fournit la gestion complète du cycle de vie des comptes utilisateur au sein d’un tenant : création, lecture, mise à jour, désactivation et suppression des utilisateurs ; assignation des rôles ; import et export massif des utilisateurs ; et gestion des numéros de téléphone et des paramètres d’authentification à deux facteurs pour les comptes individuels.
Tous les endpoints de cette section nécessitent le header x-tenant et, sauf indication contraire, nécessitent la permission manage:users.
Gestion des Utilisateurs
/api/usersRequires: manage:usersListe tous les utilisateurs du tenant. Supporte la pagination et le filtrage par rôle, statut du compte et requête de recherche. Retourne des objets utilisateur avec des informations de résumé (n’inclut pas le statut 2FA ou les détails de session — utilise l’endpoint utilisateur individuel pour ceux-là).
Paramètres de query
| Paramètre | Type | Description |
|---|---|---|
page | integer | Numéro de page (défaut : 1) |
limit | integer | Éléments par page (défaut : 20, max : 100) |
search | string | Recherche full-text sur email, username, firstName, lastName |
role | string | Filtre par nom de rôle |
status | active | disabled | locked | Filtre par statut du compte |
Réponse de succès
{
"ok": true,
"data": {
"data": [
{
"id": "usr_abc123",
"email": "[email protected]",
"username": "alice",
"firstName": "Alice",
"lastName": "Dupont",
"enabled": true,
"emailVerified": true,
"createdAt": "2025-01-15T10:30:00Z",
"roles": ["editor", "viewer"]
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 87,
"totalPages": 5
}
}
}/api/usersRequires: manage:usersCrée un nouveau compte utilisateur dans le tenant. L’utilisateur est créé à la fois dans la base de données Auris et dans le realm Keycloak sous-jacent. Si password est omis, le compte est créé sans mot de passe (l’utilisateur doit en définir un via un magic link ou le flux de réinitialisation de mot de passe).
Corps de la requête
{
"email": "[email protected]",
"username": "bob",
"firstName": "Robert",
"lastName": "Martin",
"password": "MotDePasseInitial123",
"roles": ["viewer"],
"enabled": true
}Tous les champs sauf email sont optionnels.
Réponse de succès
{
"ok": true,
"data": {
"id": "usr_def456",
"email": "[email protected]",
"username": "bob",
"firstName": "Robert",
"lastName": "Martin",
"enabled": true,
"emailVerified": false,
"createdAt": "2025-02-18T09:00:00Z",
"roles": ["viewer"]
}
}Codes d’erreur
| Code | HTTP | Description |
|---|---|---|
EMAIL_TAKEN | 409 | Un utilisateur avec cet email existe déjà dans le tenant |
USERNAME_TAKEN | 409 | Le nom d’utilisateur est déjà utilisé |
VALIDATION_ERROR | 400 | Le corps de la requête n’a pas passé la validation du schéma |
/api/users/[id]Requires: manage:usersRécupère un seul utilisateur par son ID. Retourne les détails complets de l’utilisateur incluant les appartenances aux rôles, le statut 2FA, le numéro de téléphone, les appartenances aux groupes et les informations du dernier login.
Réponse de succès
{
"ok": true,
"data": {
"id": "usr_abc123",
"email": "[email protected]",
"username": "alice",
"firstName": "Alice",
"lastName": "Dupont",
"enabled": true,
"emailVerified": true,
"phoneNumber": "+33 1 23 45 67 89",
"phoneNumberVerified": true,
"createdAt": "2025-01-15T10:30:00Z",
"lastLoginAt": "2025-02-17T14:22:00Z",
"roles": ["editor", "viewer"],
"twoFactor": {
"totpEnabled": true,
"smsEnabled": false,
"webauthnEnabled": false
}
}
}Codes d’erreur
| Code | HTTP | Description |
|---|---|---|
NOT_FOUND | 404 | L’utilisateur n’existe pas dans ce tenant |
/api/users/[id]Requires: manage:usersMet à jour les champs du profil d’un utilisateur. Tous les champs sont optionnels — seuls les champs fournis sont mis à jour. Pour désactiver un utilisateur sans le supprimer, définis enabled: false.
Corps de la requête
{
"firstName": "Alicia",
"lastName": "Dupont-Martin",
"enabled": false
}Réponse de succès
{
"ok": true,
"data": {
"id": "usr_abc123",
"email": "[email protected]",
"firstName": "Alicia",
"lastName": "Dupont-Martin",
"enabled": false
}
}/api/users/[id]Requires: manage:usersSoft-delete d’un utilisateur. Le compte utilisateur est désactivé et marqué comme supprimé dans la base de données Auris, et son compte Keycloak est retiré. Les sessions actives sont invalidées immédiatement.
Le soft-delete est irréversible via l’API. L’enregistrement utilisateur est conservé dans la base de données pour la cohérence du log d’audit mais ne peut pas être récupéré ou accessible. Utilise enabled: false via PUT /api/users/[id] si tu souhaites désactiver temporairement sans suppression.
Réponse de succès
{
"ok": true,
"data": { "deleted": true }
}Assignation des Rôles
/api/users/[id]/rolesRequires: manage:usersListe tous les rôles actuellement assignés à un utilisateur.
Réponse de succès
{
"ok": true,
"data": [
{
"id": "role_123",
"name": "editor",
"description": "Peut créer et modifier du contenu",
"color": "#3b82f6"
}
]
}/api/users/[id]/rolesRequires: manage:usersAssigne un rôle à un utilisateur. Le rôle doit exister dans le tenant. Assigner le même rôle deux fois est un no-op (idempotent).
Corps de la requête
{
"roleId": "role_123"
}Réponse de succès
{
"ok": true,
"data": { "assigned": true }
}Codes d’erreur
| Code | HTTP | Description |
|---|---|---|
NOT_FOUND | 404 | Le rôle n’existe pas dans ce tenant |
SELF_ROLE_CHANGE | 403 | Tu ne peux pas modifier tes propres rôles |
/api/users/[id]/rolesRequires: manage:usersRetire un rôle d’un utilisateur. Retirer un rôle que l’utilisateur n’a pas est un no-op (idempotent).
Corps de la requête
{
"roleId": "role_123"
}Réponse de succès
{
"ok": true,
"data": { "removed": true }
}Import Massif
/api/users/importRequires: manage:usersImporte des utilisateurs en masse depuis un fichier CSV ou JSON. L’import est exécuté de manière asynchrone — l’endpoint retourne immédiatement un job ID. Effectue un polling sur GET /api/users/import/[id] pour surveiller la progression.
Format de la requête : multipart/form-data
| Champ | Type | Description |
|---|---|---|
file | binary | Fichier CSV ou JSON |
format | csv | json | Format du fichier |
sendWelcomeEmail | boolean | Envoie un email de bienvenue aux nouveaux utilisateurs (défaut : false) |
Format CSV (la première ligne est l’en-tête) :
email,firstName,lastName,username,password,roles
[email protected],Alice,Dupont,alice,,viewer
[email protected],Robert,Martin,bob,TempPass123,editorFormat JSON :
[
{
"email": "[email protected]",
"firstName": "Alice",
"lastName": "Dupont",
"roles": ["viewer"]
}
]Réponse de succès (job créé)
{
"ok": true,
"data": {
"jobId": "import_xyz789",
"status": "pending",
"totalRows": 142,
"createdAt": "2025-02-18T10:00:00Z"
}
}/api/users/importRequires: manage:usersListe tous les jobs d’import pour le tenant courant, triés par date de création décroissante.
Réponse de succès
{
"ok": true,
"data": {
"data": [
{
"id": "import_xyz789",
"fileName": "utilisateurs-2025-02.csv",
"format": "csv",
"status": "completed",
"totalRows": 142,
"processedRows": 142,
"successCount": 140,
"errorCount": 2,
"createdAt": "2025-02-18T10:00:00Z",
"completedAt": "2025-02-18T10:01:34Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 5, "totalPages": 1 }
}
}/api/users/import/[id]Requires: manage:usersObtenir le statut courant et les détails des erreurs d’un job d’import.
Réponse de succès
{
"ok": true,
"data": {
"id": "import_xyz789",
"status": "completed",
"totalRows": 142,
"processedRows": 142,
"successCount": 140,
"errorCount": 2,
"errors": [
{
"row": 45,
"email": "mauvais@",
"error": "Adresse email invalide"
},
{
"row": 98,
"email": "[email protected]",
"error": "Email déjà existant"
}
]
}
}Statuts du job d’import : pending, processing, completed, failed, partial.
Export Massif
/api/users/exportRequires: manage:usersLance un export utilisateurs. L’export est exécuté de manière asynchrone. Effectue un polling sur GET /api/users/export pour trouver le job, puis télécharge avec GET /api/users/export/[id]/download une fois le statut completed.
Corps de la requête
{
"format": "csv"
}format est "csv" ou "json".
Réponse de succès
{
"ok": true,
"data": {
"id": "export_abc123",
"status": "pending",
"format": "csv",
"createdAt": "2025-02-18T11:00:00Z"
}
}/api/users/exportRequires: manage:usersListe tous les jobs d’export.
/api/users/export/[id]/downloadRequires: manage:usersTélécharge le fichier d’export une fois que le statut du job est completed. Retourne le fichier binaire brut avec un header Content-Disposition approprié.
Les fichiers d’export sont stockés temporairement et expirent après 24 heures. Télécharge-les rapidement après la complétion du job.
Gestion du Numéro de Téléphone
Ces endpoints permettent aux utilisateurs authentifiés de gérer leur propre numéro de téléphone. Aucune permission spéciale n’est requise au-delà d’un access token valide.
/api/user/phone/setRequires: authenticated userDéfinit ou met à jour le numéro de téléphone de l’utilisateur authentifié. Après la définition, le numéro doit être vérifié en utilisant POST /api/user/phone/verify. Un SMS OTP est envoyé au numéro fourni.
Corps de la requête
{
"phoneNumber": "+33123456789"
}Le numéro de téléphone doit être au format E.164 (format international avec indicatif pays).
Réponse de succès
{
"ok": true,
"data": {
"sent": true,
"phoneNumber": "+33123456789"
}
}Codes d’erreur
| Code | HTTP | Description |
|---|---|---|
INVALID_PHONE | 400 | Le numéro n’est pas au format E.164 |
PHONE_TAKEN | 409 | Le numéro est déjà associé à un autre compte |
SMS_RATE_LIMITED | 429 | Trop de demandes SMS (max 5 par heure) |
/api/user/phone/verifyRequires: authenticated userVérifie le numéro de téléphone avec le code OTP reçu par SMS. En cas de succès, phoneNumberVerified est défini à true sur le compte utilisateur.
Corps de la requête
{
"code": "482910"
}Réponse de succès
{
"ok": true,
"data": { "verified": true }
}Codes d’erreur
| Code | HTTP | Description |
|---|---|---|
INVALID_OTP | 400 | Le code est incorrect |
OTP_EXPIRED | 400 | Le code est expiré (TTL : 10 minutes) |
MAX_ATTEMPTS | 400 | Tentatives de vérification maximales dépassées |
Authentification à Deux Facteurs
/api/user/2fa/sms/enableRequires: authenticated userActive SMS OTP comme méthode 2FA pour l’utilisateur authentifié. Nécessite un numéro de téléphone vérifié. Un OTP est envoyé pour confirmer que le téléphone peut recevoir des codes avant l’activation.
Corps de la requête
{
"code": "123456"
}Fournis l’OTP envoyé au numéro de téléphone vérifié de l’utilisateur.
Réponse de succès
{
"ok": true,
"data": { "smsEnabled": true }
}Codes d’erreur
| Code | HTTP | Description |
|---|---|---|
PHONE_NOT_VERIFIED | 400 | L’utilisateur n’a pas de numéro de téléphone vérifié |
INVALID_OTP | 400 | Le code de confirmation est incorrect |
/api/user/2fa/webauthn/enableRequires: authenticated userInitie la cérémonie d’enregistrement WebAuthn passkey pour activer WebAuthn comme méthode 2FA. Retourne un challenge d’enregistrement. Le client doit compléter la cérémonie en utilisant l’API WebAuthn du navigateur et envoyer l’AuthenticatorAttestationResponse à POST /api/user/2fa/webauthn/challenge.
Requête : Aucun corps requis.
Réponse de succès (options d’enregistrement)
{
"ok": true,
"data": {
"challenge": "challenge-base64url",
"rp": { "name": "Auris", "id": "api.altovar.net" },
"user": {
"id": "id-utilisateur-base64url",
"name": "[email protected]",
"displayName": "Alice Dupont"
},
"pubKeyCredParams": [{ "type": "public-key", "alg": -7 }],
"timeout": 60000,
"attestation": "none"
}
}Utilise la bibliothèque @simplewebauthn/browser pour gérer ce challenge dans le navigateur.
Pages Associées
- Gestion des Utilisateurs — Guide de gestion du cycle de vie des utilisateurs
- Import & Export — Migration massive d’utilisateurs via CSV/JSON
- Provisionnement SCIM 2.0 — Provisionnement automatique des utilisateurs
- Utilisateurs et Rôles — Gère les utilisateurs depuis la Console
- API Import & Export Utilisateurs — Endpoints d’import et export massif