Contactez-nous

Authentification et en-têtes (Headers)

Apprenez à envoyer des informations d'authentification (tokens, cookies) et d'autres en-têtes dans vos requêtes API depuis React avec fetch et axios.

Sécuriser les communications : Identifier vos requêtes

La plupart des API que vous consommerez nécessiteront une forme d'authentification pour identifier l'utilisateur qui effectue la requête et pour autoriser (ou refuser) l'accès aux ressources protégées. Sans authentification, l'API ne saurait pas qui demande les données ni si cette personne a le droit de les voir ou de les modifier.

Il existe plusieurs mécanismes d'authentification courants pour les API web :

  • Token-based : Après une connexion réussie, le serveur renvoie un token (souvent un JSON Web Token - JWT) au client. Le client doit ensuite inclure ce token dans les en-têtes (headers) de chaque requête subséquente vers les points d'API protégés.
  • Cookie-based : Le serveur établit une session après la connexion et envoie un cookie (souvent marqué `HttpOnly` pour la sécurité) au navigateur. Le navigateur inclut ensuite automatiquement ce cookie dans les requêtes ultérieures vers le même domaine (ou sous-domaines, selon la configuration).
  • API Keys : Pour l'accès à des API publiques ou entre services, une clé d'API unique peut être requise, souvent passée dans un en-tête personnalisé ou comme paramètre d'URL.

Quel que soit le mécanisme utilisé par votre backend, votre application React doit être capable d'inclure les informations d'identification nécessaires (généralement via les en-têtes HTTP) lors de l'envoi des requêtes.

Envoyer des tokens via l'en-tête `Authorization`

L'approche la plus courante pour l'authentification basée sur les tokens consiste à utiliser l'en-tête HTTP Authorization. Le format standard est souvent Authorization: Bearer VOTRE_TOKEN_JWT_OU_AUTRE.

Pour inclure cet en-tête avec l'API `fetch`, vous devez l'ajouter à l'objet `options` :

const token = /* Récupérer le token (depuis l'état, localStorage, etc.) */; 

async function fetchDataWithToken() {
  try {
    const response = await fetch('/api/protected-data', {
      method: 'GET', // ou POST, PUT, etc.
      headers: {
        'Content-Type': 'application/json', // Important pour POST/PUT
        'Authorization': `Bearer ${token}` // Ajout de l'en-tête d'autorisation
      },
      // body: JSON.stringify(data) // Pour POST/PUT
    });
    if (!response.ok) throw new Error('Non autorisé ou autre erreur');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Erreur d'authentification:", error);
  }
}

Avec `axios`, vous passez également l'en-tête dans l'objet de configuration :

import axios from 'axios';

const token = /* Récupérer le token */;

async function postDataWithToken(payload) {
  try {
    const response = await axios.post('/api/protected-resource', payload, {
      headers: {
        'Authorization': `Bearer ${token}`
        // axios ajoute Content-Type: application/json automatiquement si payload est un objet
      }
    });
    console.log('Données postées:', response.data);
  } catch (error) {
    console.error("Erreur post (axios):", error.response?.data || error.message);
  }
}

La question cruciale est de savoir où stocker et comment récupérer le `token` dans votre application React. Les options courantes incluent :

  • Etat global (Redux, Zustand, Context API) : Recommandé pour une meilleure sécurité et un contrôle centralisé. Le token est stocké en mémoire après la connexion.
  • `localStorage` / `sessionStorage` : Facile à utiliser, mais présente des risques de sécurité car le token est accessible via JavaScript et vulnérable aux attaques XSS (Cross-Site Scripting). A utiliser avec prudence, jamais pour des tokens très sensibles.

Gérer l'authentification basée sur les cookies

Si votre backend utilise des sessions et des cookies pour l'authentification, la gestion côté client peut être plus simple ou plus complexe selon la configuration.

Requêtes Same-Origin : Si votre application React et votre API backend sont servies depuis le même domaine (ex: `monsite.com` et `monsite.com/api`), le navigateur gère généralement l'envoi des cookies automatiquement. Vous n'avez souvent rien de spécial à faire dans vos requêtes `fetch` ou `axios`.

Requêtes Cross-Origin : Si votre frontend (ex: `app.monsite.com`) et votre backend (ex: `api.monsite.com` ou un domaine différent) sont sur des origines distinctes, le navigateur, par défaut, n'envoie pas les cookies pour des raisons de sécurité. Pour inclure les cookies dans ces requêtes cross-origin, vous devez :

  • Configurer le backend pour qu'il réponde avec les en-têtes CORS appropriés, notamment `Access-Control-Allow-Credentials: true` et un `Access-Control-Allow-Origin` spécifique (pas `*`).
  • Configurer votre requête côté client pour demander l'envoi des informations d'identification.

Avec `fetch`, vous utilisez l'option `credentials: 'include'` :

fetch('https://api.autredomaine.com/data', {
  credentials: 'include' // Demande d'inclure les cookies (et les en-têtes Auth)
})
.then(/* ... */);

Les autres valeurs possibles pour `credentials` sont `'same-origin'` (défaut) et `'omit'` (ne jamais envoyer).

Avec `axios`, vous utilisez l'option `withCredentials: true` :

axios.get('https://api.autredomaine.com/data', {
  withCredentials: true // Demande d'inclure les cookies
})
.then(/* ... */);

Il est important de noter que les cookies marqués `HttpOnly` par le serveur sont plus sécurisés car ils ne sont pas accessibles via JavaScript dans le navigateur, les protégeant ainsi des attaques XSS. C'est la méthode préférée pour les cookies de session.

Centraliser la configuration des en-têtes

Il est fortement déconseillé de répéter la logique d'ajout des en-têtes d'authentification (ou d'autres en-têtes communs comme `Accept`) dans chaque appel `fetch` ou `axios` de votre application. C'est répétitif, sujet aux erreurs et difficile à maintenir.

Il est préférable de centraliser cette logique :

  • Fonctions Wrapper : Créez vos propres fonctions wrapper autour de `fetch` ou `axios` qui ajoutent automatiquement les en-têtes nécessaires avant d'effectuer la requête réelle.
// Exemple conceptuel de wrapper fetch
async function authenticatedFetch(url, options = {}) {
  const token = getTokenFromStore(); // Fonction pour récupérer le token
  const headers = { 
    ...options.headers, // Préserve les headers spécifiques à l'appel
    'Content-Type': options.body ? 'application/json' : undefined,
    'Authorization': token ? `Bearer ${token}` : undefined 
  };

  // Supprime les headers undefined
  Object.keys(headers).forEach(key => headers[key] === undefined && delete headers[key]);

  return fetch(url, { ...options, headers });
}

// Utilisation:
// authenticatedFetch('/api/data');
// authenticatedFetch('/api/post', { method: 'POST', body: JSON.stringify({ name: 'test' }) });
  • Intercepteurs Axios : Si vous utilisez `axios`, sa fonctionnalité d'intercepteurs est idéale pour cela. Vous pouvez configurer un intercepteur de requête qui ajoute l'en-tête `Authorization` à toutes les requêtes sortantes (ou à certaines d'entre elles).
// Configurer une instance axios centralisée
import axios from 'axios';

const apiClient = axios.create({
  baseURL: '/api'
});

apiClient.interceptors.request.use(config => {
  const token = getTokenFromStore();
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
}, error => {
  return Promise.reject(error);
});

// Utilisation:
// apiClient.get('/users'); 
// apiClient.post('/products', { name: 'widget' });
  • Configuration des bibliothèques de Data Fetching : Les bibliothèques comme React Query ou SWR permettent souvent de configurer une fonction `fetcher` globale où vous pouvez injecter cette logique d'ajout d'en-têtes une seule fois.

Centraliser la configuration des en-têtes rend votre code plus propre, plus sûr et plus facile à maintenir, surtout lorsque les exigences d'authentification évoluent.

Autres en-têtes et conclusion

Outre l'authentification et le `Content-Type`, vous pourriez avoir besoin d'envoyer d'autres en-têtes, comme `Accept` (pour indiquer le format de réponse souhaité, ex: `Accept: application/json`), ou des en-têtes personnalisés (`X-Custom-Header`). Le principe pour les ajouter reste le même : via l'objet `headers` de `fetch` ou `axios`.

En conclusion, la gestion correcte de l'authentification et des en-têtes est cruciale pour interagir avec des API sécurisées depuis React. Que vous utilisiez des tokens `Bearer` ou des cookies, comprenez comment les inclure dans vos requêtes (`Authorization` header, `credentials: 'include'`, `withCredentials: true`). Surtout, centralisez la logique d'ajout des en-têtes pour éviter la répétition et faciliter la maintenance, en utilisant des wrappers, des intercepteurs ou les capacités de configuration de votre bibliothèque de data fetching.