> ## Documentation Index
> Fetch the complete documentation index at: https://docs-dev-docs-event-stream-action-templates.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Mise en œuvre de l’API Node.js (Apps mobiles + API)

> L’implémentation Node.js de l’API pour le scénario d’architecture Mobile + 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 = `// set dependencies - code omitted

// Enable CORS - code omitted

// Create middleware for checking the JWT
const checkJwt = jwt({
  // Dynamically provide a signing key based on the kid in the header and the signing keys provided by the JWKS endpoint
  secret: jwksRsa.expressJwtSecret({
    cache: true,
    rateLimit: true,
    jwksRequestsPerMinute: 5,
    jwksUri: \`https://{yourDomain}/.well-known/jwks.json\`
  }),

  // Validate the audience and the issuer
  audience: '{YOUR_API_IDENTIFIER}', //replace with your API's audience, available at Dashboard > APIs
  issuer: 'https://{yourDomain}/',
  algorithms: [ 'RS256' ]
});

// Enable the use of request body parsing middleware - code omitted

// create timesheets API endpoint - code omitted
app.post('/timesheets', checkJwt, function(req, res){
  var timesheet = req.body;

  // Save the timesheet to the database...

  //send the response
  res.status(201).send(timesheet);
});
// launch the API Server at localhost:8080 - code omitted`;

Ce document fait partie du scénario d’architecture Mobile + API et explique comment mettre en œuvre l’API dans Node.js. Le code source complet de la mise en œuvre 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 vous référer au scénario pour obtenir des informations sur la solution mise en œuvre.

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

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

    Créez un dossier pour votre API, naviguez-y et exécutez  `npm init`. Ce processus configure votre fichier `package.json` .

    Laissez les paramètres par défaut ou modifiez-les selon votre convenance.

    Le `package.json`  de notre exemple ressemble à ce qui suit :

    ```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": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "repository": {
        "type": "git",
        "url": "git+https://github.com/auth0-samples/auth0-pnp-timesheets.git"
      },
      "author": "Auth0",
      "license": "MIT",
      "bugs": {
        "url": "https://github.com/auth0-samples/auth0-pnp-timesheets/issues"
      },
      "homepage": "https://github.com/auth0-samples/auth0-pnp-timesheets#readme"
    }
    ```

    ##### Installer les dépendances

    Définissez ensuite les dépendances avec les modules suivants :

    * **express** : ce module ajoute le [cadre d’applications Web Express](https://expressjs.com/).
    * **cors** : le présent module ajoute la prise en charge de l’activation du [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing), ce qui est nécessaire car l’API est appelée à partir d’une application à page unique 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 connexion RSA à partir d’un point de terminaison JWKS (JSON Web Key Set). À l’aide de `expressJwtSecret`, nous pouvons générer un fournisseur de secret qui fournit la bonne clé de connexion à `express-jwt` en fonction du `kid` dans l’en-tête JWT. Pour en apprendre davantage, référez-vous au [node-jwks-rsa GitHub repository](https://github.com/auth0/node-jwks-rsa).
    * **express-jwt** : Le présent module authentifie les requêtes HTTP à l’aide de jetons JWT dans vos applications Node.js. Il fournit plusieurs fonctions qui facilitent le travail avec les JWT. Pour plus d’information, reportez-vous au [express-jwt GitHub repository](https://github.com/auth0/express-jwt).
    * **body-parser** : il s’agit d’un logiciel médiateur d’analyse de corps Node.js. Il extrait la totalité du corps d’une requête entrante et l’expose sur `req.body` comme quelque chose de plus simple avec laquelle interfacer.

    Pour installer ces dépendances, suivez les étapes suivantes :

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

    ##### Implémenter les points de terminaison

    Ouvrez votre répertoire API et créez un fichier  `server.js` . Votre code doit :

    * Obtenir les dépendances.
    * Implémenter le ou les points de terminaison.
    * Lancer 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');

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

    // Enable the use of request body parsing middleware
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({
      extended: true
    }));

    // Create timesheets API endpoint
    app.post('/timesheets', function(req, res){
      res.status(201).send({message: "This is the POST /timesheets endpoint"});
    })

    // Launch the API Server at localhost:8080
    app.listen(8080);
    ```

    Lancez votre serveur API en utilisant  `node server` et envoyez une requête HTTP POST à `localhost:8080/timesheets`. Vous verrez une réponse JSON avec le message `This is the POST /timesheets endpoint`.

    Nous avons désormais notre point de terminaison, mais tout le monde peut l’appeler. Continuez à l’étape suivante pour voir comment nous pouvons résoudre ce problème.
  </Accordion>

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

    1. `express-jwt` décode le jeton et achemine la demande, l’en-tête et les données utiles vers  `jwksRsa.expressJwtSecret`.
    2. `jwks-rsa` télécharge toutes les clés de connexion à partir du point de terminaison JWKS et vérifie si l’une des clés de connexion correspond à la valeur `kid` dans l’en-tête du jeton JWT. Si aucune des clés de connexion ne correspond à la valeur `kid`reçue, une erreur sera générée. Si vous avez une correspondance, transmettez la bonne clé de connexion à `express-jwt`.
    3. `express-jwt` poursuit sa propre logique pour valider la signature du jeton, l’expiration, l'`audience` et l'`issuer`.

    Les étapes que nous suivrons dans notre code sont :

    * Créer la fonction logiciel médiateur pour valider le jeton d’accès.
    * Activez l’utilisation du logiciel médiateur dans nos chemins.

    Vous pouvez également écrire du code pour véritablement enregistrer la feuille de temps dans une base de données. Voici notre exemple d’implémentation (certains codes sont omis aux fins de concision) :

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

    Si nous lançons notre serveur maintenant et effectuons un HTTP POST vers  `localhost:8080/timesheets` nous obtiendrons le message d’erreur `Missing or invalid token (Jeton manquant ou non valide)`, ce qui est correct, car nous n’avons pas envoyé de jeton d’accès dans notre requête.

    Pour tester également le scénario de fonctionnement, nous devons :

    * Obtenir un jeton d’accès. Pour plus d’informations sur la procédure à suivre pour y parvenir, reportez-vous à : [Get an Access Token](/docs/fr-ca/architecture-scenarios/application/server-api#get-an-access-token) (Obtenir un jeton d’accès).
    * Invoquez l’API en ajoutant un en-tête `Authorization (Autorisation)` à notre requête avec la valeur `Bearer ACCESS_TOKEN (Porteur de jeton d’accès)`, où `ACCESS_TOKEN (jeton d’accès)` est la valeur du jeton que nous avons récupéré à la première étape.
  </Accordion>

  <Accordion title="3 Vérifier les permissions de l’application">
    Á cette étape, nous ajoutons la possibilité de vérifier si l’application a des autorisations (ou des permissions) et d’utiliser notre point de terminaison afin de créer une feuille de temps. En particulier, nous voulons nous rassurer que le jeton a la bonne portée, qui est `batch:upload`.

    Pour y parvenir, nous utilisons le paquetage  `express-jwt-authz` Node.js, donc ajoutez-le à votre projet :

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

    Maintenant, ajoutez un appel à `jwtAuthz(...)` à votre logiciel médiateur pour vous assurer que le jeton JWT contient une permission particulière afin d’exécuter un point de terminaison spécifique.

    Nous ajoutons une dépendance supplémentaire. La bibliothèque **express-jwt-authz** , utilisée conjointement avec express-jwt, valide le jeton [JWT](https://auth0.com/docs/tokens/concepts/jwts) et s’assure qu’il possède les autorisations adéquates pour appeler le point de terminaison souhaité. Pour plus d’informations, consultez le  [référentiel GitHub express-jwt-authz](https://github.com/auth0/express-jwt-authz).

    Voici notre exemple d’implémentation (certains codes sont omis aux fins de concision) :

    ```javascript lines theme={null}
    // set dependencies - some code omitted
    const jwtAuthz = require('express-jwt-authz');

    // Enable CORS - code omitted

    // Create middleware for checking the JWT - code omitted

    // Enable the use of request body parsing middleware - code omitted

    // create timesheets API endpoint
    app.post('/timesheets', checkJwt, jwtAuthz(['create:timesheets'], { customUserKey: 'auth' }), function(req, res){
      var timesheet = req.body;

      // Save the timesheet to the database...

      //send the response
      res.status(201).send(timesheet);
    })

    // launch the API Server at localhost:8080 - code omitted
    ```

    Si nous invoquons notre API avec un jeton qui n’inclut pas cette permission, nous devons obtenir le message d’erreur Interdit avec le code d’état HTTP `403`. Vous pouvez l’essayer en supprimant cette permission de votre API.
  </Accordion>

  <Accordion title="4 Déterminer l’identité de l’utilisateur">
    Le logiciel médiateur `express-jwt` utilisé pour valider le jeton JWT configure également `req.user` avec les informations contenues dans le jeton JWT. Si vous voulez utiliser la demande `sub` pour identifier l’utilisateur de manière unique, vous pouvez utiliser `req.user.sub`. Pour l’application des feuilles de temps, nous voulons utiliser l’adresse courriel de l’utilisateur comme identifiant unique.

    ##### Créer une action

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

    1. Allez sur [Auth0 Dashboard > Actions > Bibliothèque](https://manage.auth0.com/#/actions/library)et sélectionnez**Créer une version personnalisée**.

    2. Saisissez un **Nom**descriptif pour votre action (par exemple, `Add email to access token`), sélectionnez le déclencheur **Connexion/Post-connexion**, puis sélectionnez **Créer**.

    3. Repérez l’éditeur de code des actions, copiez le code JavaScript suivant dans celui-ci, puis sélectionnez **Enregistrer le brouillon**  pour enregistrer vos modifications.

       ```js 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` est utilisé pour s’assurer que la demande a un nom unique qui n’entre pas en conflit avec des demandes OIDC standard ou des services internes. Pour en savoir plus sur les restrictions et instructions avec les demandes à espace de noms et sans espace de noms, consultez [Créer des demandes personnalisées](/docs/fr-ca/secure/tokens/json-web-tokens/create-custom-claims).
           </Callout>

    4. Dans la barre latérale de l’éditeur de code des actions, sélectionnez Test (icône de lecture), puis sélectionnez **Exécuter** pour  [tester votre code](/docs/fr-ca/customize/actions/test-actions).

    5. Lorsque vous êtes prêt à ce que l’action soit mise en ligne, selectionnez **Deploy (Déployer)**.

    ##### Ajoutez votre action au flux de connexion

    Ensuite, ajoutez l’action créée au [Flux de connexion](https://manage.auth0.com/#/actions/flows/login/). Pour savoir comment attacher des actions à des flux, lisez la section Attacher l’action à un flux dans [Écrire votre première action](/docs/fr-ca/customize/actions/write-your-first-action).

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

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

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

      // Associate the timesheet entry with the current user
      var userId = req.auth['https://api.exampleco.com/email'];
      timesheet.user_id = userId;

      // Save the timesheet to the database...

      //send the response
      res.status(201).send(timesheet);
    });
    ```
  </Accordion>
</AccordionGroup>
