> ## 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.

> Découvrez comment utiliser Hooks pour modifier les scopes et ajouter des claims personnalisés au jeton d’accès obtenu à l’aide du Client Credentials Flow.

# Personnaliser les jetons à l’aide de Hooks dans le Client Credentials Flow

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASQUÉ*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

<Warning>
  La date de fin de vie (EOL) de Rules et Hooks est fixée au **18 novembre 2026**, et ils ne sont plus offerts aux nouveaux tenants créés à compter du **16 octobre 2023**. Les tenants existants ayant des Hooks actifs conserveront l’accès au produit Hooks jusqu’à la fin de vie.

  Nous vous recommandons fortement d’utiliser Actions pour étendre Auth0. Avec Actions, vous avez accès à des informations de typage détaillées, à de la documentation intégrée et à des packages `npm` publics, et vous pouvez connecter des intégrations externes qui améliorent votre expérience globale en matière d’extensibilité. Pour en savoir plus sur ce qu’offre Actions, consultez [Comprendre le fonctionnement d’Auth0 Actions](/docs/fr-ca/customize/actions/actions-overview).

  Pour vous aider dans votre migration, nous vous proposons des guides pour [passer de Rules à Actions](/docs/fr-ca/customize/actions/migrate/migrate-from-rules-to-actions) et [passer de Hooks à Actions](/docs/fr-ca/customize/actions/migrate/migrate-from-hooks-to-actions). Nous avons également une page dédiée, [Move to Actions](https://auth0.com/extensibility/movetoactions), qui présente des comparaisons de fonctionnalités, [une démo d’Actions](https://www.youtube.com/watch?v=UesFSY1klrI) et d’autres ressources pour vous accompagner dans votre migration.

  Pour en savoir plus sur la dépréciation de Rules et Hooks, consultez notre billet de blogue : [Preparing for Rules and Hooks End of Life](https://auth0.com/blog/preparing-for-rules-and-hooks-end-of-life/).
</Warning>

<Warning>
  Comme nous prévoyons retirer les fonctions Rules et Hooks en 2026, vous ne devriez créer de nouvelles Rules ou de nouveaux Hooks que dans votre environnement de développement, et uniquement pour tester la migration vers Actions.

  Pour savoir comment migrer vos Rules vers Actions, consultez [Passer de Rules à Actions](/docs/fr-ca/customize/actions/migrate/migrate-from-rules-to-actions). Pour savoir comment migrer vos Hooks vers Actions, consultez [Passer de Hooks à Actions](/docs/fr-ca/customize/actions/migrate/migrate-from-hooks-to-actions).
</Warning>

Vous pouvez modifier les scopes et ajouter des claims personnalisés dans les jetons émis au moyen du [Client Credentials Flow](/docs/fr-ca/get-started/authentication-and-authorization-flow/client-credentials-flow) en ajoutant des [Hooks](/docs/fr-ca/customize/hooks).

Les Hooks vous permettent de personnaliser le comportement d’Auth0 à l’aide de code Node.js. Ce sont des fonctions sécurisées et autonomes associées à des points d’extensibilité précis de la plateforme Auth0 (comme le Client Credentials Flow). Auth0 invoque les Hooks à l’exécution pour appliquer votre logique personnalisée.

Vous pouvez gérer les Hooks à l’aide du <Tooltip tip="Auth0 Dashboard: produit principal d’Auth0 pour configurer vos services." cta="Voir le glossaire" href="/docs/fr-ca/glossary?term=Auth0+Dashboard">Auth0 Dashboard</Tooltip> ou de la <Tooltip tip="Auth0 Dashboard: produit principal d’Auth0 pour configurer vos services." cta="Voir le glossaire" href="/docs/fr-ca/glossary?term=Management+API">Management API</Tooltip>.

<Warning>
  Bien que vous puissiez créer plusieurs hooks pour un point d’extensibilité donné, chaque point d’extensibilité ne peut avoir qu’un seul hook activé à la fois. Tous les hooks subséquents que vous créez pour ce point d’extensibilité sont automatiquement désactivés; vous devez donc les activer explicitement. Le hook activé sera exécuté pour toutes les applications et API.
</Warning>

<div id="prerequisites">
  ## Prérequis
</div>

Avant de commencer ce tutoriel, vous devez :

* [Enregistrer votre API auprès d’Auth0](/docs/fr-ca/get-started/auth0-overview/set-up-apis)

  * [Ajouter les permissions d’API appropriées](/docs/fr-ca/get-started/apis/add-api-permissions)
* [Enregistrer l’application M2M auprès d’Auth0](/docs/fr-ca/get-started/auth0-overview/create-applications/machine-to-machine-apps).

  * Sélectionnez un **Type d’application** de **Applications machine à machine**.
  * Choisissez votre API enregistrée précédemment.
  * Autorisez l’application M2M à appeler votre API.

<div id="steps">
  ## Étapes
</div>

1. **Créer un Hook**: Créez un hook pour personnaliser votre jeton.
2. **Tester le Hook**: Testez votre nouveau hook en exécutant un Client Credentials Flow et en décodant le jeton d’accès.

<div id="create-a-hook">
  ### Créer un Hook
</div>

Dans cet exemple, vous allez :

* ajouter une revendication arbitraire (`https://foo.com/claim`) au [jeton d’accès](/docs/fr-ca/secure/tokens/access-tokens)
* ajouter une permission supplémentaire à l’API que vous avez configurée

Créez un Hook pour personnaliser votre jeton. Lorsqu’on vous demandera de choisir un point d’extensibilité, sélectionnez `Client Credentials Exchange`, puis ajoutez le code suivant dans l’éditeur :

```js lines theme={null}
module.exports = function(client, scope, audience, context, cb) {
  var access_token = {};
  access_token['https://foo.com/claim'] = 'bar';
  access_token.scope = scope;
  access_token.scope.push('extra');
  cb(null, access_token);
};
```

<Warning>
  Auth0 renvoie les informations du profil dans un format structuré de claim, tel que défini par la [spécification OpenID Connect (OIDC)](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). Cela signifie que les claims personnalisés ajoutés aux ID tokens ou aux jetons d’accès doivent [respecter les directives et les restrictions](/docs/fr-ca/secure/tokens/json-web-tokens/create-custom-claims) afin d’éviter d’éventuelles collisions.
</Warning>

<div id="test-your-hook">
  ### Testez votre Hook
</div>

Pour tester le hook que vous venez de créer, vous devez lancer un échange Client Credentials, obtenir le <Tooltip tip="Jeton d’accès : donnée d’autorisation, sous la forme d’une chaîne opaque ou d’un JWT, utilisée pour accéder à une API." cta="Voir le glossaire" href="/docs/fr-ca/glossary?term=Access+Token">jeton d’accès</Tooltip>, le décoder et en examiner le contenu.

<div id="get-token">
  #### Obtenir un jeton
</div>

Pour obtenir un jeton, effectuez une requête `POST` vers le [point de terminaison du Client Credentials Flow](https://auth0.com/docs/api/authentication#client-credentials-flow). Assurez-vous de remplacer les valeurs de remplacement CLIENT\_ID, CLIENT\_SECRET et API\_IDENTIFIER par le <Tooltip tip="Client ID : valeur d’identification attribuée à votre ressource enregistrée par Auth0." cta="Voir le glossaire" href="/docs/fr-ca/glossary?term=Client+ID">Client ID</Tooltip> de votre application, le <Tooltip tip="Client Secret : secret utilisé par un client (application) pour s’authentifier auprès du serveur d’autorisation; il ne doit être connu que du client et du serveur d’autorisation et doit être suffisamment aléatoire pour ne pas pouvoir être deviné." cta="Voir le glossaire" href="/docs/fr-ca/glossary?term=Client+Secret">Client Secret</Tooltip> de votre application et l’identifiant de votre API, respectivement. Vous trouverez le Client ID et le Client Secret dans les paramètres de votre [Application](https://manage.auth0.com/#/applications), et l’identifiant de l’API dans les paramètres de votre [API](https://manage.auth0.com/#/apis).

<AuthCodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://{yourDomain}/oauth/token' \
    --header 'content-type: application/x-www-form-urlencoded' \
    --data grant_type=client_credentials \
    --data 'client_id={yourClientId}' \
    --data client_secret={yourClientSecret} \
    --data audience=YOUR_API_IDENTIFIER
  ```

  ```csharp C# theme={null}
  var client = new RestClient("https://{yourDomain}/oauth/token");
  var request = new RestRequest(Method.POST);
  request.AddHeader("content-type", "application/x-www-form-urlencoded");
  request.AddParameter("application/x-www-form-urlencoded", "grant_type=client_credentials&client_id={yourClientId}&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER", ParameterType.RequestBody);
  IRestResponse response = client.Execute(request);
  ```

  ```go Go theme={null}
  package main

  import (
  	"fmt"
  	"strings"
  	"net/http"
  	"io/ioutil"
  )

  func main() {

  	url := "https://{yourDomain}/oauth/token"

  	payload := strings.NewReader("grant_type=client_credentials&client_id={yourClientId}&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER")

  	req, _ := http.NewRequest("POST", url, payload)

  	req.Header.Add("content-type", "application/x-www-form-urlencoded")

  	res, _ := http.DefaultClient.Do(req)

  	defer res.Body.Close()
  	body, _ := ioutil.ReadAll(res.Body)

  	fmt.Println(res)
  	fmt.Println(string(body))

  }
  ```

  ```java Java theme={null}
  HttpResponse response = Unirest.post("https://{yourDomain}/oauth/token")
    .header("content-type", "application/x-www-form-urlencoded")
    .body("grant_type=client_credentials&client_id={yourClientId}&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER")
    .asString();
  ```

  ```javascript Node.JS theme={null}
  var axios = require("axios").default;

  var options = {
    method: 'POST',
    url: 'https://{yourDomain}/oauth/token',
    headers: {'content-type': 'application/x-www-form-urlencoded'},
    data: new URLSearchParams({
      grant_type: 'client_credentials',
      client_id: '{yourClientId}',
      client_secret: '{yourClientSecret}',
      audience: 'YOUR_API_IDENTIFIER'
    })
  };

  axios.request(options).then(function (response) {
    console.log(response.data);
  }).catch(function (error) {
    console.error(error);
  });
  ```

  ```php PHP theme={null}
  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://{yourDomain}/oauth/token",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => "grant_type=client_credentials&client_id={yourClientId}&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER",
    CURLOPT_HTTPHEADER => [
      "content-type: application/x-www-form-urlencoded"
    ],
  ]);

  $response = curl_exec($curl);
  $err = curl_error($curl);

  curl_close($curl);

  if ($err) {
    echo "cURL Error #:" . $err;
  } else {
    echo $response;
  }
  ```

  ```python Python theme={null}
  import http.client

  conn = http.client.HTTPSConnection("")

  payload = "grant_type=client_credentials&client_id={yourClientId}&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER"

  headers = { 'content-type': "application/x-www-form-urlencoded" }

  conn.request("POST", "/{yourDomain}/oauth/token", payload, headers)

  res = conn.getresponse()
  data = res.read()

  print(data.decode("utf-8"))
  ```

  ```ruby Ruby theme={null}
  require 'uri'
  require 'net/http'
  require 'openssl'

  url = URI("https://{yourDomain}/oauth/token")

  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER

  request = Net::HTTP::Post.new(url)
  request["content-type"] = 'application/x-www-form-urlencoded'
  request.body = "grant_type=client_credentials&client_id={yourClientId}&client_secret={yourClientSecret}&audience=YOUR_API_IDENTIFIER"

  response = http.request(request)
  puts response.read_body
  ```
</AuthCodeGroup>

Une réponse réussie comprendra :

* un `access_token`,
* sa durée de validité en secondes (`expires_in`),
* le type de jeton défini comme `Bearer` (`token_type`), et
* une permission `extra` (`scope`) (ajoutée par votre Hook)

```json lines theme={null}
HTTP/1.1 200 OK
Content-Type: application/json
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik5ESTFNa05DTVRGQlJrVTRORVF6UXpFMk1qZEVNVVEzT1VORk5ESTVSVU5GUXpnM1FrRTFNdyJ9.eyJpc3MiOiJodHRwczovL2RlbW8tYWNjb3VudC5hdXRoMC3jb20vIiwic3ViIjoic0FRSlFpQmYxREw0c2lqSVZCb2pFRUZvcmRoa0o4WUNAY2xpZW50cyIsImF1ZCI6ImRlbW8tYWNjb3VudC5hcGkiLCJleHAiOjE0ODc3NjU8NjYsImlhdCI6MTQ4NzY3OTI2Niwic2NvcGUiOiJyZWFkOmRhdGEgZXh0cmEiLCJodHRwczovL2Zvby5jb20vY2xhaW0iOiKoPXIifQ.da-48mHY_7esfLZpvHWWL8sIH1j_2mUYAB49c-B472lCdsNFvpaLoq6OKQyhnqk9_aW_Xhfkusos3FECTrLFvf-qwQK70QtwbkbVye_IuPSTAYdQ2T-XTzGDm9Nmmy5Iwl9rNYLxVs2OoCdfpVMyda0OaI0AfHBgEdKWluTP67OOnV_dF3KpuwtK3dPKWTCo2j9VCa7X1I4h0CNuM79DHhY2wO7sL8WBej7BSNA3N2TUsp_YTWWfrvsr_vVhJf-32G7w_12ms_PNFUwj2C30ZZIPWc-uEkDztyMLdI-lu9q9TLrLdr0dOhfrtfkdeJx4pUSiHdJHf42kg7UAVK6JcA",
  "expires_in": 86400,
  "scope": "extra",
  "token_type": "Bearer"
}
```

<div id="decode-token">
  #### Décoder le jeton
</div>

La façon la plus simple de décoder le jeton d’accès et d’en examiner le contenu est d’utiliser le [débogueur JWT.io](https://jwt.io/#debugger-io).

Copiez votre jeton d’accès et collez-le dans l’éditeur. Le <Tooltip tip="JSON Web Token (JWT) : format standard de ID Token (et souvent de jeton d’accès) utilisé pour représenter des claims de manière sécurisée entre deux parties." cta="Voir le glossaire" href="/docs/fr-ca/glossary?term=JWT">JWT</Tooltip> est décodé automatiquement et son contenu s’affiche.

Notez que les deux derniers éléments du **Payload** ont été définis par votre hook :

* `"scope": "extra"`
* `"https://foo.com/claim": "bar"`

<div id="learn-more">
  ## En savoir plus
</div>

* [Auth0 Hooks](/docs/fr-ca/customize/hooks)
* [Client Credentials Flow](/docs/fr-ca/get-started/authentication-and-authorization-flow/client-credentials-flow)
* [Effectuez une requête à votre API à l’aide du Client Credentials Flow](/docs/fr-ca/get-started/authentication-and-authorization-flow/client-credentials-flow/call-your-api-using-the-client-credentials-flow)
