> ## 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 de la SPA pour le scénario d’architecture SPAs + API

# Configuration de l’API et de la SPA (SPAs + 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) + "*****MASQUÉ*****";
          }
          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 mettre en place une API pour notre scénario.

<Callout icon="file-lines" color="#0EA5E9" iconType="regular">
  Par souci de simplicité, nous limiterons notre mise en œuvre à l’authentification et à l’autorisation. Comme vous le verrez dans les exemples, l’entrée de feuille de temps sera codée en dur et l’API n’enregistrera pas cette entrée. Elle renverra simplement 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, votre application doit être dirigée vers son URL. Par exemple, si vous aviez une API capable de renvoyer soit des commandes, soit 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 ou `GET /orders` pourrait récupérer le jeu de données d’une ou de plusieurs commandes.
</Card>

Pour cette mise en œuvre, 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 qui permettra à un employé de créer une nouvelle entrée de feuille de temps.

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

**Voir la mise en œuvre en** [**Node.js**](/docs/fr-ca/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 avec un <Tooltip tip="Access Token : Identifiant d’autorisation, sous la forme d’une chaîne opaque ou d’un JWT, utilisé pour accéder à une API." cta="Voir le glossaire" href="/docs/fr-ca/glossary?term=Access+Token">jeton d’accès</Tooltip> bearer dans l’en-tête, la première chose à faire est de valider le jeton. Cela comprend 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 les suivantes :

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

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

Le processus de validation comprend aussi la vérification des Application permissions (scopes), mais nous y reviendrons séparément dans le paragraphe suivant de ce document.

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

**Voir la mise en œuvre dans** [**Node.js**](/docs/fr-ca/get-started/architecture-scenarios/spa-api/api-implementation-nodejs#2-secure-the-api-endpoints).

<div id="check-the-applications-permissions">
  ### Vérifier les permissions 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 permissions requises pour accéder aux ressources protégées.

Pour ce faire, l’API doit vérifier les [scopes](/docs/fr-ca/get-started/apis/scopes) du JWT décodé. Ce claim fait partie du payload, et il s’agit d’une liste de chaînes séparées par des espaces.

**Consultez la mise en œuvre dans** [**Node.js**](/docs/fr-ca/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, il faut s’assurer que nous retournons uniquement les feuilles de temps qui appartiennent à l’utilisateur qui effectue la requête; pour ajouter une nouvelle feuille de temps, il faut s’assurer que celle-ci est associée à l’utilisateur qui effectue la requête.

L’une des claims JWT standard est la claim `sub`, qui identifie le principal auquel la claim se rapporte. Dans le cas du flow Implicit Grant, cette claim contiendra l’identité de l’utilisateur, c’est-à-dire l’identifiant unique de l’utilisateur Auth0. Vous pouvez vous en servir pour associer des informations dans des systèmes externes à un utilisateur précis.

Vous pouvez aussi utiliser une custom claim pour ajouter un autre attribut de l’utilisateur — comme son adresse courriel — à l’access token et vous en servir pour identifier l’utilisateur de façon unique.

**Consultez la mise en œuvre dans** [**Node.js**](/docs/fr-ca/get-started/architecture-scenarios/spa-api/api-implementation-nodejs#4-determine-the-user-identity).

<div id="implement-the-spa">
  ## Mettre en place la SPA
</div>

Dans cette section, nous verrons comment mettre en place 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](/docs/fr-ca/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 transmettre les valeurs de configuration suivantes :

* **clientID** : La valeur de votre <Tooltip tip="Client ID : valeur d’identification attribuée à votre ressource enregistrée par Auth0." cta="Voir le glossaire" href="/docs/fr-ca/glossary?term=Client+Id">Client Id</Tooltip> Auth0. Vous pouvez la récupérer dans les Settings de votre Application du [Dashboard](https://manage.auth0.com/#/applications%7D).
* **domain** : La valeur de votre domaine Auth0. Vous pouvez la récupérer dans les Settings de votre Application du [Dashboard](https://manage.auth0.com/#/applications%7D).
* **responseType** : Indique le flux d’authentification à utiliser. Pour une SPA qui utilise l’**Implicit Flow**, 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 également le renvoi d’un <Tooltip tip="ID Token : justificatif destiné au client lui-même, plutôt qu’à l’accès à une ressource." cta="Voir le glossaire" href="/docs/fr-ca/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 d’une application (Client ID) pour un ID Token ou d’une API (API Identifier) pour un jeton d’accès." cta="Voir le glossaire" href="/docs/fr-ca/glossary?term=audience">audience</Tooltip>** : La valeur de votre identifiant d’API. Vous pouvez la récupérer dans les [Settings de votre API](https://manage.auth0.com/#/apis%7D) du Dashboard.
* **redirectUri** : L’URL vers laquelle Auth0 doit rediriger l’utilisateur après son authentification.
* **scope** : Les [scopes](/docs/fr-ca/get-started/apis/scopes) qui déterminent les renseignements à renvoyer dans le ID Token et le jeton d’accès. Un scope de `openid profile` renverra tous les renseignements du profil utilisateur dans le ID Token. Vous devez aussi demander les scopes requis pour appeler l’API, dans ce cas-ci les scopes `read:timesheets create:timesheets`. Cela garantira que le jeton d’accès possède 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 vous redirigera vers le **redirectUri** que vous avez indiqué lors de la configuration de la nouvelle instance de l’application Auth0. À cette étape, vous devrez appeler la méthode `parseHash()` , qui analyse un fragment de hachage d’URL afin d’extraire le résultat d’une réponse d’authentification 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 renseignements du profil utilisateur
* **accessToken** : un jeton d’accès pour l’API, spécifié par l’**audience**.
* **expiresIn** : une chaîne contenant la durée d’expiration (en secondes) du jeton d’accès.

Déterminez où il convient le mieux de [stocker les jetons](/docs/fr-ca/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 au moyen du [Authorization Code Flow](/docs/fr-ca/get-started/authentication-and-authorization-flow/authorization-code-flow) ou du [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/docs/fr-ca/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce).

Si vous avez une application monopage (SPA) sans serveur backend correspondant, votre SPA devrait demander de nouveaux jetons à la connexion et les conserver en mémoire sans les enregistrer. Pour effectuer des appels d’API, votre SPA utiliserait alors la copie en mémoire du jeton.

Pour un exemple de gestion des sessions dans les SPA, consultez la section [Gérer les jetons d’authentification](/docs/fr-ca/quickstart/spa/vanillajs#handle-authentication-tokens) du [Quickstart pour application monopage en Javascript](/docs/fr-ca/quickstart/spa/vanillajs).

**Voir la mise en œuvre avec** [**Angular 2**](/docs/fr-ca/get-started/architecture-scenarios/spa-api/spa-implementation-angular2#2-authorize-the-user).

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

<Card title="Extraire des 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 le ID Token [à l’aide d’une bibliothèque](https://jwt.io/#libraries-io) (assurez-vous de d’abord le valider). 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) à partir de votre backend.
</Card>

La méthode `client.userInfo` peut être appelée en lui passant le `authResult.accessToken` retourné 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 retournera 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 laquelle de ces propriétés dans la fonction de rappel fournie lors de l’appel de la fonction `userInfo` :

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

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

**Consultez la mise en œuvre dans** [**Angular 2**](/docs/fr-ca/get-started/architecture-scenarios/spa-api/spa-implementation-angular2#3-get-the-user-profile).

<div id="display-ui-elements-conditionally-based-on-scope">
  ### Afficher conditionnellement des éléments de l’interface utilisateur en fonction du scope
</div>

En fonction du `scope` de l’utilisateur, vous pourriez souhaiter afficher ou masquer certains éléments de l’interface utilisateur. Pour déterminer le scope accordé à un utilisateur, vous devrez stocker le scope initialement demandé lors du processus d’autorisation. Une fois l’utilisateur autorisé, le `scope` sera é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 devriez utiliser ceux de `authResult.scope`.

**Voir la mise en œuvre dans** [**Angular 2**](/docs/fr-ca/get-started/architecture-scenarios/spa-api/spa-implementation-angular2#4-display-ui-elements-conditionally-based-on-scope).

<div id="call-the-api">
  ### Faire une requête à 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`.

**Consultez la mise en œuvre dans** [**Angular 2**](/docs/fr-ca/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 : le principal produit d’Auth0 pour configurer vos services." cta="Voir le glossaire" href="/docs/fr-ca/glossary?term=Auth0+dashboard">Auth0 Dashboard</Tooltip>, la durée de vie par défaut est de `7200` secondes (2 heures), mais vous pouvez la définir 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, vous devez 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 l’idéal, car vous ne voudrez peut-être pas rediriger l’utilisateur hors de sa tâche en cours pour qu’il recommence le flux d’authentification.

Dans ce type de situation, vous pouvez utiliser l’[authentification silencieuse](/docs/fr-ca/authenticate/login/configure-silent-authentication). L’authentification silencieuse vous permet d’exécuter un flux d’authentification dans lequel Auth0 répond uniquement par des redirections, jamais avec une page de connexion. Cela exige toutefois que l’utilisateur ait déjà ouvert une session au moyen de l’[authentification unique (SSO)](/docs/fr-ca/authenticate/single-sign-on).

**Voir la mise en œuvre dans** [**Angular 2**](/docs/fr-ca/get-started/architecture-scenarios/spa-api/spa-implementation-angular2#6-renew-the-access-token).
