> ## 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 Node.js de l’API pour le scénario d’architecture « Applications serveur + API »

# Applications serveur + API : implémentation Node.js de l’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>;
};

Dans le cadre du [scénario d’architecture Server + API](/fr-CA/docs/get-started/architecture-scenarios/server-application-api), nous allons mettre en œuvre l’API Timesheets en Node.js. Consultez le scénario pour en savoir plus sur la solution mise en œuvre.

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

<div id="step-1-define-the-api-endpoint">
  ## Étape 1. Définir le point de terminaison de l’API
</div>

Nous utiliserons le framework d’applications Web [Express](http://expressjs.com/) pour créer notre API Node.js.

<div id="create-a-packagejson-file">
  ### Créer un fichier package.json
</div>

Créez un dossier pour votre API, accédez-y, puis exécutez `npm init`. Cette commande créera votre fichier `package.json`.

Vous pouvez conserver les paramètres par défaut ou les modifier 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": {
    "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"
}
```

<div id="install-the-dependencies">
  ### Installer les dépendances
</div>

Ensuite, nous devons configurer nos dépendances. Nous utiliserons les modules suivants :

* **express** : Ce module ajoute le [framework d’applications Web Express](https://expressjs.com/).
* **jwks-rsa** : Cette bibliothèque récupère des clés de signature RSA à partir d’un point de terminaison JWKS (JSON Web Key Set). En utilisant `expressJwtSecret`, nous pouvons générer un fournisseur de secrets qui fournira la clé de signature appropriée à `express-jwt` en fonction du `kid` dans l’en-tête du <Tooltip tip="JSON Web Token (JWT) : format standard des ID Token (et souvent des Jetons d’accès) utilisé pour représenter de façon sécurisée des déclarations entre deux parties." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=JWT">JWT</Tooltip>. Pour en savoir plus, consultez le [dépôt GitHub node-jwks-rsa](https://github.com/auth0/node-jwks-rsa).
* **express-jwt** : Ce module vous permet d’authentifier des 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 à utiliser. Pour en savoir plus et découvrir plusieurs solutions de rechange, consultez le dépôt GitHub de body-parser.

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

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

<div id="implement-the-endpoint">
  ### Implémentez le point de terminaison
</div>

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

* Configurer les dépendances.
* Activer le middleware d’analyse du corps de la requête.
* Implémenter le point de terminaison.
* Lancer le serveur de l’API.

Voici un exemple d’implémentation :

```javascript lines theme={null}
// définir les dépendances
const express = require('express');
const app = express();
const jwt = require('express-jwt');
const jwksRsa = require('jwks-rsa');
const bodyParser = require('body-parser');

// 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 API pour le téléversement des feuilles de temps
app.post('/timesheets/upload', function(req, res){
  res.status(201).send({message: "This is the POST /timesheets/upload endpoint"});
})

// lancer le serveur d’API à localhost:8080
app.listen(8080);
```

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

Nous avons maintenant notre point de terminaison, mais n’importe qui peut y accéder. Passez au paragraphe suivant pour voir comment régler ce problème.

<div id="step-2-secure-the-api-endpoint">
  ## Étape 2. Sécuriser le point de terminaison de l’API
</div>

Afin de valider notre jeton, nous utiliserons la fonction `jwt`, fournie par le [middleware express-jwt](https://github.com/auth0/express-jwt#usage), ainsi que le package `jwks-rsa` pour récupérer la clé publique d’Auth0. Les bibliothèques font ce qui suit :

1. `express-jwt` décodera le jeton et transmettra la requête, l’en-tête et la charge utile à `jwksRsa.expressJwtSecret`.
2. `jwks-rsa` téléchargera ensuite toutes les clés de signature à partir du point de terminaison JWKS et vérifiera si l’une d’elles correspond au `kid` dans l’en-tête du JWT. Si aucune des clés de signature ne correspond au `kid` reçu, une erreur sera générée. Si une correspondance est trouvée, nous transmettrons la bonne clé de signature à `express-jwt`.
3. `express-jwt` poursuivra ensuite sa logique de validation de la signature du jeton, de l’expiration, de `audience` et de `issuer`.

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

* Créer la fonction middleware pour valider le <Tooltip tip="Jeton d’accès : information 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="/fr-CA/docs/glossary?term=access+token">jeton d’accès</Tooltip>.
* Activer l’utilisation du middleware sur nos routes.

C’est aussi un bon moment pour implémenter la logique permettant d’enregistrer les entrées de feuille de temps dans une base de données locale, ou dans tout autre mécanisme de stockage de votre choix. Voici notre exemple d’implémentation (une partie du code est omise par souci de concision) :

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

// activer le middleware d'analyse du corps de la requête - code omis

// Créer un middleware pour vérifier le 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: process.env.AUTH0_AUDIENCE,
  issuer: \`https://{yourDomain}/\`,
  algorithms: ['RS256']
});

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

  // Enregistrer l'entrée de feuille de temps dans la base de données...

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

// démarrer le serveur d'API sur localhost:8080 - code omis`;

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

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

Pour tester également le scénario où tout fonctionne, nous devons :

* Obtenir un jeton d’accès. Pour savoir comment faire, consultez : [Get an Access Token](/fr-CA/docs/get-started/architecture-scenarios/server-application-api#get-an-access-token)
* Appeler l’API en ajoutant à notre requête un en-tête `Authorization` ayant pour valeur `Bearer ACCESS_TOKEN` (où `ACCESS_TOKEN` correspond à la valeur du jeton récupéré à la première étape).

<div id="step-3-check-the-client-permissions">
  ## Étape 3. Vérifier les autorisations de l’application
</div>

À cette étape, nous allons ajouter à notre implémentation la possibilité de vérifier si l’application dispose des autorisations (ou du `scope`) requises pour utiliser notre point de terminaison afin de téléverser une feuille de temps. Plus précisément, nous voulons nous assurer que le jeton possède le bon scope, soit `batch:upload`.

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

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

Il suffit maintenant d’ajouter un appel à `jwtAuthz(...)` à votre middleware pour vérifier que le JWT contient un scope particulier avant d’exécuter un point de terminaison donné. 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 - certains codes omis
const jwtAuthz = require('express-jwt-authz');

// Créer un middleware pour vérifier le JWT

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

// Point de terminaison de téléversement par lot
app.post('/timesheets/upload', checkJwt, jwtAuthz(['batch:upload']), function(req, res){
  var timesheet = req.body;

  // Enregistrer l'entrée de feuille de temps dans la base de données...

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

// Lancer le serveur d’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.

Et voilà ! C’est terminé !
