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

# Applications serveur + API : Implémentation de l’API en Node.js

> L’implémentation Node.js de l’API pour le scénario d’architecture Serveur Client + 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 serveur + API](https://auth0.com/docs/architecture-scenarios/application/server-api), nous allons implémenter l’API Feuilles de temps dans Node.js. Veuillez vous référer au scénario pour obtenir des informations sur la solution implémentation.

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

## 1. Définir le point 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 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 échantillon 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

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

* **express** : Ce module ajoute le [cadre d’applications Web Express](https://expressjs.com/).
* **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 <Tooltip href="/docs/fr-ca/glossary?term=json-web-token" tip="Jeton Web JSON (JWT)
  Format standard de jeton d’ID (et souvent de jeton d’accès) utilisé pour représenter en toute sécurité des demandes entre deux parties." cta="Voir le glossaire">JWT</Tooltip>. Pour en apprendre davantage, consultez [node-jwks-rsa GitHub repository](https://github.com/auth0/node-jwks-rsa).
* **express-jwt** : Ce module vous laisse authentifier les requêtes HTTP à l’aide de jetons JWT dans vos applications Node.js. Express-jwtusieurs fonctions qui facilitent le travail avec les JWT. Pour plus d’information consultez [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 partie entière du corps d’une requête entrante et l’expose sur `req.body` comme quelque chose de plus facile à interfacer. Pour plus d’informations et plusieurs alternatives, consultez le dépôt GitHub body-parser.

Pour installer ces dépendances, procédez comme suit :

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

### Implémenter le point de terminaison

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

* Régler les dépendances.
* Activer le logiciel médiateur d’analyse du corps de la demande.
* Implémenter le point de terminaison.
* Lancer le serveur API.

Voici notre exemple d’implémentation :

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

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

// create timesheets upload API endpoint
app.post('/timesheets/upload', function(req, res){
  res.status(201).send({message: "This is the POST /timesheets/upload 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/upload`. Vous verrez une réponse JSON avec le message `Ceci est le point de terminaison POST /feuilles de temps/téléversement`.

Nous avons désormais notre point de terminaison, mais tout le monde peut l’appeler. Rendez-vous au paragraphe suivant pour voir comment nous pouvons résoudre ce problème.

## 2. Sécuriser le point de terminaison API

Afin de valider notre jeton, nous allons utiliser la fonction `jwt` fournie par le logiciel médiateur [express-jwt](https://github.com/auth0/express-jwt#usage), et le paquet `jwks-rsa` pour récupérer la clé publique d’Auth0. 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 nous avons une correspondance, nous transmettrons 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 fonctionnalité logiciel médiateur pour valider le jeton d’accès.
* Activez l’utilisation de logiciel médiateur dans nos chemins.

C’est également le bon moment pour implémenter la logique d’enregistrement des entrées de la feuille de temps dans une base de données locale, ou tout autre mécanisme de stockage que vous préférez. Voici notre exemple d’implémentation (certains codes sont omis en raison aux fins de concision) :

export const codeExample = `// set dependencies - code omitted

// enable the use of request body parsing middleware - 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: process.env.AUTH0_AUDIENCE,
  issuer: \`https://{yourDomain}/\`,
  algorithms: ['RS256']
});

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

  // Save the timesheet entry to the database...

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

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

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

Si nous lançons notre serveur maintenant et effectuons un HTTP POST vers `localhost:8080/timesheets/upload` nous obtiendrons le message d’erreur `Missing or invalid token`, 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 à : [Obtenir un jeton d’accès](https://auth0.com/docs/architecture-scenarios/application/server-api#get-an-access-token)
* Invoquez l’API en ajoutant un en-tête d’`Authorization` à notre requête avec la valeur `Bearer ACCESS_TOKEN`, où `ACCESS_TOKEN` est la valeur du jeton que nous avons récupéré à la première étape.

## 3. Vérifier les autorisations du client

Á cette étape nous ajoutons la possibilité de vérifier si le client a des autorisations (ou  `scope`) pour utiliser notre point de terminaison afin de téléverser une feuille de temps. En particulier, nous voulons nous rassurer que le jeton a la bonne permission, qui est `batch:upload`.

Pour y parvenir, nous utilisons le paquet `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 particulier. Voici notre exemple d’implémentation (certains codes sont omis en raison aux fins de concision) :

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

// Create middleware for checking the JWT

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

// Batch upload endpoint
app.post('/timesheets/upload', checkJwt, jwtAuthz(['batch:upload']), function(req, res){
  var timesheet = req.body;

  // Save the timesheet entry 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 devrions obtenir le message d’erreur Interdit avec le code d’état HTTP `403`. Vous pouvez l’essayer en supprimant cette permission de votre API.

Et voilà! Vous avez terminé!
