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

> L’implémentation en Node.js de l’API pour le scénario d’architecture Mobile + API

# Implémentation de l’API en Node.js (applications mobiles + API)

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) + "*****MASKED*****";
          }
          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>;
};

export const codeExample = `// définir les dépendances - code omis

// Activer CORS - code omis

// Créer le middleware de vérification du JWT
const checkJwt = jwt({
  // Fournir dynamiquement une clé de signature en fonction du kid dans l’en-tête et des clés de signature fournies par le point de terminaison JWKS
  secret: jwksRsa.expressJwtSecret({
    cache: true,
    rateLimit: true,
    jwksRequestsPerMinute: 5,
    jwksUri: \`https://{yourDomain}/.well-known/jwks.json\`
  }),

  // Valider l’audience et l’émetteur
  audience: '{YOUR_API_IDENTIFIER}', //remplacez par l’audience de votre API, disponible dans Dashboard > APIs
  issuer: 'https://{yourDomain}/',
  algorithms: [ 'RS256' ]
});

// Activer le middleware d’analyse du corps de la requête - code omis

// créer le point de terminaison de l’API de feuilles de temps - code omis
app.post('/timesheets', checkJwt, function(req, res){
  var timesheet = req.body;

  // Enregistrer la feuille de temps dans la base de données...

  //envoyer la réponse
  res.status(201).send(timesheet);
});
// lancer le serveur API sur localhost:8080 - code omis`;

Ce document fait partie du scénario d’architecture Mobile + API et explique comment mettre en œuvre l’API en Node.js. Le code source complet de l’implémentation de l’API Node.js se trouve dans [ce dépôt GitHub](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node).

Veuillez consulter le scénario pour en savoir plus sur la solution mise en œuvre.

<AccordionGroup>
  <Accordion title="1 Définir les points de terminaison de l’API">
    Cette implémentation utilise le [cadriciel d’application Web Express](http://expressjs.com/) pour créer une API Node.js.

    ##### Créer un fichier package.json

    Créez un dossier pour votre API, accédez-y, puis exécutez `npm init`. Cela configure votre fichier `package.json`.

    Conservez les paramètres par défaut ou modifiez-les selon vos besoins.

    Le fichier `package.json` de notre exemple ressemble à ceci :

    ```json lines theme={null}
    {
      "name": "timesheets-api",
      "version": "1.0.0",
      "description": "API used to add timesheet entries for employees and contractors",
      "main": "index.js",
      "scripts": {
        "start": "node index.js",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "dependencies": {
        "body-parser": "^1.20.0",
        "cors": "^2.8.5",
        "express": "^4.18.0",
        "express-oauth2-jwt-bearer": "^1.6.0"
      },
      "author": "Auth0",
      "license": "MIT"
    }
    ```

    ##### Installer les dépendances

    Ensuite, configurez les dépendances avec les modules suivants :

    * **express** : Ce module ajoute le [framework Web Express](https://expressjs.com/).
    * **cors** : Ce module ajoute la prise en charge de l’activation de [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing), ce qui est nécessaire puisque l’API est appelée à partir d’une application monopage qui s’exécute sur un domaine différent dans un navigateur Web.
    * **jwks-rsa** : Cette bibliothèque récupère les clés de signature RSA à partir d’un point de terminaison JWKS (jeu de clés Web JSON). À l’aide de `expressJwtSecret`, nous pouvons générer un fournisseur de secret qui transmet la clé de signature appropriée à `express-jwt` en fonction du `kid` dans l’en-tête JWT. Pour en savoir plus, consultez le [dépôt GitHub node-jwks-rsa](https://github.com/auth0/node-jwks-rsa).
    * **express-jwt** : Ce module authentifie les requêtes HTTP à l’aide de jetons JWT dans vos applications Node.js. Il fournit plusieurs fonctions qui facilitent l’utilisation des JWT. Pour en savoir plus, consultez le [dépôt GitHub express-jwt](https://github.com/auth0/express-jwt).
    * **body-parser** : Il s’agit d’un intergiciel Node.js d’analyse du corps des requêtes. Il extrait l’intégralité du corps d’un flux de requête entrant et l’expose dans `req.body` sous une forme plus facile à exploiter.

    Pour installer ces dépendances, exécutez ce qui suit :

    ```bash wrap lines theme={null}
    npm install express cors express-jwt jwks-rsa body-parser express-jwt-authz --save
    ```

    ##### Implémentez les points de terminaison

    Accédez au répertoire de votre API et créez un fichier `server.js`. Votre code doit :

    * Récupérer les dépendances.
    * Implémenter le ou les points de terminaison.
    * Démarrer le serveur API.

    Voici notre exemple d’implémentation :

    ```javascript lines theme={null}
    const express = require('express');
    const app = express();
    const { expressjwt: jwt } = require('express-jwt');
    const jwksRsa = require('jwks-rsa');
    const cors = require('cors');
    const bodyParser = require('body-parser');

    // Activer CORS
    app.use(cors());

    // Activer l'utilisation du middleware d'analyse du corps de la requête
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({
      extended: true
    }));

    // Créer le point de terminaison de l'API des feuilles de temps
    app.post('/timesheets', function(req, res){
      res.status(201).send({message: "This is the POST /timesheets endpoint"});
    })

    // Lancer le serveur API à localhost:8080
    app.listen(8080);
    ```

    Démarrez votre serveur d’API à l’aide de `node server`, puis envoyez une requête HTTP POST à `localhost:8080/timesheets`. Vous devriez voir une réponse JSON contenant le message `This is the POST /timesheets endpoint`.

    Nous avons maintenant notre point de terminaison, mais n’importe qui peut l’appeler. Passez à l’étape suivante pour voir comment résoudre ce problème.
  </Accordion>

  <Accordion title="2 Sécuriser les points de terminaison de l’API">
    Pour valider notre jeton, utilisez la fonction `jwt`, fournie par le [middleware express-jwt](https://github.com/auth0/express-jwt#usage), ainsi que `jwks-rsa` pour récupérer notre secret. Les bibliothèques font ce qui suit :

    1. `express-jwt` décode le jeton et transmet la requête, l’en-tête et la charge utile à `jwksRsa.expressJwtSecret`.
    2. `jwks-rsa` télécharge toutes les clés de signature depuis le point de terminaison JWKS et vérifie si l’une d’elles correspond au `kid` dans l’en-tête du JWT. Si aucune clé de signature ne correspond au `kid` reçu, une erreur est générée. S’il y a correspondance, la bonne clé de signature est transmise à `express-jwt`.
    3. `express-jwt` poursuit ensuite sa logique pour valider la signature du jeton, son expiration, l’`audience` et l’`issuer`.

    Les étapes que nous suivrons dans notre code sont les suivantes :

    * Créer la fonction middleware pour valider le jeton d’accès.
    * Activer l’utilisation du middleware dans nos routes.

    Vous pouvez aussi écrire du code pour enregistrer réellement la feuille de temps dans une base de données. Voici notre exemple d’implémentation (une partie du code est omise par souci de concision) :

    <AuthCodeBlock children={codeExample} language="javascript" />

    Si nous démarrons notre serveur maintenant et effectuons une requête HTTP POST vers `localhost:8080/timesheets`, nous devrions obtenir le message d’erreur `Missing or invalid token` (ce qui est normal puisque nous n’avons pas envoyé de jeton d’accès dans notre requête).

    Pour tester également le scénario fonctionnel, nous devons :

    * Obtenir un jeton d’accès. Pour savoir comment faire, consultez : [Get an Access Token](/fr-CA/docs/secure/tokens/access-tokens/get-access-tokens).
    * Appeler l’API en ajoutant un en-tête `Authorization` à notre requête avec la valeur `Bearer ACCESS_TOKEN` (où `ACCESS_TOKEN` est la valeur du jeton récupéré à la première étape).
  </Accordion>

  <Accordion title="3 Vérifiez les autorisations de l’application">
    Dans cette étape, nous ajoutons la possibilité de vérifier si l’application dispose des autorisations (ou scopes) nécessaires et d’utiliser notre point de terminaison pour créer une feuille de temps. Plus précisément, nous voulons nous assurer que le jeton possède le scope approprié, soit `batch:upload`.

    Pour ce faire, nous utilisons le package Node.js `express-jwt-authz` ; ajoutez-le donc à votre projet :

    ```bash lines theme={null}
    npm install express-jwt-authz --save
    ```

    Ajoutez maintenant un appel à `jwtAuthz(...)` à votre middleware pour vous assurer que le JWT contient un scope précis avant d’exécuter un point de terminaison donné.

    Nous ajoutons une dépendance supplémentaire. La bibliothèque **express-jwt-authz**, utilisée conjointement avec express-jwt, valide le [JWT](/fr-CA/docs/secure/tokens/json-web-tokens) et s’assure qu’il dispose des autorisations appropriées pour appeler le point de terminaison visé. Pour en savoir plus, consultez le [dépôt GitHub d’express-jwt-authz](https://github.com/auth0/express-jwt-authz).

    Voici notre exemple d’implémentation (une partie du code est omise par souci de concision) :

    ```javascript lines theme={null}
    // définir les dépendances - une partie du code est omise
    const jwtAuthz = require('express-jwt-authz');

    // Activer CORS - code omis

    // Créer le middleware pour vérifier le JWT - code omis

    // Activer l'utilisation du middleware d'analyse du corps de la requête - code omis

    // créer le point de terminaison API des feuilles de temps
    app.post('/timesheets', checkJwt, jwtAuthz(['create:timesheets'], { customUserKey: 'auth' }), function(req, res){
      var timesheet = req.body;

      // Enregistrer la feuille de temps dans la base de données...

      //envoyer la réponse
      res.status(201).send(timesheet);
    })

    // lancer le serveur API à localhost:8080 - code omis
    ```

    Si nous appelons notre API avec un jeton qui n’inclut pas ce scope, nous devrions obtenir le message d’erreur Forbidden avec le code d’état HTTP `403`. Vous pouvez le vérifier en supprimant ce scope de votre API.
  </Accordion>

  <Accordion title="4 Déterminer l’identité de l’utilisateur">
    Le middleware `express-jwt` utilisé pour valider le JWT renseigne également `req.user` avec l’information contenue dans le JWT. Si vous souhaitez utiliser la revendication `sub` pour identifier l’utilisateur de manière unique, vous pouvez utiliser `req.user.sub`. Pour l’application de feuilles de temps, nous voulons utiliser l’adresse courriel de l’utilisateur comme identifiant unique.

    ##### Créer une Action

    D’abord, [créez une nouvelle Action](/fr-CA/docs/customize/actions/write-your-first-action) qui ajoutera l’adresse courriel de l’utilisateur au jeton d’accès.

    1. Accédez à [Auth0 Dashboard > Actions > Library](https://manage.auth0.com/#/actions/library), puis sélectionnez **Build Custom**.
    2. Saisissez un **Nom** descriptif pour votre Action (par exemple, `Add email to access token`), sélectionnez le déclencheur **Login / Post Login**, puis sélectionnez **Create**.
    3. Repérez l’éditeur de code Actions, copiez-y le code JavaScript suivant, puis sélectionnez **Save Draft** pour enregistrer vos modifications :

       ```text lines theme={null}
       exports.onExecutePostLogin = async (event, api) => {
         const namespace = 'https://my-app.example.com';
         api.accessToken.setCustomClaim(`${namespace}/email`, event.user.email);
       }
       ```

           <Callout icon="file-lines" color="#0EA5E9" iconType="regular">
             Le `namespace` sert à garantir que la revendication a un nom unique qui n’entre pas en conflit avec les revendications OIDC standard ni avec les services internes. Pour en savoir plus sur les restrictions et les directives relatives aux revendications avec et sans espace de noms, consultez [Create Custom Claims](/fr-CA/docs/secure/tokens/json-web-tokens/create-custom-claims).
           </Callout>
    4. Dans la barre latérale de l’éditeur de code Actions, sélectionnez Test (icône de lecture), puis sélectionnez **Run** pour [tester votre code](/fr-CA/docs/customize/actions/test-actions).
    5. Lorsque vous êtes prêt à déployer l’Action, sélectionnez **Deploy**.

    ##### Ajouter votre Action au déclencheur Post-Login

    Ensuite, ajoutez l’Action que vous avez créée au [déclencheur Post-Login](https://manage.auth0.com/#/actions/triggers/post-login/). Pour savoir comment attacher des Actions à des déclencheurs, consultez [Write Your First Action](/fr-CA/docs/customize/actions/write-your-first-action).

    ##### Récupérer l’identifiant unique

    Enfin, dans votre API, récupérez la valeur de la revendication à partir de `req.auth`. Utilisez cette valeur comme identifiant utilisateur unique à associer aux entrées de feuille de temps.

    ```js lines theme={null}
    app.get('/timesheets', checkJwt, jwtAuthz(['read:timesheets'], { customUserKey: 'auth' }), function(req, res) {
      var timesheet = req.body;

      // Associer l'entrée de feuille de temps à l'utilisateur actuel
      var userId = req.auth['https://api.exampleco.com/email'];
      timesheet.user_id = userId;

      // Enregistrer la feuille de temps dans la base de données...

      //envoyer la réponse
      res.status(201).send(timesheet);
    });
    ```
  </Accordion>
</AccordionGroup>
