> ## 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 usar Hooks con el punto de extensibilidad Client Credentials Exchange, que está disponible para conexiones de base de datos y conexiones sin contraseña.

# Intercambio de credenciales de cliente

<Warning>
  La fecha de fin de vida útil (EOL) de Rules y Hooks será el **18 de noviembre de 2026**, y ya no están disponibles para los nuevos inquilinos creados a partir del **16 de octubre de 2023**. Los inquilinos existentes con Hooks activos conservarán el acceso al producto Hooks hasta su fin de vida útil.

  Le recomendamos encarecidamente que use Actions para extender Auth0. Con Actions, tiene acceso a información de tipos enriquecida, documentación integrada y paquetes públicos de `npm`, y puede conectar integraciones externas que mejoran su experiencia general de extensibilidad. Para obtener más información sobre lo que ofrece Actions, lea [Understand How Auth0 Actions Work](/es/docs/customize/actions/actions-overview).

  Para ayudarle con la migración, ofrecemos guías que le ayudarán a [migrar de Rules a Actions](/es/docs/customize/actions/migrate/migrate-from-rules-to-actions) y [migrar de Hooks a Actions](/es/docs/customize/actions/migrate/migrate-from-hooks-to-actions). También contamos con una página específica de [Move to Actions](https://auth0.com/extensibility/movetoactions) que destaca comparaciones de funcionalidades, [una demostración de Actions](https://www.youtube.com/watch?v=UesFSY1klrI) y otros recursos para ayudarle en su proceso de migración.

  Para obtener más información sobre la deprecación de Rules y Hooks, lea nuestra entrada de blog: [Preparing for Rules and Hooks End of Life](https://auth0.com/blog/preparing-for-rules-and-hooks-end-of-life/).
</Warning>

En el punto de extensibilidad Client Credentials Exchange, Hooks le permiten ejecutar acciones personalizadas cuando se emite un <Tooltip tip="Token de acceso: credencial de autorización, en forma de una cadena opaca o JWT, que se utiliza para acceder a una API." cta="Ver glosario" href="/es/docs/glossary?term=Access+Token">Token de acceso</Tooltip> a través del endpoint [`POST /oauth/token` de la API de autenticación](https://auth0.com/docs/api/authentication#client-credentials-flow) mediante el flujo de credenciales de cliente. Por ejemplo, puede impedir que se emita el token, agregar claims personalizados al token de acceso o modificar sus alcances. Para obtener más información, lea [Client Credentials Flow](/es/docs/get-started/authentication-and-authorization-flow/client-credentials-flow).

Los Hooks en este punto de extensibilidad son bloqueantes (sincrónicos), lo que significa que se ejecutan como parte del proceso del activador e impiden que el resto del flujo de Auth0 continúe hasta que el Hook se complete.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  El `triggerId` del punto de extensibilidad Client Credentials Exchange es `credentials-exchange`. Para aprender a crear Hooks para este punto de extensibilidad, lea [Create Hooks](/es/docs/customize/hooks/create-hooks).
</Callout>

Para conocer otros puntos de extensibilidad, lea Puntos de extensibilidad.

<div id="starter-code-and-parameters">
  ## Código de ejemplo inicial y parámetros
</div>

Al crear un Hook que se ejecuta en el punto de extensibilidad Client Credentials Exchange, puede resultarle útil el siguiente código de ejemplo inicial. Los parámetros que se pueden pasar a la función Hook y usar en ella se enumeran al principio del ejemplo de código.

```javascript lines expandable theme={null}
/**
@param {object} client - información del cliente
@param {string} client.name - nombre del cliente
@param {string} client.id - ID de cliente
@param {string} client.tenant - nombre del tenant de Auth0
@param {object} client.metadata - metadatos del cliente
@param {array|undefined} scope - un array de cadenas que representan el claim scope del token, o undefined
@param {string} audience - claim de audiencia del token
@param {object} context - información de contexto de Auth0
@param {object} context.webtask - contexto del Hook (webtask)
@param {function} cb - function (error, accessTokenClaims)
*/

module.exports = function(client, scope, audience, context, cb) {
  var access_token = {};
  access_token.scope = scope; // no eliminar esta línea

  // Modificar alcances o agregar claims adicionales
  // access_token['https://example.com/claim'] = 'bar';
  // access_token.scope.push('extra');

  // Denegar el token y responder con una respuesta de error OAuth2
  // if (denyExchange) {
  //   // Para devolver un HTTP 400 con { "error": "invalid_scope", "error_description": "Not authorized for this scope." }
  //   return cb(new InvalidScopeError('Not authorized for this scope.'));
  //
  //   // Para devolver un HTTP 400 con { "error": "invalid_request", "error_description": "Not a valid request." }
  //   return cb(new InvalidRequestError('Not a valid request.'));
  //
  //   // Para devolver un HTTP 500 con { "error": "server_error", "error_description": "A server error occurred." }
  //   return cb(new ServerError('A server error occurred.'));
  // }

  cb(null, access_token);
};
```

Tenga en cuenta lo siguiente:

* La función callback (`cb`) al final del código de ejemplo indica que la ejecución ha finalizado y debe incluirse.

* La línea `access_token.scope = scope` garantiza que todos los alcances concedidos estén presentes en el token de acceso. Si la elimina, se restablecerán todos los alcances y el token incluirá solo los alcances que agregue con el script.

<div id="default-response">
  ### Respuesta predeterminada
</div>

Cuando ejecutas un Hook en el punto de extensibilidad Client Credentials Exchange, el objeto de respuesta predeterminado es:

```json lines theme={null}
{
  "scope": "array of strings"
}
```

<div id="starter-code-response">
  ### Respuesta del código base
</div>

Una vez que hayas personalizado el código base con tus alcances y claims adicionales, puedes probar el Hook con el ejecutor integrado en el Hook Editor. El ejecutor simula una llamada al Hook con el mismo cuerpo y la misma respuesta que obtendrías con un Client Credentials Exchange.

<Warning>
  Ejecutar el código con el ejecutor requiere guardarlo, lo que significa que el código original se sobrescribirá.
</Warning>

Cuando ejecutas un Hook basado en el código base, el objeto de respuesta es:

```json lines theme={null}
{
  "audience": "https://my-tenant.auth0.com/api/v2/",
  "client": {
    "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "name": "client-name",
    "tenant": "my-tenant",
    "metadata": {
      "plan": "full"
    }
  },
  "scope": [
    "read:connections"
  ]
}
```

<div id="sample-script-add-an-additional-scope-to-the-access-token">
  ## Script de ejemplo: Añadir un scope adicional al token de acceso
</div>

En este ejemplo, usamos un Hook para añadir un scope adicional a los ya existentes en el token de acceso.

```js lines theme={null}
module.exports = function(client, scope, audience, context, cb) {
    // Alcances a agregar
    var access_token = {};

    // Obtener el scope que está actualmente en el Token de acceso
    // y agregarlo al objeto con el que estamos trabajando
    // ¡No eliminar esta línea!
    access_token.scope = scope;

    // Agregar el scope `read:resource`
    access_token.scope.push('read:resource');

    // Callback para indicar la finalización y devolver el nuevo
    // arreglo de alcances
    cb(null, access_token);
};
```

Para obtener más información, consulta [Scopes](/es/docs/get-started/apis/scopes).

<div id="response">
  ### Respuesta
</div>

Al ejecutar este Hook, el objeto de respuesta es:

```json lines theme={null}
{
  "scope": [
    "read:connections",
    "read:resource"
  ]
}
```

<div id="sample-script-add-a-claim-to-the-access-token">
  ## Script de ejemplo: Agregar un claim al token de acceso
</div>

En este ejemplo, agregamos un claim personalizado con espacio de nombres y su valor al token de acceso. Para obtener más información, consulta [Create Namespaced Custom Claims](/es/docs/secure/tokens/json-web-tokens/create-custom-claims).

Puedes agregar lo siguiente como claims al token emitido:

* La propiedad `scope` del objeto de respuesta
* Cualquier propiedad con nombres de propiedad con espacio de nombres

El punto de extensibilidad ignora todas las demás propiedades del objeto de respuesta.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Para acceder a un Hook Secret configurado desde un hook, usa `context.webtask.secrets.SECRET_NAME`.
</Callout>

```js lines theme={null}
module.exports = function(client, scope, audience, context, cb) {
    // Claims a agregar
    var access_token = {};

    // Nuevo claim para agregar al token
    access_token['https://example.com/foo'] = 'bar';

    // Callback para indicar la finalización y devolver el nuevo claim
    cb(null, access_token);
  };
```

<div id="response">
  ### Respuesta
</div>

Al ejecutar este Hook, el objeto de respuesta es:

```json lines theme={null}
{
  "https://example.com/foo": "bar"
}
```

<div id="sample-script-raise-an-error-or-deny-an-access-token">
  ## Script de ejemplo: Generar un error o denegar un token de acceso
</div>

En este ejemplo, usamos objetos `Error` personalizados para generar respuestas de error de OAuth2. (Para obtener más información, consulte [RFC de OAuth2: sección 5.2 en el IETF Datatracker](https://tools.ietf.org/html/rfc6749#section-5.2).)

Si se devuelve un error simple de JavaScript en la función de devolución de llamada, como:

```js lines theme={null}
module.exports = function(client, scope, audience, context, cb) {
    // Callback para indicar la finalización y devolver el nuevo claim
    cb(new Error("Unknown error occurred.");
  };
```

Luego, cuando solicites un grant `client_credentials` al endpoint `/oauth/token`, Auth0 responderá con:

```json lines theme={null}
HTTP 500
{ "error": "server_error", "error_description": "Unknown error occurred." }
```

Sin embargo, si desea un mayor control sobre la respuesta de error de OAuth2, puede usar en su lugar tres objetos `Error` personalizados.

<div id="invalidscopeerror">
  ### InvalidScopeError
</div>

```js lines theme={null}
module.exports = function(client, scope, audience, context, cb) {
    const invalidScope = ...; // determinar si el scope es válido

    if(invalidScope) {
      cb(new InvalidScopeError("Scope is not permitted."));
    }
  };
```

Luego, cuando solicitas una concesión `client_credentials` al endpoint `/oauth/token`, Auth0 responde con:

```json lines theme={null}
HTTP 400
{ "error": "invalid_scope", "error_description": "Scope is not permitted." }
```

<div id="invalidrequesterror">
  ### InvalidRequestError
</div>

```js lines theme={null}
module.exports = function(client, scope, audience, context, cb) {
    const invalidRequest = ...; // determinar si la solicitud es válida

    if(invalidRequest) {
      cb(new InvalidRequestError("Bad request."));
    }
  };
```

Luego, cuando solicite el grant `client_credentials` en el endpoint `/oauth/token`, Auth0 responderá con:

```json lines theme={null}
HTTP 400
{ "error": "invalid_request", "error_description": "Bad request." }
```

<div id="servererror">
  ### ServerError
</div>

```js lines theme={null}
module.exports = function(client, scope, audience, context, cb) {
    callOtherService(function(err, response) {
      if(err) {
        return cb(new ServerError("Error calling remote system: " + err.message));
      }
    });
  };
```

Entonces, cuando solicites una concesión de tipo `client_credentials` al endpoint `/oauth/token`, Auth0 responderá con:

```json lines theme={null}
HTTP 400
{ "error": "server_error", "error_description": "Error calling remote system: ..." }
```

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Actualmente, el comportamiento de la clase integrada `Error` de JavaScript y de `ServerError` es idéntico, pero la clase `ServerError` le permite especificar explícitamente el error de OAuth2 que se devolverá.
</Callout>

<div id="learn-more">
  ## Más información
</div>
