Les clés d'API (API keys) qui fuient à l'intérieur d'applications mobiles sont une plaie récurrente. Que ce soit une clé Google Maps, une clé Firebase, ou un token d'un service tiers, je vois trop souvent ces secrets se retrouver dans des dépôts Git publics, des APK/IPA décompilés ou des bundles JavaScript. Dans cet article, je partage mon expérience pratique pour éviter ces fuites dans des apps React Native et Flutter. Je vous propose des stratégies concrètes, des outils, et des erreurs courantes à éviter — le tout en langage clair et actionnable.
Pourquoi une API key dans l'app est dangereuse
Avant d'entrer dans le vif du sujet, rappelons pourquoi il est risqué d'embarquer une clé statique dans l'application :
Une application mobile peut être décompilée ou analysée : les bundles JS (React Native) ou les fichiers Dart/asset (Flutter) peuvent révéler des secrets.Une clé compromise permet l'abus du service (facturation, quotas explosés, modification de données).Il est difficile de révoquer et remplacer rapidement une clé si elle est intégrée partout.Principes de base à appliquer systématiquement
Je travaille toujours à partir de quelques principes simples :
Ne jamais hardcoder une clé secrète dans le code source qui sera livré au client.Ne pas confondre clé publique (destinée à être utilisée côté client, ex. clé de mesure publique) et secret (doit rester côté serveur).Utiliser des tokens courte durée et un backend comme intermédiaire pour les opérations sensibles.Stratégies recommandées pour React Native et Flutter
Voici les stratégies que j'applique selon la sensibilité du secret.
Déporter la logique sensible vers un backend : la meilleure pratique est d'implémenter un serveur (ou serverless) qui détient la clé sensible et expose une API propre pour l'app. L'app demande un token temporaire ou exécute une action via le backend. Ainsi, la clé principale n'est jamais embarquée.Utiliser des tokens courts et renouvelables : au lieu d'une clé permanente, générez des tokens JWT ou OAuth de courte durée. Si le token fuit, son impact est limité dans le temps.Restreindre l'utilisation des clés côté fournisseur : beaucoup de fournisseurs (Google, AWS, Firebase, Mapbox) permettent de limiter une clé par IP, bundle ID (iOS), SHA1 fingerprint (Android) ou référent. Configurez au maximum ces restrictions.Stockage sécurisé côté client : si vous devez stocker un token côté appareil, utilisez des stockages sécurisés.React Native : react-native-keychain, react-native-encrypted-storage, ou l’API Native Keystore/Keychain.Flutter : flutter_secure_storage (utilise Keychain/Keystore), ou le plugin platform-specific via MethodChannels.Ne pas se fier aux fichiers .env côté client : des solutions comme react-native-config ou flutter_dotenv facilitent la gestion des variables d'environnement, mais ces variables finissent souvent compilées dans l'app et peuvent être récupérées par un attaquant. Utile pour config non sensibles, dangereux pour les secrets.Obfuscation et minification : cela n'est pas une protection forte, mais peut ralentir l'analyse.React Native : activer ProGuard/R8 pour la partie Android native, activer Hermes (bytecode) et minifier le bundle JS.Flutter : activer le tree shaking et l'obfuscation (obfuscate: true + --split-debug-info).Utiliser des mécanismes natifs : Keychain/Keystore : les solutions natives protègent mieux les secrets que les fichiers dans l'espace stockage classique. Toujours coupler avec stockage chiffré.Certificate pinning et HTTPS strict : pour empêcher les attaques MITM, activez le certificate pinning pour l'API backend ou utilisez mTLS si possible.Pratiques CI/CD et gestion des secrets
La fuite survient souvent via Git ou via les pipelines. Voici les mesures que je recommande :
Ne jamais stocker des secrets dans le dépôt : utilisez les secrets des plateformes CI (GitHub Actions Secrets, GitLab CI variables, Bitrise Secrets).Configurer des scans automatiques pour détecter les secrets dans les commits : GitGuardian, TruffleHog, Gitleaks.Utiliser des outils d'encryptage pour les dépôts partagés : git-crypt, sops ou HashiCorp Vault pour stocker des secrets chiffrés.Mettre des hooks pre-commit pour empêcher le commit accidentel de fichiers contenant "API_KEY", "SECRET", "PASSWORD".Révocation et rotation
Anticipez la compromission :
Automatisez la rotation des clés et tokens.Surveillez l'utilisation des clés (logs, anomalies de traffic) et déclenchez des révoquations si nécessaire.Préparez des clés secondaires pour un remplacement rapide dans le cas d'une fuite.Approches pratiques selon le cas d'usage
Voici comment j'aborderais différents besoins concrets :
Accès à une API backend privée : authentification via OAuth2 + refresh tokens. Backend détient les secrets des services tiers.Utilisation d'APIs publiques (ex. Google Maps) : mettre une clé restreinte par bundle ID/SHA1 et limiter les endpoints autorisés.Upload de fichiers vers un stockage (S3, GCS) : génération de pré-signed URLs côté serveur, jamais exposer les credentials.Comparatif des options de stockage côté client
| Option | Protection | Cas d'usage |
| Fichier plat dans bundle | Faible (facilement extractible) | Jamais pour secrets |
| Env vars compilées (.env) | Moyen (relié au build) | Configs non sensibles |
| Keychain / Keystore | Élevé (chiffrage matériel possible) | Stockage local de tokens |
| Backend + tokens courte durée | Très élevé (clé principale jamais côté client) | Recommandé pour opérations sensibles |
Outils et services que j'utilise ou conseille
Vault (HashiCorp) pour la gestion centralisée des secrets en prod.Google Secret Manager / AWS Secrets Manager pour stocker secrets backend.React Native : react-native-keychain, react-native-encrypted-storage.Flutter : flutter_secure_storage.Scanners : GitGuardian, Gitleaks, TruffleHog, Snyk.Exemples d'erreurs que j'ai vues et comment les corriger
J’ai vu des développeurs :
Committer un .env contenant une clé. Corrigé par : suppression et rotation immédiate de la clé + mise en place d'un scan de commit.Mettre la clé Firebase dans le bundle et penser que c'est sans risque. Corrigé par : configuration des règles Firebase et limitation des domaines/UIDs.Compromettre un token de build stocké dans le CI. Corrigé par : migration vers les secrets natifs du CI et rotation.Checklist rapide à appliquer aujourd'hui
Vérifier qu'aucune clé sensible n'est dans Git (traces de commits inclus).Configurer les secrets dans le CI et supprimer toute variable en clair du repo.Déployer un backend pour actions sensibles et émettre des tokens courte durée.Activer Keychain/Keystore pour le stockage local si nécessaire.Mise en place de scans automatiques et alertes pour détection de fuite.Si vous voulez, je peux vous fournir un template GitHub Actions pour empêcher le commit de secrets, ou une architecture de référence (schéma) pour intégrer un backend de tokenisation dans une app React Native ou Flutter. Dites-moi la stack que vous utilisez et je vous l'adapte.