Migration des Règles vers les Actions

Lorsque vous convertissez des Règles existantes en Actions, vous devez associer la nouvelle action au déclencheur post-connexion (post-login) du flux de connexion Si vous suivez les étapes ci-dessous et que vous conservez vos Actions dans le même ordre que vos Règles d’origine, la fonctionnalité devrait être identique.

Planifier votre migration

Les Actions Post-connexion s’exécutent après les règles existantes. Vous pouvez donc convertir les règles individuellement dans le Dashboard ou en une seule fois à l’aide de Management API.

Vous devrez convertir le code, puis activer l’action et désactiver la règle. Vous pouvez activer l’action et désactiver la règle rapidement, successivement, mais en fonction de l’ordre, il se peut qu’il y ait un court laps de temps pendant lequel l’une ou l’autre ou aucune des deux actions n’est en cours d’exécution.

Pour cette raison, nous vous recommandons de migrer votre pipeline étape par étape : convertissez des éléments de votre code Règles en code Action, testez dans un environnement préproduction, puis passez à la production avec un élément à la fois. Comme les Règles actives s’exécutent avant les Actions déployées, si vous commencez par la fin de votre pipeline de règles et remontez vers le bas, vous pouvez conserver une partie de la logique dans les Règles pendant que vous élaborez et testez d’autres logiques dans les Actions.

Conseils pour la planification de la migration

  • Conservez vos Actions et vos Règles à l’échelle 1:1, de sorte que les fonctionnalités puissent être activées et désactivées par blocs et testées.

  • Utilisez des indicateurs dans les métadonnées de l’utilisateur pour éviter de dupliquer des opérations coûteuses ou ponctuelles.

  • Commencez par la fin de votre pipeline de règles et remontez vers le bas; comme les règles actives s’exécutent avant les actions déployées, vous pouvez conserver une partie de la logique dans les règles pendant que vous construisez et testez d’autres logiques dans les actions.

  • Veillez à effectuer les changements à un moment où l’impact et le traffic seront les plus faibles.

  • Envisagez de personnaliser votre page de connexion temporairement pour interrompre les ouvertures de session si la conversion risque d’entraîner des ouvertures de session non valides ou des lacunes dans la protection.

  • Envisagez d’utiliser l’outil Auth0 Deploy CLI afin de rédiger des scripts, de tester et de mettre en œuvre rapidement la migration en une seule fois ou de manière itérative.

Comprendre les limites

Bien que les Actions puissent gérer la grande majorité des tâches effectuées par les Règles, vous devez être conscient de certaines limites avant de commencer votre migration. (Rappelez-vous : les Règles et les Actions peuvent être en cours d’exécution pendant la migration).

Pour obtenir la liste complète des limitations, veuillez consulter la section Limitations des actions.

Conversion du code

Pour convertir une Règle en Action, vous devez remplacer le code spécifique à la Règle par le code de l’Action. Cette section couvre les tâches que vous devrez effectuer pour transformer une Règle fonctionnelle en une Action équivalente.

Conseils pour la conversion du code

  • En général, il faut rechercher les propriétés en lecture seule des objets de Rules (règles) user et context dans l’objet d’Actions event (événement). Recherchez les effets secondaires de vos Actions sur le système (comme l’échec d’une connexion ou la mise à jour des métadonnées de l’utilisateur) dans les fonctions d’objet api.

  • Utilisez l’Éditeur de code d’actions dans le Auth0 Dashboard pour écrire votre code; il vous aidera en mettant en évidence les erreurs et en fournissant des suggestions d’auto-remplissage.

  • Avant de mettre en ligne, vous devez soigneusement tester vos nouvelles Actions dans un environnement d’essai ou de test.

Copier le code de la Règle dans une nouvelle Action

  1. Connectez-vous à votre locataire de production et copiez le code de la Règle que vous souhaitez convertir.

  2. Passez à un locataire hors production et accédez à Auth0 Dashboard > Actions (Actions) > Library (Bibliothèque).

  3. Sélectionner Build Custom (Construire une action personnalisée), puis :

    • Saisissez un Name (Nom) pour votre action qui correspond au nom de la Règle que vous convertissez.

    • Rendez-vous à Trigger (Déclencheur) et sélectionnez Login / Post Login (Connexion/post-connexion).

    • Accédez à Durée d’exécution, et sélectionnez Node 22.

    • Sélectionnez Create (Créer).

  4. Dans le bloc de code de l’éditeur de code d’actions, collez le code de règle que vous souhaitez convertir sous la fonction exportée onExecutePostLogin.

  5. Apportez les modifications détaillées dans la suite de cet article à mesure que vous déplacez le code dans la fonction.

Modifier la déclaration de fonction

Les Règles utilisent une simple fonction déclarée avec des paramètres user, context, et callback tandis que les Actions utilisent une fonction exportée sous un nom particulier. Apportez la modification suivante; pour l’instant, ignorez les erreurs qui surviennent.

Avant

async function myRulesFunction(user, context, callback) {
    // ... additional code
}

Was this helpful?

/

Après

exports.onExecutePostLogin = async (event, api) => {
	// ... additional code
};

Was this helpful?

/

Modifier l’accès aux données utilisateur

Pour les Règles, les données relatives à l’utilisateur qui se connecte sont stockées dans l’objet user. Pour les Actions, ces données se trouvent dans la propriété user de l’objet event. La majorité des propriétés existantes sont accessibles dans ce nouvel emplacement.

Avant

function myRulesFunction(user, context, callback) {
	const userEmail = user.email;
	const userId = user.user_id;

	// This property could be undefined in Rules.
	const userAppMetadata = user.app_metadata || {};

	// ... additional code
}

Was this helpful?

/

Après

exports.onExecutePostLogin = async (event, api) => {
	const userEmail = event.user.email;
	const userId = event.user.user_id;

	// This property will never be undefined in Actions.
	const userAppMetadata = event.user.app_metadata;

	// ... additional code
};

Was this helpful?

/

Modifier l’accès aux données contextuelles

Pour les Règles, les données relatives à la session de connexion en cours sont stockées dans l’objet context. Pour les Actions, ces données ont été remodelées et déplacées vers l’objet event. De nombreuses propriétés ont été transférées telles quelles, tandis que d’autres ont été combinées pour plus de clarté.

Avant

function myRulesFunction(user, context, callback) {
	const clientId = context.clientID;
	const clientMetadata = context.clientMetadata || {};

	const connectionId = context.connectionID;
	const connectionMetadata = context.connectionMetadata || {};

	const protocol = context.protocol;

	const tenant = context.tenant;

	// ... additional code
}

Was this helpful?

/

Après

exports.onExecutePostLogin = async (event, api) => {
	const clientId = event.client.client_id;
	const clientMetadata = event.client.metadata;

	const connectionId = event.connection.id;
	const connectionMetadata = event.connection.metadata;

	const protocol = event.transaction.protocol;

	const tenant = event.tenant.id;

	// ... additional code
};

Was this helpful?

/

Convertir les dépendances

Les Règles comprennent des dépendances qui exigent la mention du numéro de version dans un énoncé require. Les Actions utilisent une syntaxe CommonJS plus classique et exigent que les versions soient indiquées en dehors de l’éditeur de code.

Pour les Règles, seules des versions spécifiques de certains packages sont autorisées, tandis que l’ajout de nouveaux packages et de nouvelles versions nécessite une demande auprès d’Auth0. Pour les Actions, vous pouvez exiger n’importe quel package figurant dans le registre npm.

  1. Rechercher les déclarations require dans le code de votre Règle.

  2. Supprimez les numéros de version, après les avoir notés.

  3. Ajoutez la dépendance en suivant les étapes de la section « Ajouter une dépendance » de Write Your First Action (Programmer votre première Action) (si la dépendance n’est pas un module de base NodeJS; si la dépendance est un module NodeJS de base, vous n’avez pas besoin de l’inclure).

  4. Déplacez les déclarations require que vous avez trouvées en dehors de la déclaration function.

Avant

function myRulesFunction(user, context, callback) {
	const dependency = require("dependency@1.2.3");

	// ... additional code
}

Was this helpful?

/

Après

const dependency = require("dependency"); // v1.2.3
exports.onExecutePostLogin = async (event, api) => {
	// ... additional code
};

Was this helpful?

/

Convertir les rappels

Une fois la Règle traitée, elle doit appeler la fonction callback() et transmettre une erreur en cas d’échec de la connexion. Inversement, les Actions peuvent renvoyer un message de réussite ou appeler une méthode api avec un message en cas d’échec de la connexion. Toutes les instances de callback() dans une Règle doivent être supprimées ou remplacées par api.access.deny() en cas d’échec. Utilisez une déclaration return pour les Règles et les Actions, si le traitement doit s’arrêter pour une raison particulière.

Avant

function myRulesFunction(user, context, callback) {
	const userAppMetadata = user.app_metadata || {};
	if (userAppMetadata.condition === "success") {
		// This Rule succeeded, proceed with next Rule.
		return callback(null, user, context);
	}

	if (userAppMetadata.condition === "failure") {
		// This Rule failed, stop the login with an error response.
		return callback(new Error("Failure message"));
	}

	// ... additional code
}

Was this helpful?

/

Après

exports.onExecutePostLogin = async (event, api) => {
	if (event.user.app_metadata.condition === "success") {
		// This Action succeeded, proceed with next Action.
		return;
	}

	if (event.user.app_metadata.condition === "failure") {
		// This Action failed, stop the login with an error response.
		return api.access.deny("Failure message");
	}

	// ... additional code
};

Was this helpful?

/

Modifier la gestion des secrets

Pour les Règles, vous définissez les valeurs de configuration de manière globale, ce qui signifie que toutes les Règles peuvent accéder à toutes les valeurs secrètes. (Pour en savoir plus, veuillez consulter Configurations de règles de stockage.) Pour les Actions, vous devez définir des valeurs de configuration pour chaque Action individuelle. Vous ne pourrez accéder à la valeur secrète d’une Action en dehors du contexte de l’Action.

Pour convertir les secrets des Règles en Actions :

  1. Enregistrez les valeurs nécessaires à l’action spécifique sur laquelle vous travaillez.

  2. Ajoutez un secret pour chaque valeur à laquelle vous devez accéder à l’intérieur de l’action. Pour en savoir plus, consultez la section Ajouter un secret dans Programmer votre première Action.

  3. Convertir votre code :

Avant

function myRulesFunction (user, context, callback) {
  const { CLIENT_ID, CLIENT_SECRET } = configuration;

  // ... additional code
}

Was this helpful?

/

Après

exports.onExecutePostLogin = async (event, api) => {
  const { CLIENT_ID, CLIENT_SECRET } = event.secrets;

  // ... additional code
}

Was this helpful?

/

Comme pour les Règles, Auth0 chiffre toutes les valeurs secrètes au repos.

Convertir les revendications personnalisées en jetons

Les Règles et les Actions permettent toutes deux d’ajouter des demandes personnalisées aux jetons d’ID et d’accès. Pour les Règles, il s’agit d’une propriété de l’objet context tandis que les Actions utilisent une méthode de l’objet api.

Avant

function myRulesFunction(user, context, callback) {
	const userAppMetadata = user.app_metadata || {};
	const namespace = "https://namespace/";

	context.idToken[`${namespace}/emp_id`] = userAppMetadata.emp_id;
	context.accessToken[`${namespace}/emp_id`] = userAppMetadata.emp_id;

	// ... additional code
}

Was this helpful?

/

Après

exports.onExecutePostLogin = async (event, api) => {
	const namespace = "https://namespace/";

	api.idToken.setCustomClaim(
		`${namespace}/emp_id`, 
		event.user.app_metadata.emp_id
	); 		   

	api.accessToken.setCustomClaim(
		`${namespace}/emp_id`, 
		event.user.app_metadata.emp_id
	);

	// ... additional code
};

Was this helpful?

/

Convertir le déclenchement multifacteur

Pour les Règles, l’authentification multifacteur (MFA) peut être déclenchée en modifiant la propriété multifacteur de l’objet context. Dans les Actions, cela se fait avec une méthode sur l’objet api.

Avant

function myRulesFunction(user, context, callback) {
	if (user.app_metadata.needs_mfa === true) {
		context.multifactor = { 
			provider: "any", 
			allowRememberBrowser: false,
		};
	}

	// ... additional code
}

Was this helpful?

/

Après

exports.onExecutePostLogin = async (event, api) => {
	if (event.user.app_metadata.needs_mfa === true) {
		api.multifactor.enable("any", { allowRememberBrowser: false });
	}

	// ... additional code
};

Was this helpful?

/

Convertir les mises à jour des métadonnées utilisateur

La mise à jour user_metadata et app_metadata dans les Règles requiert un appel à Management API, ce qui peut entraîner des erreurs de limite anti-attaques. Les actions, en revanche, permettent d’indiquer plusieurs modifications de métadonnées utilisateur en n’appelant Management API qu’une seule fois.

Avant

function myRulesFunction(user, context, callback) {
	user.app_metadata = user.app_metadata || {}; 
	user.app_metadata.roles = user.app_metadata.roles || [];
	user.app_metadata.roles.push("administrator"); 

	auth0.users
		.updateAppMetadata(user.user_id, user.app_metadata) 
		.then(() => callback(null, user, context))
		.catch((err) => callback(err));

	// ... additional code
}

Was this helpful?

/

Si les Règles suivantes doivent mettre à jour les métadonnées utilisateur, elles devront appeler Management API séparément, augmentant ainsi le risque de dépasser la limite anti-attaques.

Après

exports.onExecutePostLogin = async (event, api) => {
	const userRolesUpdated = event.user.app_metadata.roles || [];
	userRolesUpdated.push("administrator"); 

	// Note the two different methods here. 
	api.user.setAppMetadata("roles", userRolesUpdated);
	api.user.setUserMetadata("hasRoles", true);

	// ... additional code
};

Was this helpful?

/

Si les Actions suivantes doivent mettre à jour les métadonnées utilisateur, elles devront appeler api.user.setUserMetadata ou api.user.setAppMetadata. Dans les Actions, les appels multiples à ces fonctions dans le cadre d’une ou de plusieurs Actions se traduiront par un appel unique à Management API une fois le flux terminé.

Convertir d’autres appels de Management API

De manière générale, nous vous déconseillons d’appeler Management API à partir d’un chemin critique à fort trafic comme les Règles ou les Actions. Toutes les demandes adressées aux API Auth0 sont soumises à la limite anti-attaques, y compris les appels émis par les points d’extension. Le fait d’appeler une API pour chaque connexion pourrait facilement entraîner des échecs de connexion pendant les périodes de forte affluence.

Cependant, si les appels sont nécessaires et sont configurés pour éviter les limites anti-attaques, il est possible d’appeler Management API à partir des Actions. Comme indiqué dans la section « Comprendre les limites » plus haut dans cet article, les Actions ne sont pas fournies avec un jeton d’accès pour Management API, vous devrez donc obtenir un jeton d’accès avant d’activer votre Action :

  1. Enregistrer une application de communication entre machines et autorisez-la à utiliser Management API.

  2. Enregistrer le Client ID (ID Client) et Client Secret (Secret du client) dans l’Action.

  3. Obtenir un jeton d’accès pour Management API.

  4. Appelez Management API :

Avant

function myRulesFunction(user, context, callback) {
	const ManagementClient = require("auth0@2.9.1").ManagementClient; 
	const managementClientInstance = new ManagementClient({
		// These come from built-in Rules globals
		token: auth0.accessToken, 
		domain: auth0.domain,
	}); 

	managementClientInstance.users.assignRoles(
		{ id: user.user_id }, 
		{ roles: ["ROLE_ID_TO_ADD"] }, 
		(error, user) => {
			if (error) {
				return callback(error);
			}

			// ... additional code
		}
	);
}

Was this helpful?

/

Après

const auth0Sdk = require("auth0");
exports.onExecutePostLogin = async (event, api) => {
	const ManagementClient = auth0Sdk.ManagementClient;

	// This will make an Authentication API call
	const managementClientInstance = new ManagementClient({
		// These come from a machine-to-machine application
		domain: event.secrets.M2M_DOMAIN,
		clientId: event.secrets.M2M_CLIENT_ID,
		clientSecret: event.secrets.M2M_CLIENT_SECRET,
		scope: "update:users"
	});

	managementClientInstance.users.assignRoles(
		{ id: event.user.user_id }, 
		{ roles: ["ROLE_ID_TO_ADD"]}, 
		(error, user) => {
			if (error) {
				return api.access.deny(error.message);
			}

			// ... additional code
		}
	);
};

Was this helpful?

/

Convertir les redirections

Les Règles peuvent rediriger un utilisateur qui se connecte vers une page externe, puis attendre une réponse. Dans ce cas, toutes les règles précédant la redirection seront exécutées deux fois : une fois avant la redirection et une fois lors de la réponse. La logique de la redirection et de la réponse est généralement contenue dans la même Règle.

Dans les Actions, le pipeline d’actions est interrompu lors de la redirection et reprend lorsque l’utilisateur revient. Par ailleurs, la fonction de déclenchement de la redirection exportée est distincte de la fonction de rappel de la redirection.

Avant

function myRulesFunction(user, context, callback) {
    if (context.protocol === "redirect-callback") {
        // User was redirected to the /continue endpoint
        user.app_metadata.wasRedirected = true;
        return callback(null, user, context);
    } else if (
        context.protocol === "oauth2-password" ||
        context.protocol === "oauth2-refresh-token" ||
        context.protocol === "oauth2-resource-owner"
    ) {
        // User cannot be redirected
        return callback(null, user, context);
    }
    // User is logging in directly
    if (!user.app_metadata.wasRedirected) {
        context.redirect = {
            url: "https://example.com",
        };
        callback(null, user, context);
    }
}

Was this helpful?

/

Après

exports.onExecutePostLogin = async (event, api) => {
    api.accessToken.setClaim("https://dev.TLD/wasRedirected", true)

Was this helpful?

/

Convertir les références de clients SSO actuels

L’objet de la Règle context.sso fournit des détails sur la session active et les clients qui l’utilisent. Pour en savoir plus, consultez l’entrée context.sso dans les Propriétés de l’objet contexte dans les règles. Vous trouverez des données comparables dans l’objet Actions, events.session.

Avant

function (user, context, callback) {

  const clients = context.sso?.current_clients ?? []; 

  if (clients.length > 0) { 
	context.idToken.clients = clients.join(" "); 
  }

  return callback(null, user, context);
}

Was this helpful?

/

Après

exports.onExecutePostLogin = async (event, api) => {
  const clients = event?.session?.clients ?? []; 

  if (clients.length > 0) { 
    api.idToken.setCustomClaim('clients', clients.map(c=> c?.client_id).join(" ")); 
  }
};

Was this helpful?

/

Achever la migration

Une fois que votre nouveau code d’action a été écrit et testé, vous devez activer l’action et désactiver la règle. Vous pouvez effectuer ces deux tâches rapidement et successivement, mais en fonction de l’ordre, il se peut qu’il y ait un court laps de temps pendant lequel l’une ou l’autre ou aucune des deux actions n’est en cours d’exécution. Comme les Règles actives s’exécutent avant les Actions déployées, si vous commencez par la fin de votre pipeline de règles et remontez vers le bas, vous pouvez conserver une partie de la logique dans les Règles pendant que vous élaborez et testez d’autres logiques dans les Actions.