Skip to Content

API Actions Engine

Les Actions sont des snippets de code JavaScript personnalisé qui s’exécutent à des points spécifiques pendant les flux d’authentification. Elles permettent d’étendre Auris avec une logique personnalisée sans modifier la plateforme core : enrichir les tokens avec des données externes, bloquer les inscriptions suspectes, appliquer des politiques de mots de passe personnalisées ou synchroniser les données utilisateur avec des systèmes externes.

Les Actions sont exécutées dans un environnement sandboxé avec une portée limitée. Chaque action est associée à un point de déclenchement (ex. post_login) et est exécutée par ordre de priorité. Plusieurs actions peuvent être associées au même déclencheur.

Tous les endpoints des actions nécessitent le header x-tenant. La création et gestion des actions nécessite un accès niveau admin (impliqué par la permission admin:all ou la permission manage:actions).

Cycle de Vie d’une Action

  1. Crée une action avec un type de déclencheur et du code JavaScript.
  2. Teste l’action en examinant les logs d’exécution.
  3. Définis le statut de l’action sur active pour l’activer en production.
  4. Surveille l’exécution via l’endpoint des logs.

CRUD Actions

Lister les Actions

GET/api/actionsRequires: manage:actions

Liste toutes les actions pour le tenant. Retourne les métadonnées de l’action incluant le type de déclencheur, le statut, les statistiques d’exécution et l’ordre. Les actions sont exécutées par ordre ascendant du champ order pour chaque type de déclencheur.

Paramètres de query

ParamètreTypeDescription
pageintegerNuméro de page (défaut : 1)
limitintegerÉléments par page (défaut : 20)
triggerstringFiltre par type de déclencheur (ex. post_login)
statusactive | inactiveFiltre par statut

Réponse de succès

{ "ok": true, "data": { "data": [ { "id": "act_abc123", "name": "Enrichir Token avec Données CRM", "trigger": "post_login", "status": "active", "order": 1, "timeout": 5000, "executionCount": 14523, "errorCount": 12, "lastExecutedAt": "2025-02-18T09:50:00Z", "createdAt": "2025-01-10T10:00:00Z", "updatedAt": "2025-02-15T14:00:00Z" } ], "pagination": { "page": 1, "limit": 20, "total": 5, "totalPages": 1 } } }

Créer une Action

POST/api/actionsRequires: manage:actions

Crée une nouvelle action. L’action est créée avec le statut inactive par défaut. Définis-la sur active via l’endpoint de toggle après les tests. Le code JavaScript est validé pour les patterns bloqués avant le stockage.

Corps de la requête

{ "name": "Enrichir Token avec Données CRM", "trigger": "post_login", "code": "async function handler(context, api) {\n const response = await api.fetch('https://crm.example.com/api/user', {\n headers: { 'X-User-Email': context.user.email }\n });\n const crmData = await response.json();\n api.setCustomClaim('crm_id', crmData.id);\n api.setCustomClaim('account_tier', crmData.tier);\n}", "order": 1, "timeout": 5000 }
ChampTypeObligatoireDescription
namestringOuiNom lisible par l’utilisateur
triggerstringOuiPoint de déclenchement (voir Types de Déclencheurs)
codestringOuiCorps de la fonction JavaScript
orderintegerNonOrdre d’exécution dans le déclencheur (défaut : 0, plus petit = premier)
timeoutintegerNonTemps d’exécution maximum en millisecondes (défaut : 5000, max : 10000)

Réponse de succès

{ "ok": true, "data": { "id": "act_ghi789", "name": "Enrichir Token avec Données CRM", "trigger": "post_login", "status": "inactive", "code": "async function handler(context, api) { ... }", "order": 1, "timeout": 5000, "executionCount": 0, "errorCount": 0, "createdAt": "2025-02-18T10:00:00Z" } }

Codes d’erreur

CodeHTTPDescription
VALIDATION_ERROR400Champs obligatoires manquants ou type de déclencheur invalide
BLOCKED_PATTERN400Le code contient un pattern bloqué (voir Restrictions Sandbox)
CODE_TOO_LARGE400Le code dépasse la taille maximale autorisée

Récupérer une Action

GET/api/actions/[id]Requires: manage:actions

Récupère une seule action par ID, incluant le code complet et les statistiques d’exécution.

Mettre à Jour une Action

PUT/api/actions/[id]Requires: manage:actions

Met à jour le nom, le code, le déclencheur, l’ordre ou le timeout d’une action. Tous les champs sont optionnels — seuls les champs fournis sont mis à jour. Le code mis à jour est re-validé pour les patterns bloqués.

Corps de la requête

{ "name": "Enrichir Token avec Données CRM v2", "code": "async function handler(context, api) {\n // Logique mise à jour\n const data = await api.fetch('https://crm.example.com/v2/user/' + context.user.id);\n const user = await data.json();\n api.setCustomClaim('crm_id', user.id);\n}", "timeout": 8000 }

Supprimer une Action

DELETE/api/actions/[id]Requires: manage:actions

Supprime une action définitivement. L’action est immédiatement retirée de la pipeline d’exécution. Les logs d’exécution pour cette action sont conservés.

Réponse de succès

{ "ok": true, "data": { "deleted": true } }

Activer/Désactiver une Action

PATCH/api/actions/[id]Requires: manage:actions

Bascule une action entre l’état active et inactive. Seules les actions actives sont exécutées pendant les flux d’authentification.

Corps de la requête

{ "status": "active" }

Valeurs valides : active, inactive.

Réponse de succès

{ "ok": true, "data": { "id": "act_abc123", "status": "active", "updatedAt": "2025-02-18T11:30:00Z" } }

Logs d’Exécution

GET/api/actions/[id]/logsRequires: manage:actions

Récupère les logs d’exécution pour une action spécifique. Chaque entrée de log enregistre si l’exécution a réussi ou échoué, la durée et les messages d’erreur. Les logs sont triés par timestamp en ordre décroissant.

Paramètres de query

ParamètreTypeDescription
pageintegerNuméro de page (défaut : 1)
limitintegerÉléments par page (défaut : 20)

Réponse de succès

{ "ok": true, "data": { "data": [ { "id": "log_abc123", "actionId": "act_abc123", "trigger": "post_login", "status": "success", "duration": 234, "userId": "usr_xyz789", "createdAt": "2025-02-18T09:50:00Z" }, { "id": "log_def456", "actionId": "act_abc123", "trigger": "post_login", "status": "error", "duration": 5001, "error": "Action expirée après 5000ms", "userId": "usr_abc123", "createdAt": "2025-02-18T09:48:00Z" } ], "pagination": { "page": 1, "limit": 20, "total": 14535, "totalPages": 727 } } }

Valeurs de statut du log : success, error.

Types de Déclencheurs

Les Actions peuvent être associées à l’un des six points de déclenchement dans la pipeline d’authentification :

DéclencheurSe déclenche quandCas d’usage
pre_loginAvant que l’authentification soit tentéeBloquer la connexion depuis des IP ou domaines email spécifiques, rate limiting personnalisé
post_loginAprès l’authentification réussie, avant l’émission des tokensEnrichir les tokens avec des données externes, logs analytics personnalisés, synchroniser avec CRM
pre_signupAvant la création d’un nouveau compte utilisateurBloquer les emails jetables, appliquer une validation personnalisée, vérifier des blocklists externes
post_signupAprès la création d’un nouveau compte utilisateurEnvoyer une notification de bienvenue, créer des enregistrements dans des systèmes externes, assigner des rôles par défaut
post_change_passwordAprès qu’un utilisateur change son mot de passeInvalider les credentials en cache, notifier les systèmes externes, log d’audit
pre_m2m_tokenAvant l’émission d’un token M2MValider les scopes client, ajouter des claims personnalisés, appliquer des restrictions horaires

Ordre d’Exécution

Quand plusieurs actions actives partagent le même déclencheur, elles sont exécutées en séquence par ordre ascendant de la valeur order. Si une action échoue (lance une erreur ou expire), les actions suivantes pour ce déclencheur sont quand même exécutées, sauf si l’action échouée nie explicitement la requête.

Objet ActionContext

Chaque action reçoit un objet context comme premier argument. La forme varie selon le type de déclencheur.

pre_login / post_login

{ user: { id: "usr_abc123", email: "[email protected]", username: "alice", firstName: "Alice", lastName: "Martin", roles: ["editor", "viewer"], emailVerified: true, phoneNumber: "+33612345678", phoneNumberVerified: true, metadata: {} }, connection: { method: "password", // "password" | "magic_link" | "social" | "sso" provider: null, // nom du social provider (ex. "google") ou null ipAddress: "203.0.113.50", userAgent: "Mozilla/5.0 ...", timestamp: "2025-02-18T10:00:00Z" }, tenant: "acme-corp" }

Pour pre_login, l’objet user peut être null si l’utilisateur n’a pas encore été résolu (ex. email incorrect). connection.method et connection.ipAddress sont toujours disponibles.

pre_signup / post_signup

{ user: { email: "[email protected]", username: "nouvelutilisateur", firstName: "Nouveau", lastName: "Utilisateur" }, connection: { method: "password", ipAddress: "203.0.113.50", userAgent: "Mozilla/5.0 ...", timestamp: "2025-02-18T10:00:00Z" }, tenant: "acme-corp" }

Pour post_signup, l’objet user inclut également id et roles.

post_change_password

{ user: { id: "usr_abc123", email: "[email protected]" }, tenant: "acme-corp" }

pre_m2m_token

{ application: { id: "app_xyz789", name: "Service Backend", clientId: "m2m-client-id", type: "M2M" }, requestedScopes: ["read:users", "manage:roles"], tenant: "acme-corp" }

Objet ActionResult (API)

Le second argument passé aux actions est l’objet api, qui fournit des méthodes pour influencer le flux d’authentification :

MéthodeDisponible dansDescription
api.setCustomClaim(key, value)post_login, pre_m2m_tokenAjoute un claim personnalisé à l’access token
api.setMetadata(key, value)post_login, post_signupDéfinit les métadonnées utilisateur (persistées en base de données)
api.deny(reason)pre_login, pre_signup, pre_m2m_tokenNie la tentative d’authentification avec une raison
api.log(message)Tous les déclencheursÉcrit un message dans le log d’exécution de l’action
api.fetch(url, options)Tous les déclencheursEffectue une requête HTTP (fetch avec timeout limité)

Exemple : Bloquer l’Inscription pour Emails Jetables

async function handler(context, api) { const disposableDomains = ['tempmail.com', 'throwaway.email', 'guerrillamail.com']; const domain = context.user.email.split('@')[1]; if (disposableDomains.includes(domain)) { api.deny('Les adresses email jetables ne sont pas autorisées'); return; } api.log('Inscription autorisée pour le domaine : ' + domain); }

Exemple : Enrichir le Token après la Connexion

async function handler(context, api) { try { const response = await api.fetch('https://crm.example.com/api/lookup', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer crm-api-key' }, body: JSON.stringify({ email: context.user.email }) }); if (response.ok) { const data = await response.json(); api.setCustomClaim('crm_id', data.customerId); api.setCustomClaim('plan', data.subscriptionPlan); api.log('Token enrichi : plan=' + data.subscriptionPlan); } else { api.log('Recherche CRM échouée : ' + response.status); } } catch (error) { api.log('Erreur recherche CRM : ' + error.message); // Ne pas nier la connexion si l'enrichissement échoue } }

Exemple : Bloquer les Tokens M2M en Dehors des Heures de Travail

async function handler(context, api) { var hour = new Date().getUTCHours(); if (hour < 6 || hour > 22) { api.deny('Les tokens M2M ne peuvent pas être émis en dehors des heures de travail (06:00-22:00 UTC)'); return; } api.log('Token M2M émis pour ' + context.application.name + ' à l\'heure UTC ' + hour); }

Restrictions Sandbox

Les Actions sont exécutées dans un environnement sandboxé avec une portée limitée. Les patterns suivants sont détectés et bloqués lors de la validation du code (pendant la création et la mise à jour). Le code contenant l’un de ces patterns est rejeté avec une erreur BLOCKED_PATTERN :

  • require( — aucun import de modules CommonJS
  • import — aucun import de modules ES
  • process. — aucun accès à l’objet process Node.js
  • child_process — aucune exécution de shell
  • fs. / fs/promises — aucun accès au système de fichiers
  • global. / globalThis. — aucun accès à la portée globale
  • Patterns d’évaluation dynamique du code — aucune génération de code à runtime depuis des chaînes

La méthode api.fetch() est fournie comme alternative sécurisée aux bibliothèques HTTP externes. Elle supporte les méthodes GET, POST, PUT, PATCH et DELETE avec un body JSON ou texte. Le timeout est hérité du paramètre timeout de l’action.

Limites de Runtime

LimiteValeur
Temps d’exécution maximumConfigurable par action (défaut 5000ms, max 10000ms)
Taille maximale du code64 Ko
Taille maximale de réponse api.fetch()1 Mo
Globaux disponiblesJSON, Date, Math, String, Number, Array, Object, Map, Set, Promise, RegExp, console.log (redirigé vers api.log)

Gestion des Erreurs

Quand une action lance une erreur non gérée ou expire :

  1. L’erreur est enregistrée dans le log d’exécution de l’action.
  2. Le errorCount sur l’action est incrémenté.
  3. Le flux d’authentification continue (les actions ne bloquent pas l’auth par défaut sauf si api.deny() est appelé).
  4. Si l’action est critique, utilise api.deny() explicitement dans ton gestionnaire d’erreurs.

Les erreurs des actions ne bloquent pas l’authentification par défaut. Si tu as besoin qu’une action échouée empêche la connexion (ex. un contrôle de conformité), tu dois appeler api.deny() explicitement dans ton bloc catch. Sinon, l’utilisateur sera authentifié même si l’action échoue.

Éditeur Visuel Blueprint

La Console Auris inclut un éditeur visuel à nœuds (Blueprint Editor) pour créer des actions via une interface drag-and-drop plutôt qu’en écrivant du JavaScript. Le Blueprint Editor génère des définitions de règles JSON qui sont compilées en JavaScript équivalent à runtime.

Le Blueprint Editor est une alternative à l’éditeur de code — les deux produisent le même résultat. Les actions créées avec le Blueprint Editor peuvent être visualisées et modifiées en code et vice versa.

Consulte la documentation de la Console pour les détails sur le Blueprint Editor.


Pages Associées