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

> Configuration de l’API et du SPA pour le scénario d’architecture SPA + API

# Configuration de l’API et du SPA (SPA + 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 cette section, nous verrons comment implémenter une API dans notre cas d’utilisation.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Par souci de simplicité, notre implémentation se concentrera uniquement sur l’authentification et l’autorisation. Comme vous le verrez dans les exemples, l’entrée de feuille de temps fournie à l’API sera codée en dur, et l’API ne la conservera pas. Elle se contentera simplement de renvoyer une partie des informations.
</Callout>

<div id="define-the-api-endpoints">
  ## Définir les points de terminaison de l’API
</div>

Nous devons d’abord définir les points de terminaison de notre API.

<Card title="Qu’est-ce qu’un point de terminaison d’API ?">
  Un **point de terminaison d’API** est une URL unique qui représente un objet. Pour interagir avec cet objet, vous devez faire pointer votre application vers son URL. Par exemple, si vous aviez une API capable de renvoyer des commandes ou des clients, vous pourriez configurer deux points de terminaison : `/orders` et `/customers`. Votre application interagirait avec ces points de terminaison au moyen de différentes méthodes HTTP ; par exemple, `POST /orders` pourrait créer une nouvelle commande, tandis que `GET /orders` pourrait récupérer l’ensemble de données d’une ou de plusieurs commandes.
</Card>

Pour cette implémentation, nous ne définirons que 2 points de terminaison : un pour récupérer la liste de toutes les feuilles de temps d’un employé, et un autre pour permettre à un employé de créer une nouvelle entrée de feuille de temps.

Une requête `HTTP GET` vers le point de terminaison `/timesheets` permettra à un utilisateur de récupérer ses feuilles de temps, et une requête `HTTP POST` vers le point de terminaison `/timesheets` lui permettra d’ajouter une nouvelle feuille de temps.

**Voir l’implémentation en** [**Node.js**](/fr-CA/docs/get-started/architecture-scenarios/spa-api/api-implementation-nodejs#1-define-the-api-endpoints).

<div id="secure-the-endpoints">
  ### Sécuriser les points de terminaison
</div>

Lorsqu’une API reçoit une requête contenant un jeton du porteur <Tooltip tip="Jeton d’accès : justificatif d’autorisation, sous la forme d’une chaîne opaque ou d’un JWT, servant à accéder à une API." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=Access+Token">Jeton d’accès</Tooltip> dans l’en-tête, la première chose à faire est de valider le jeton. Ce processus comporte une série d’étapes, et si l’une d’elles échoue, la requête doit être rejetée avec le message d’erreur `Missing or invalid token` à l’intention de l’application appelante.

Les validations que l’API doit effectuer sont :

* Vérifier que le <Tooltip tip="JSON Web Token (JWT) : format standard d’ID Token (et souvent de Jeton d’accès) utilisé pour représenter de façon sécurisée des revendications entre deux parties." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=JWT">JWT</Tooltip> est bien formé
* Vérifier la signature
* Valider les revendications standard

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  [JWT.io](https://jwt.io/) fournit une liste de bibliothèques capables d’effectuer l’essentiel du travail pour vous : analyser le JWT, vérifier la signature et les revendications.
</Callout>

Le processus de validation comprend aussi la vérification des autorisations de l’application (scopes), mais nous traiterons ce point séparément dans le paragraphe suivant de ce document.

Pour en savoir plus sur la validation des jetons d’accès, consultez [Valider les jetons d’accès](/fr-CA/docs/secure/tokens/access-tokens/validate-access-tokens).

**Consultez l’implémentation dans** [**Node.js**](/fr-CA/docs/get-started/architecture-scenarios/spa-api/api-implementation-nodejs#2-secure-the-api-endpoints).

<div id="check-the-applications-permissions">
  ### Vérifier les autorisations de l’application
</div>

À ce stade, nous avons vérifié que le JWT est valide. La dernière étape consiste à vérifier que l’application dispose des autorisations requises pour accéder aux ressources protégées.

Pour ce faire, l’API doit vérifier les [scopes](/fr-CA/docs/get-started/apis/scopes) du JWT décodé. Cette revendication fait partie du payload et se présente sous la forme d’une liste de chaînes séparées par des espaces.

**Voir l’implémentation dans** [**Node.js**](/fr-CA/docs/get-started/architecture-scenarios/spa-api/api-implementation-nodejs#3-check-the-client-permissions).

<div id="determine-user-identity">
  ### Déterminer l’identité de l’utilisateur
</div>

Pour les deux points de terminaison (récupération de la liste des feuilles de temps et ajout d’une nouvelle feuille de temps), nous devrons déterminer l’identité de l’utilisateur.

Pour récupérer la liste des feuilles de temps, cela permet de s’assurer que nous renvoyons uniquement les feuilles de temps appartenant à l’utilisateur à l’origine de la demande. Pour ajouter une nouvelle feuille de temps, cela permet de s’assurer que la feuille de temps est associée à l’utilisateur à l’origine de la demande.

L’une des revendications JWT standard est la revendication `sub`, qui identifie l’entité principale visée par la revendication. Dans le cas du flux d’octroi implicite, cette revendication contiendra l’identité de l’utilisateur, c’est-à-dire l’identifiant unique de l’utilisateur Auth0. Vous pouvez l’utiliser pour associer à un utilisateur particulier toute information stockée dans des systèmes externes.

Vous pouvez également utiliser une revendication personnalisée pour ajouter un autre attribut de l’utilisateur — comme son adresse de courriel — au Jeton d’accès et vous en servir pour identifier l’utilisateur de façon unique.

**Consultez l’implémentation dans** [**Node.js**](/fr-CA/docs/get-started/architecture-scenarios/spa-api/api-implementation-nodejs#4-determine-the-user-identity).

<div id="implement-the-spa">
  ## Implémenter la SPA
</div>

Dans cette section, nous verrons comment mettre en œuvre une SPA dans notre scénario.

<div id="authorize-the-user">
  ### Autoriser l’utilisateur
</div>

Pour autoriser l’utilisateur, nous allons utiliser la [bibliothèque auth0.js](/fr-CA/docs/libraries/auth0js). Vous pouvez initialiser une nouvelle instance de l’application Auth0 comme suit :

export const codeExample = `var auth0 = new auth0.WebAuth({
  clientID: '{yourClientId}',
  domain: '{yourDomain}',
  responseType: 'token id_token',
  audience: 'YOUR_API_IDENTIFIER',
  redirectUri: '{https://yourApp/callback}',
  scope: 'openid profile read:timesheets create:timesheets'
});`;

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

Vous devez fournir les valeurs de configuration suivantes :

* **clientID**: La valeur de votre <Tooltip tip="ID client : valeur d’identification attribuée par Auth0 à votre ressource enregistrée." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=Client+Id">ID client</Tooltip> Auth0. Vous pouvez la récupérer dans les paramètres de votre application, dans le [Auth0 Dashboard](https://manage.auth0.com/#/applications%7D).
* **domain**: La valeur de votre Domaine Auth0. Vous pouvez la récupérer dans les paramètres de votre application, dans le [Auth0 Dashboard](https://manage.auth0.com/#/applications%7D).
* **responseType**: Indique le flux d’authentification à utiliser. Pour une SPA qui utilise le **flux implicite**, cette valeur doit être définie sur `token id_token`. La partie `token` déclenche le renvoi d’un jeton d’accès dans le fragment d’URL, tandis que la partie `id_token` déclenche aussi le renvoi d’un <Tooltip tip="ID Token : justificatif d’identité destiné à l’application cliente elle-même, et non à l’accès à une ressource." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=ID+Token">ID Token</Tooltip>.
* **<Tooltip tip="Audience : identifiant unique de l’audience d’un jeton émis. Nommée aud dans un jeton, sa valeur contient l’ID soit d’une application (ID client) pour un ID Token, soit d’une API (identifiant d’API) pour un jeton d’accès." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=audience">audience</Tooltip>**: La valeur de l’identifiant de votre API. Vous pouvez la récupérer dans les [paramètres de votre API](https://manage.auth0.com/#/apis%7D), dans le Auth0 Dashboard.
* **redirectUri**: L’URL vers laquelle Auth0 doit rediriger l’utilisateur une fois l’authentification terminée.
* **scope**: Les [scopes](/fr-CA/docs/get-started/apis/scopes) qui déterminent les informations renvoyées dans l’ID Token et le jeton d’accès. Un scope de `openid profile` renverra toutes les informations du profil utilisateur dans l’ID Token. Vous devez aussi demander les scopes requis pour appeler l’API, dans ce cas les scopes `read:timesheets create:timesheets`. Cela garantira que le jeton d’accès contient ces scopes.

Pour lancer le flux d’authentification, vous pouvez appeler la méthode `authorize()` :

```js lines theme={null}
auth0.authorize();
```

Après l’authentification, Auth0 redirigera l’utilisateur vers le **redirectUri** que vous avez spécifié lors de la configuration de la nouvelle instance de l’application Auth0. À ce stade, vous devrez appeler la méthode `parseHash()`, qui analyse un fragment de hash d’URL pour extraire le résultat d’une réponse d’authentification d’Auth0.

Le contenu de l’objet authResult renvoyé par parseHash dépend des paramètres d’authentification utilisés. Il peut inclure les éléments suivants :

* **idToken** : un JWT ID Token contenant des informations de profil utilisateur
* **accessToken** : un jeton d’accès pour l’API spécifiée par **audience**.
* **expiresIn** : une chaîne de caractères contenant la durée d’expiration (en secondes) du jeton d’accès.

Déterminez où il est préférable de [stocker les jetons](/fr-CA/docs/secure/security-guidance/data-security/token-storage). Si votre application monopage a un serveur backend, les jetons doivent être gérés côté serveur à l’aide du [flux de code d’autorisation](/fr-CA/docs/get-started/authentication-and-authorization-flow/authorization-code-flow) ou du [flux de code d’autorisation avec Proof Key for Code Exchange (PKCE)](/fr-CA/docs/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce).

Si vous avez une application monopage (SPA) sans serveur backend correspondant, votre SPA doit demander de nouveaux jetons à la connexion et les stocker en mémoire, sans persistance. Pour effectuer des appels d’API, votre SPA utilisera ensuite la copie du jeton conservée en mémoire.

Pour obtenir un exemple de gestion des sessions dans les SPA, consultez la section [Traiter les jetons d’authentification](/fr-CA/docs/quickstart/spa/vanillajs#handle-authentication-tokens) du [guide de démarrage rapide pour les applications monopages JavaScript](/fr-CA/docs/quickstart/spa/vanillajs).

**Voir l’implémentation en** [**Angular 2**](/fr-CA/docs/get-started/architecture-scenarios/spa-api/spa-implementation-angular2#2-authorize-the-user).

<div id="get-the-user-profile">
  ### Obtenir le profil utilisateur
</div>

<Card title="Extraire les informations du jeton">
  Cette section montre comment récupérer les informations de l’utilisateur à l’aide du Jeton d’accès et du [point de terminaison /userinfo](https://auth0.com/docs/api/authentication#get-user-info). Pour éviter cet appel d’API, vous pouvez simplement décoder l’ID Token [à l’aide d’une bibliothèque](https://jwt.io/#libraries-io) (assurez-vous de le valider d’abord). Si vous avez besoin de renseignements supplémentaires sur l’utilisateur, envisagez d’utiliser [notre Management API](https://auth0.com/docs/api/management/v2#!/Users/get_users_by_id) depuis votre serveur principal.
</Card>

La méthode `client.userInfo` peut être appelée en lui passant le `authResult.accessToken` renvoyé afin de récupérer les informations du profil de l’utilisateur. Elle enverra une requête au [point de terminaison /userinfo](https://auth0.com/docs/api/authentication#get-user-info) et renverra l’objet `user`, qui contient les informations de l’utilisateur, comme dans l’exemple ci-dessous :

```json lines theme={null}
{
    "email_verified": "false",
    "email": "test@example.com",
    "clientID": "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH",
    "updated_at": "2017-02-07T20:50:33.563Z",
    "name": "tester9@example.com",
    "picture": "https://gravatar.com/avatar/example.png",
    "user_id": "auth0|123456789012345678901234",
    "nickname": "tester9",
    "created_at": "2017-01-20T20:06:05.008Z",
    "sub": "auth0|123456789012345678901234"
}
```

Vous pouvez accéder à n’importe quelle propriété dans la fonction `callback` passée lors de l’appel à la fonction `userInfo` :

```javascript lines theme={null}
const accessToken = authResult.accessToken;

auth0.client.userInfo(accessToken, (err, profile) => {
  if (profile) {
    // Obtenir le surnom et l'image de profil de l'utilisateur
    var nickname = profile.nickname;
    var picture = profile.picture;
  }
});
```

**Consultez l’implémentation dans** [**Angular 2**](/fr-CA/docs/get-started/architecture-scenarios/spa-api/spa-implementation-angular2#3-get-the-user-profile).

<div id="display-ui-elements-conditionally-based-on-scope">
  ### Afficher des éléments d’interface conditionnellement selon le `scope`
</div>

Selon le `scope` de l’utilisateur, vous pouvez afficher ou masquer certains éléments d’interface. Pour déterminer le scope accordé à un utilisateur, vous devez stocker le scope initialement demandé pendant le processus d’autorisation. Lorsqu’un utilisateur est autorisé, le `scope` est également renvoyé dans `authResult`.

Si le `scope` dans `authResult` est vide, cela signifie que tous les scopes demandés ont été accordés. Si le `scope` dans `authResult` n’est pas vide, cela signifie qu’un ensemble différent de scopes a été accordé, et vous devez utiliser ceux de `authResult.scope`.

**Consultez l’implémentation dans** [**Angular 2**](/fr-CA/docs/get-started/architecture-scenarios/spa-api/spa-implementation-angular2#4-display-ui-elements-conditionally-based-on-scope).

<div id="call-the-api">
  ### Appeler l’API
</div>

Pour accéder aux ressources sécurisées de votre API, le Jeton d’accès de l’utilisateur authentifié doit être inclus dans les requêtes qui lui sont adressées. Pour ce faire, envoyez le Jeton d’accès dans un en-tête `Authorization` à l’aide du schéma `Bearer`.

**Voir l’implémentation dans** [**Angular 2**](/fr-CA/docs/get-started/architecture-scenarios/spa-api/spa-implementation-angular2#5-call-the-api).

<div id="renew-the-access-token">
  ### Renouveler le Jeton d’accès
</div>

Par mesure de sécurité, il est recommandé de limiter la durée de vie du Jeton d’accès d’un utilisateur. Lorsque vous créez une API dans le <Tooltip tip="Auth0 Dashboard : produit principal d’Auth0 pour configurer vos services." cta="Voir le glossaire" href="/fr-CA/docs/glossary?term=Auth0+dashboard">Auth0 Dashboard</Tooltip>, la durée de vie par défaut est de `7200` secondes (2 heures), mais elle peut être configurée pour chaque API.

Une fois expiré, un Jeton d’accès ne peut plus être utilisé pour accéder à une API. Pour y accéder de nouveau, il faut obtenir un nouveau Jeton d’accès.

Pour obtenir un nouveau Jeton d’accès, vous pouvez répéter le flux d’authentification utilisé pour obtenir le Jeton d’accès initial. Dans une SPA, ce n’est pas idéal, car vous ne voudrez peut-être pas rediriger l’utilisateur loin de sa tâche en cours pour qu’il termine de nouveau le flux d’authentification.

Dans ce genre de cas, vous pouvez utiliser l’[authentification silencieuse](/fr-CA/docs/authenticate/login/configure-silent-authentication). L’authentification silencieuse vous permet d’exécuter un flux d’authentification dans lequel Auth0 ne renvoie que des redirections, jamais une page de connexion. Cela exige toutefois que l’utilisateur soit déjà connecté au moyen de l’[authentification unique (SSO)](/fr-CA/docs/authenticate/single-sign-on).

**Consultez l’implémentation dans** [**Angular 2**](/fr-CA/docs/get-started/architecture-scenarios/spa-api/spa-implementation-angular2#6-renew-the-access-token).
