> ## Documentation Index
> Fetch the complete documentation index at: https://translations.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Aprenda a migrar su código existente de Auth0 Rules a código de Auth0 Actions.

# Migrar de Rules a Actions

Al convertir Rules existentes a Actions, debe asociar la nueva Action al Trigger Post-Login (`post-login`) del flujo de inicio de sesión. Si sigue los pasos que se indican a continuación y mantiene sus Actions en el mismo orden que sus Rules originales, la funcionalidad debería ser idéntica.

<div id="plan-your-migration">
  ## Planifique su migración
</div>

Las Actions de Post-Login se ejecutan después de las Rules existentes, por lo que puede convertir las Rules una por una en el Dashboard o todas a la vez con la <Tooltip tip="Management API: Un producto que permite a los clientes realizar tareas administrativas." cta="Ver glosario" href="/es/docs/glossary?term=Management+API">Management API</Tooltip>.

Tendrá que convertir el código y, después, activar la Action y desactivar la Rule. Activar la Action y desactivar la Rule puede hacerse rápidamente una tras otra, pero, según el orden, podría haber un breve período en el que se estén ejecutando ambas o ninguna.

Por este motivo, recomendamos migrar su pipeline paso a paso: convierta partes del código de sus Rules en código de Action, haga pruebas en un entorno de ensayo y, después, pase a producción una parte cada vez. Como las Rules activas se ejecutan antes que las Actions desplegadas, si empieza por el final del pipeline de sus Rules y avanza hacia atrás, puede mantener parte de la lógica en Rules mientras crea y prueba otra lógica en Actions.

<Card title="Consejos para planificar su migración">
  * Mantenga una relación 1:1 entre sus Actions y Rules, para que la funcionalidad pueda activarse y desactivarse por bloques y ponerse a prueba.
  * Use indicadores en los metadatos del usuario para evitar duplicar operaciones costosas o de una sola ejecución.
  * Empiece por el final del pipeline de sus Rules y avance hacia atrás; como las Rules activas se ejecutan antes que las Actions desplegadas, puede mantener parte de la lógica en Rules mientras crea y prueba otra lógica en Actions.
  * Asegúrese de aplicar los cambios en un momento en que el impacto y el tráfico sean mínimos.
  * Considere [personalizar temporalmente su página de inicio de sesión](/es/docs/customize) para detener los inicios de sesión si el cambio pudiera causar inicios de sesión no válidos o brechas en la protección.
  * Considere usar [Auth0 Deploy CLI](/es/docs/deploy-monitor/deploy-cli-tool) para crear scripts, probar e implementar rápidamente la migración de una sola vez o de forma iterativa.
</Card>

<div id="understand-limitations">
  ## Entienda las limitaciones
</div>

Aunque Actions puede encargarse de la gran mayoría de las tareas que pueden realizar Rules, debe tener en cuenta algunas limitaciones antes de comenzar la migración. (Recuerde: puede tener tanto Rules como Actions ejecutándose mientras realiza la migración).

* Actions no proporciona [un token de acceso para la Management API](/es/docs/customize/rules/use-management-api) ni acceso al objeto global `auth0`, como sí ocurre con Rules. Para saber cómo se pueden seguir realizando llamadas a la Management API, consulte la sección [Convertir código](#convert-code).

Para ver la lista completa de limitaciones, consulte [Limitaciones de Actions](/es/docs/customize/actions/limitations).

<div id="convert-code">
  ## Convertir código
</div>

Para convertir una Rule en una Action, debe sustituir el código específico de Rules por código de Actions. En esta sección se describen las tareas que deberá realizar para convertir una Rule funcional en su Action equivalente.

<Card title="Consejos para convertir código">
  * En general, busque las propiedades de solo lectura de los objetos `user` y `context` de Rules en el objeto `event` de Actions. Busque en las funciones del objeto `api` cualquier efecto secundario que sus Actions tengan en el sistema (como hacer fallar un inicio de sesión o actualizar los metadatos del usuario).
  * Use el editor de código de Actions en el Auth0 Dashboard para escribir su código; le ayudará resaltando errores y ofreciendo sugerencias de autocompletado.
  * Antes de pasar a producción, [pruebe exhaustivamente sus nuevas Actions](/es/docs/customize/actions/test-actions) en un [entorno de ensayo o de prueba](/es/docs/get-started/auth0-overview/create-tenants/set-up-multiple-environments).
</Card>

<div id="copy-rule-code-to-a-new-action">
  ### Copiar el código de la Rule en una nueva Action
</div>

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Recomendamos copiar el código de su Rule en una nueva Action y usar el editor de código de Actions en el Auth0 Dashboard; esto le ayudará a identificar los problemas pendientes en su código.
</Callout>

1. Inicie sesión en su inquilino de producción y copie el código de la Rule que desea convertir.
2. Cambie a un inquilino de no producción y vaya a [Auth0 Dashboard > Actions > Library](https://manage.auth0.com/#/select-tenant?path=/actions/library).
3. Seleccione **Build Custom** y, a continuación:

   * Introduzca un **Name** para su Action que coincida con el nombre de la Rule que está convirtiendo.
   * Busque **Trigger** y seleccione **Login / Post Login**.
   * Busque **Runtime** y seleccione **Node 16.**
   * Seleccione **Create**.
4. En el bloque de código del editor de código de Actions, pegue debajo de la función exportada `onExecutePostLogin` el código de la Rule que desea convertir.
5. Realice los cambios detallados en el resto de este artículo a medida que incorpora el código en la función.

<div id="change-the-function-declaration">
  ### Cambie la declaración de la función
</div>

Las Rules usan una función declarada simple con los parámetros `user`, `context` y `callback`, mientras que las Actions usan una función exportada con un nombre específico. Realice el siguiente cambio; por ahora, ignore los errores que aparezcan.

**Antes**

```js lines theme={null}
async function myRulesFunction(user, context, callback) {
    // ... código adicional
}
```

**Después**

```js lines theme={null}
exports.onExecutePostLogin = async (event, api) => {
	// ... código adicional
};
```

<div id="change-how-user-data-is-accessed">
  ### Cambie la forma de acceder a los datos de usuario
</div>

En Rules, los datos del usuario que inicia sesión se almacenan en el [`user` object](/es/docs/customize/rules/user-object-in-rules). En Actions, estos datos se encuentran en la propiedad `user` del [`event` object](/es/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-event-object). La mayoría de las propiedades existentes están disponibles en esta nueva ubicación.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Los datos almacenados o modificados en propiedades del objeto `event` no están disponibles en otras Actions.
</Callout>

**Antes**

```javascript lines theme={null}
function myRulesFunction(user, context, callback) {
	const userEmail = user.email;
	const userId = user.user_id;

	// Esta propiedad podría ser undefined en Rules.
	const userAppMetadata = user.app_metadata || {};

	// ... código adicional
}
```

**Después**

```js lines theme={null}
exports.onExecutePostLogin = async (event, api) => {
	const userEmail = event.user.email;
	const userId = event.user.user_id;

	// Esta propiedad nunca será undefined en Actions.
	const userAppMetadata = event.user.app_metadata;

	// ... código adicional
};
```

<div id="change-how-context-data-is-accessed">
  ### Cambie cómo se accede a los datos de contexto
</div>

En Rules, los datos de la sesión de inicio de sesión actual se almacenan en el [`objeto context`](/es/docs/customize/rules/context-object). En Actions, estos datos se han reestructurado y trasladado al [`objeto event`](/es/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-event-object). Muchas de las propiedades se trasladaron tal cual, pero algunas se combinaron para mejorar la claridad.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Los datos almacenados o modificados en propiedades del objeto `event` no están accesibles desde otras Actions. Si su Rule desencadena una funcionalidad principal al establecer datos en estas propiedades, como `context.idToken` o `context.multifactor`, lea una de las secciones siguientes que aborda su caso de uso.
</Callout>

**Antes**

```javascript lines theme={null}
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;

	// ... código adicional
}
```

**Después**

```js lines theme={null}
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;

	// ... código adicional
};
```

<div id="convert-dependencies">
  ### Convertir dependencias
</div>

En las Rules, las dependencias se incluyen de una forma que exige indicar el número de versión en una instrucción `require`. Las Actions usan una sintaxis CommonJS más estándar y requieren que las versiones se indiquen fuera del editor de código.

En Rules, solo se permiten versiones concretas de paquetes concretos, y para agregar paquetes o versiones nuevos es necesario enviar una solicitud a Auth0. En Actions, puede usar `require` con cualquier paquete disponible en el registro de `npm`.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Si sus módulos de `npm` no están en la versión más reciente, este es un buen momento para actualizarlos.
</Callout>

1. Busque las instrucciones `require` dentro del código de su Rule.
2. Elimine los números de versión, pero anótelos.
3. Agregue la dependencia siguiendo los pasos de la sección "Add a Dependency" de [Write Your First Action](/es/docs/customize/actions/write-your-first-action) (si la dependencia no es un [módulo integrado de NodeJS](https://github.com/nodejs/node/tree/main/lib); si la dependencia es un módulo integrado de NodeJS, no necesita incluirla).
4. Mueva las instrucciones `require` encontradas fuera de la declaración `function`:

**Antes**

```javascript lines theme={null}
function myRulesFunction(user, context, callback) {
	const dependency = require("dependency@1.2.3");

	// ... código adicional
}
```

**Después**

```javascript lines theme={null}
const dependency = require("dependency"); // v1.2.3
exports.onExecutePostLogin = async (event, api) => {
	// ... código adicional
};
```

<div id="convert-callbacks">
  ### Convertir las devoluciones de llamada
</div>

Cuando un Rule termina de procesarse, debe llamar a la función `callback()` y pasar un error si el inicio de sesión falla. En cambio, Actions puede simplemente devolver en caso de éxito o llamar a un método de `api` con un mensaje si el inicio de sesión falla. Todas las instancias de `callback()` en un Rule deben eliminarse o sustituirse por `api.access.deny()` en caso de error. Tanto en Rules como en Actions, si el procesamiento debe detenerse por una condición específica, use una instrucción `return`.

**Antes**

```javascript lines theme={null}
function myRulesFunction(user, context, callback) {
	const userAppMetadata = user.app_metadata || {};
	if (userAppMetadata.condition === "success") {
		// Este Rule tuvo éxito, continuar con el siguiente Rule.
		return callback(null, user, context);
	}

	if (userAppMetadata.condition === "failure") {
		// Este Rule falló, detener el inicio de sesión con una respuesta de error.
		return callback(new Error("Failure message"));
	}

	// ... código adicional
}
```

**Después**

```js lines theme={null}
exports.onExecutePostLogin = async (event, api) => {
	if (event.user.app_metadata.condition === "success") {
		// Esta Action se realizó correctamente, continuar con la siguiente Action.
		return;
	}

	if (event.user.app_metadata.condition === "failure") {
		// Esta Action falló, detener el inicio de sesión con una respuesta de error.
		return api.access.deny("Failure message");
	}

	// ... código adicional
};
```

<div id="change-handling-of-secrets">
  ### Cambiar la gestión de los secretos
</div>

En Rules, los valores de configuración se establecen de forma global, lo que significa que todos los Rules pueden acceder a todos los valores secretos. (Para obtener más información, lea [Store Rule Configurations](/es/docs/customize/rules/configuration).) En Actions, los valores de configuración se establecen para cada Action individual. No puede acceder al valor secreto de una Action fuera del contexto de esa Action.

Para convertir secretos de Rules a Actions:

1. Guarde los valores necesarios para la Action específica en la que está trabajando.
2. Agregue un Secret para cada valor al que necesite acceder desde la Action. Para saber cómo hacerlo, lea la sección **Add a Secret** de [Write Your First Action](/es/docs/customize/actions/write-your-first-action).
3. Convierta su código:

**Antes**

```javascript lines theme={null}
function myRulesFunction (user, context, callback) {
  const { CLIENT_ID, CLIENT_SECRET } = configuration;

  // ... código adicional
}
```

**Después**

```js lines theme={null}
exports.onExecutePostLogin = async (event, api) => {
  const { CLIENT_ID, CLIENT_SECRET } = event.secrets;

  // ... código adicional
}
```

Al igual que con Rules, Auth0 cifra todos los valores secretos almacenados.

<div id="convert-custom-claims-in-tokens">
  ### Convertir claims personalizadas en los tokens
</div>

Tanto Rules como Actions pueden agregar claims personalizadas a los tokens de ID y a los <Tooltip tip="Token de acceso: credencial de autorización, en forma de una cadena opaca o un JWT, que se utiliza para acceder a una API." cta="Ver glosario" href="/es/docs/glossary?term=access+tokens">tokens de acceso</Tooltip>. En Rules, esto es una propiedad del objeto `context`, mientras que en Actions se usa un método del [objeto `api`](/es/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-api-object).

**Antes**

```javascript lines theme={null}
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;

	// ... código adicional
}
```

**Después**

```js lines theme={null}
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
	);

	// ... código adicional
};
```

<div id="convert-multi-factor-triggering">
  ### Convertir la activación de MFA
</div>

En Rules, la <Tooltip tip="Autenticación multifactor (MFA): proceso de autenticación del usuario que utiliza un factor adicional al username y la contraseña, como un code por SMS." cta="Ver glosario" href="/es/docs/glossary?term=multi-factor+authentication">autenticación multifactor</Tooltip> se puede activar modificando la propiedad `multifactor` del [objeto `context`](/es/docs/customize/rules/context-object). En Actions, esto se hace con un [método del objeto `api`](/es/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/post-login-api-object).

**Antes**

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

	// ... código adicional
}
```

**Después**

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

	// ... código adicional
};
```

<div id="convert-user-metadata-updates">
  ### Convertir las actualizaciones de metadatos de usuario
</div>

Para actualizar las propiedades `user_metadata` y `app_metadata` en Rules, es necesario hacer una llamada a la Management API, lo que puede provocar errores de [límite de tasa](/es/docs/troubleshoot/customer-support/operational-policies/rate-limit-policy/management-api-endpoint-rate-limits). Sin embargo, Actions permite indicar varios cambios en los metadatos de usuario y hacer una sola llamada a la Management API.

**Antes**

```javascript lines theme={null}
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));

	// ... código adicional
}
```

Si los Rules posteriores necesitan actualizar los metadatos del usuario, tendrían que llamar a la Management API por separado, lo que aumentaría la probabilidad de alcanzar el [límite de tasa](/es/docs/troubleshoot/customer-support/operational-policies/rate-limit-policy/management-api-endpoint-rate-limits).

**Después**

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

	// Nótese el uso de dos métodos diferentes aquí. 
	api.user.setAppMetadata("roles", userRolesUpdated);
	api.user.setUserMetadata("hasRoles", true);

	// ... código adicional
};
```

Si las Actions posteriores necesitaran actualizar los metadatos del usuario, tendrían que llamar a `api.user.setUserMetadata` o `api.user.setAppMetadata`. En Actions, varias llamadas a estas funciones desde una o varias Actions darán lugar a una sola llamada a la Management API una vez que se complete el flujo.

<div id="convert-other-management-api-calls">
  ### Convertir otras llamadas a la Management API
</div>

En general, no recomendamos llamar a la Management API desde una ruta crítica de alto tráfico, como Rules o Actions. Las solicitudes a todas las API de Auth0 [están sujetas a límites de tasa](/es/docs/troubleshoot/customer-support/operational-policies/rate-limit-policy), incluidas las llamadas desde puntos de extensibilidad, y llamar a una API en todos los inicios de sesión podría provocar fácilmente errores de inicio de sesión en momentos de mucho tráfico.

Sin embargo, si las llamadas son necesarias y están configuradas para evitar los límites de tasa, es posible llamar a la Management API desde Actions. Como se mencionó antes en la sección "Comprender las limitaciones" de este artículo, Actions no recibe un token de acceso para la Management API, por lo que deberá obtener un token de acceso antes de activar su Action:

1. [Registre una aplicación de máquina a máquina y autorícela para la Management API](/es/docs/get-started/auth0-overview/create-applications/machine-to-machine-apps).
2. Guarde el **ID de cliente** y el **Secreto del cliente** en la Action.
3. [Obtenga un token de acceso para la Management API](/es/docs/secure/tokens/access-tokens/management-api-access-tokens/get-management-api-access-tokens-for-production).
4. Llame a la Management API:

   <Warning>
     Actions no puede conservar datos entre ejecuciones, por lo que no es posible almacenar en caché el token de acceso durante ningún período de tiempo; dado que cada llamada a la Management API también requiere una llamada a la Authentication API, llamar a la Management API es una operación muy costosa.
   </Warning>

**Antes**

```javascript lines theme={null}
function myRulesFunction(user, context, callback) {
	const ManagementClient = require("auth0@2.9.1").ManagementClient; 
	const managementClientInstance = new ManagementClient({
		// Estos provienen de las variables globales integradas de Rules
		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);
			}

			// ... código adicional
		}
	);
}
```

**Después**

```javascript lines theme={null}
const auth0Sdk = require("auth0");
exports.onExecutePostLogin = async (event, api) => {
	const ManagementClient = auth0Sdk.ManagementClient;

	// Esto realizará una llamada a la Authentication API
	const managementClientInstance = new ManagementClient({
		// Estos provienen de una aplicación machine-to-machine
		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);
			}

			// ... código adicional
		}
	);
};
```

<div id="convert-redirects">
  ### Convertir redirecciones
</div>

Las Rules pueden redirigir a un usuario que está iniciando sesión a una página externa y luego esperar una respuesta. En este caso, todas las Rules anteriores a la redirección se ejecutarán dos veces: una antes de la redirección y otra cuando se reciba la respuesta. La lógica de la redirección y la de la respuesta suelen estar en la misma Rule.

En Actions, el pipeline se pausa cuando se produce la redirección y se reanuda cuando el usuario regresa. Además, la función exportada que activa la redirección está separada del callback de redirección.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Explicar cómo realizar correctamente todas las redirecciones en Actions queda fuera del alcance de esta guía. Para obtener información más detallada, consulte [Redirect with Actions](/es/docs/customize/actions/explore-triggers/signup-and-login-triggers/login-trigger/redirect-with-actions).
</Callout>

**Antes**

```javascript lines theme={null}
function myRulesFunction(user, context, callback) {
    if (context.protocol === "redirect-callback") {
        // El usuario fue redirigido al endpoint /continue
        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"
    ) {
        // El usuario no puede ser redirigido
        return callback(null, user, context);
    }
    // El usuario está iniciando sesión directamente
    if (!user.app_metadata.wasRedirected) {
        context.redirect = {
            url: "https://example.com",
        };
        callback(null, user, context);
    }
}
```

**Después**

```js lines theme={null}
exports.onExecutePostLogin = async (event, api) => {
    api.accessToken.setClaim("https://dev.TLD/wasRedirected", true)
```

<div id="convert-current-sso-clients-references">
  ### Convertir las referencias actuales de clientes SSO
</div>

El objeto `context.sso` de Rules proporciona información sobre la sesión actual y los clientes que la usan. Para obtener más información, consulta la entrada de `context.sso` en [Propiedades del objeto Context en Rules](/es/docs/customize/rules/context-object). En Actions, encontrarás información similar en el objeto `event.session`.

**Antes**

```javascript lines theme={null}
function (user, context, callback) {

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

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

  return callback(null, user, context);
}
```

**Después**

```js lines theme={null}
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(" ")); 
  }
};
```

<div id="complete-the-migration">
  ## Complete la migración
</div>

Una vez que haya escrito y probado el nuevo código de Actions, debe activar la Action y desactivar la Rule. Estas dos tareas pueden realizarse rápidamente una tras otra, pero, según el orden, podría haber un breve período en el que se ejecuten ambas o ninguna. Dado que las Rules activas se ejecutan antes que las Actions desplegadas, si comienza al final del pipeline de Rules y retrocede, puede mantener parte de la lógica en Rules mientras crea y prueba otra lógica en Actions.
