Sécuriser vos apps Firebase avec App Check et reCAPTCHA en 2026
Vos endpoints Firebase sont-ils vraiment appelés par votre app ? Ou par un script qui a copié la clé API ? App Check et reCAPTCHA Enterprise apportent la réponse en 2026.

Il y a une confusion fréquente chez les développeurs qui débutent avec Firebase : ils pensent que la clé API (apiKey: "AIza...") qu'ils collent dans leur code frontend protège leur backend. Ce n'est pas le cas. La clé API Firebase est publique par conception. Tu peux la voir dans le code source d'à peu près n'importe quelle app web Firebase, il suffit d'ouvrir l'inspecteur du navigateur. Elle sert uniquement à identifier ton projet, pas à le protéger.
La vraie sécurité Firebase repose sur trois couches : les règles Firestore/Storage (qui contrôlent qui peut lire ou écrire quoi selon l'utilisateur connecté), les rôles IAM (qui contrôlent les accès administrateurs et service accounts), et enfin Firebase App Check (qui vérifie que la requête vient bien de ton app authentique et non d'un script tiers).
Cette troisième couche est celle que beaucoup ignorent — et qui coûte cher quand un bot commence à taper sur les endpoints Cloud Functions ou Firestore. Cet article couvre en profondeur Firebase App Check et reCAPTCHA Enterprise en 2026, avec les providers, la mise en œuvre côté web/Android/iOS, l'enforcement, la replay protection et les coûts.
Le vrai problème que résout App Check
Imaginons une app de commande de plats livrés à Abidjan, construite avec Firebase. Le frontend utilise :
- Firebase Auth pour connecter le client (numéro de téléphone + OTP)
- Firestore pour stocker les commandes
- Cloud Functions pour appeler CinetPay et pour envoyer des notifications au restaurant
Un jour, un concurrent envoie un script qui scrape ton catalogue en simulant un client. Ou pire, un attaquant tape sur ton endpoint sendOtp (Cloud Function) des milliers de fois par minute pour épuiser ton crédit SMS Twilio. Ou bien, un bot s'inscrit à ton programme de fidélité en créant 50 000 faux comptes pour capter les bonus de bienvenue.
Firebase Auth ne bloque rien : les comptes sont légitimes du point de vue Firebase (l'attaquant s'inscrit vraiment via signInWithPhoneNumber). Les règles Firestore ne bloquent rien : l'utilisateur créé est authentifié, il peut donc écrire dans les collections que tu lui autorises. La clé API est publique, l'attaquant l'a extraite du bundle web en 30 secondes.
C'est là qu'intervient App Check : il atteste que la requête entrante vient bien de ton app authentique (le vrai binaire Android que tu as signé et publié, ou la vraie build web que tu contrôles), et non d'un script qui simule cette app.
App Check vs Firebase Auth : la distinction cruciale
Beaucoup mélangent les deux. La distinction est simple :
- Firebase Auth identifie l'utilisateur : qui est la personne qui utilise l'app ?
- App Check identifie le client : est-ce que la requête vient bien de mon app officielle ?
Une requête peut être :
- Authentifiée (Auth OK) mais provenant d'un script (App Check KO) → probablement un abus
- Non authentifiée (anonymous, endpoint public) mais provenant de l'app (App Check OK) → OK
- Authentifiée et de l'app (Auth OK, App Check OK) → cas normal
- Non authentifiée et non de l'app (Auth KO, App Check KO) → blocage total
App Check et Auth se combinent : tu veux les deux vérifiés pour les endpoints sensibles.
Les providers App Check disponibles en 2026
App Check utilise des attestation providers natifs de chaque plateforme, qui savent démontrer cryptographiquement que le code qui tourne est bien ton binaire officiel.
Android : Play Integrity API
Sur Android, le provider standard est Play Integrity API (Google). Il remplace définitivement l'ancien SafetyNet qui a été mis à la retraite. Play Integrity vérifie :
- Que l'app est bien celle publiée sur Google Play (empreinte du binaire signée)
- Que le device est un vrai device Android non compromis (bootloader intact, non-rooté, non-modifié)
- Que Google Play Services est présent et fonctionnel
En cas d'échec (émulateur, device rooté, APK modifié), Play Integrity refuse d'émettre le token. App Check refuse alors la requête côté Firebase.
iOS et macOS : App Attest
Sur iOS 14+ et macOS 11+, le provider est App Attest (Apple). Il utilise le Secure Enclave du device pour attester cryptographiquement de l'identité de ton app.
Pour les anciens iOS, un fallback DeviceCheck est possible mais recommandé uniquement en transition.
Web : reCAPTCHA Enterprise
Sur web, le provider recommandé est reCAPTCHA Enterprise (successeur de reCAPTCHA v3). Il évalue passivement le comportement de la session (mouvements de souris, timing, contexte navigateur, IP, réputation) et retourne un token cryptographiquement signé.
Alternative : reCAPTCHA v3 classique, qui reste supporté mais avec moins de fonctionnalités que Enterprise.
Debug provider (pour développer)
Pendant le développement local ou en émulateur, tu ne peux pas passer par Play Integrity ou App Attest. Firebase fournit un debug provider : tu génères un token de debug, tu l'enregistres dans la console Firebase, et pendant la session de dev tes appels sont autorisés.
Comment ça marche techniquement
Le flow App Check est simple sur le papier :
- Ton app démarre. Le SDK App Check demande au provider natif un jeton d'attestation (Play Integrity, App Attest ou reCAPTCHA Enterprise selon la plateforme).
- Le provider valide la légitimité de l'app et retourne un jeton signé cryptographiquement.
- Le SDK Firebase envoie ce jeton avec chaque requête vers Firestore, Cloud Storage, Cloud Functions, Realtime Database.
- Côté serveur Firebase, le jeton est vérifié. S'il est valide, la requête est traitée. Sinon, elle est rejetée.
- Le jeton a un TTL court (typiquement 1 heure). Le SDK le renouvelle automatiquement.
Ce qui rend App Check efficace, c'est que le jeton n'est pas stockable par un attaquant : chaque jeton est lié à une session, à un device et a une durée de vie limitée. Recopier un jeton dans un script tiers ne marche pas au-delà de quelques minutes.
Configuration pas à pas : activer App Check
Dans la console Firebase, va dans "App Check" (dans la section "Build" ou "Sécurité" selon la version de l'UI).
Pour chaque app enregistrée (web, Android, iOS), tu configures un provider :
- Web : renseigne ta clé de site reCAPTCHA Enterprise (créée depuis Google Cloud Console)
- Android : renseigne l'empreinte SHA-256 de ta clé de signature APK, et active Play Integrity
- iOS : renseigne ton App ID et active App Attest
Puis choisis le mode :
- Monitoring (mode observation) : App Check journalise les requêtes légitimes et illégitimes mais ne bloque rien. À utiliser en premier pour évaluer l'impact.
- Enforced (mode actif) : App Check bloque toute requête sans jeton valide. À activer quand tu es confiant.
Ne passe jamais directement en Enforced. Reste 2 à 4 semaines en Monitoring, vérifie que 99 % de tes requêtes légitimes ont un jeton valide, corrige les cas edge (users sur vieux navigateurs, apps beta non enregistrées), puis passe en Enforced.
Intégration Web avec reCAPTCHA Enterprise
Voici le code d'initialisation d'un client web :
import { initializeApp } from "firebase/app";
import {
initializeAppCheck,
ReCaptchaEnterpriseProvider
} from "firebase/app-check";
const app = initializeApp({
apiKey: "AIza...",
authDomain: "mon-app.firebaseapp.com",
projectId: "mon-app",
appId: "1:12345:web:abcd"
});
const appCheck = initializeAppCheck(app, {
provider: new ReCaptchaEnterpriseProvider("6Lc...site-key..."),
isTokenAutoRefreshEnabled: true
});
C'est tout. Toutes les requêtes Firebase depuis ce client incluent désormais automatiquement le jeton App Check.
Pour le mode debug en local, ajoute avant initializeAppCheck :
if (import.meta.env.DEV) {
self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
}
Le SDK génère un jeton de debug affiché dans la console. Copie-le et enregistre-le dans App Check → Debug tokens dans la console Firebase.
Intégration Android avec Play Integrity
Dans ton build.gradle (module app) :
implementation platform("com.google.firebase:firebase-bom:33.5.0")
implementation "com.google.firebase:firebase-appcheck-playintegrity"
implementation "com.google.firebase:firebase-appcheck-debug"
Dans ta classe Application :
import com.google.firebase.appcheck.FirebaseAppCheck
import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
FirebaseApp.initializeApp(this)
FirebaseAppCheck.getInstance().installAppCheckProviderFactory(
PlayIntegrityAppCheckProviderFactory.getInstance()
)
}
}
En debug builds, utilise DebugAppCheckProviderFactory pendant le développement local.
Intégration iOS avec App Attest
Dans ton AppDelegate.swift :
import FirebaseCore
import FirebaseAppCheck
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let providerFactory = AppAttestProviderFactory()
AppCheck.setAppCheckProviderFactory(providerFactory)
FirebaseApp.configure()
return true
}
}
class AppAttestProviderFactory: NSObject, AppCheckProviderFactory {
func createProvider(with app: FirebaseApp) -> AppCheckProvider? {
return AppAttestProvider(app: app)
}
}
En debug schemes, utilise AppCheckDebugProviderFactory.
Enforcement dans les Cloud Functions
Depuis 2023, tu peux forcer App Check directement dans tes Cloud Functions 2ème gen. Sur une callable function :
import { onCall, HttpsError } from "firebase-functions/v2/https";
export const createOrder = onCall(
{
enforceAppCheck: true, // rejette les requêtes sans App Check valide
consumeAppCheckToken: true // active la replay protection
},
async (request) => {
if (!request.auth) {
throw new HttpsError("unauthenticated", "Login requis");
}
// ...
}
);
L'option enforceAppCheck: true rejette toute requête dont le jeton App Check est manquant ou invalide, avec une erreur 401. L'option consumeAppCheckToken: true active la replay protection : un jeton ne peut être utilisé qu'une seule fois. Cela empêche un attaquant de récupérer un jeton légitime et de le rejouer massivement.
Vérification manuelle du token côté serveur (HTTPS request)
Pour un endpoint HTTPS non callable (ex. un webhook custom), tu vérifies manuellement le token avec le SDK Admin :
import { onRequest } from "firebase-functions/v2/https";
import { getAppCheck } from "firebase-admin/app-check";
export const customEndpoint = onRequest(async (req, res) => {
const token = req.header("X-Firebase-AppCheck");
if (!token) {
res.status(401).send("App Check token manquant");
return;
}
try {
await getAppCheck().verifyToken(token);
} catch (err) {
res.status(401).send("App Check token invalide");
return;
}
// Requête légitime, procéder
res.status(200).json({ ok: true });
});
reCAPTCHA seul, en dehors d'App Check
Il est aussi possible d'utiliser reCAPTCHA seul (sans App Check Firebase) pour protéger des formulaires ou des endpoints spécifiques. En 2026, trois variantes existent :
reCAPTCHA v2 : la case à cocher "Je ne suis pas un robot", ou l'invisible sur clic. Toujours utile pour les formulaires publics, mais frictionnel.
reCAPTCHA v3 : évaluation passive silencieuse, retourne un score de 0.0 à 1.0 sur la probabilité que la session soit humaine. Pas de challenge visible.
reCAPTCHA Enterprise : la version Google Cloud de reCAPTCHA. En plus du score, elle donne :
- Action verification : signature que l'action provient bien de la page où reCAPTCHA était chargé
- Multi-factor authentication assessments
- Password leak detection
- Account takeover detection
- Intégration avec Cloud Armor / WAF
Enterprise est facturé au-delà d'un quota gratuit (1 million d'évaluations/mois gratuites, puis quelques centimes par milliers). C'est la version recommandée en 2026 pour tout usage sérieux, et c'est celle qu'App Check web utilise en interne.
Erreurs classiques et débogage
SafetyNet ne marche plus : normal, il a été retiré par Google en 2024. Migre vers Play Integrity.
Le SDK App Check tourne en debug mode en prod : vérifie que tu n'as pas laissé la variable FIREBASE_APPCHECK_DEBUG_TOKEN activée dans un build prod.
Quota reCAPTCHA Enterprise dépassé : monitor tes évaluations dans Google Cloud, active des budget alerts, ajuste ton scoring si trop de faux positifs.
Requêtes bloquées en Enforced alors qu'elles semblent légitimes : très souvent des utilisateurs sur vieux navigateurs (Safari 14 et moins, Chrome hors des dernières versions), sur émulateurs ou sur devices Android modifiés. Regarde les logs App Check dans la console Firebase avant d'incriminer ton code.
Token invalide sur les Callable Functions : vérifie que ton SDK client est à jour (Firebase v9+ obligatoire), et que l'app est bien enregistrée dans la console avec le bon provider.
Coûts en 2026
App Check : gratuit. Aucun coût direct de Firebase.
Play Integrity : gratuit jusqu'à un quota très large (10 000 requêtes par jour par app), au-delà tarification Google Play.
App Attest : gratuit, inclus dans iOS/macOS.
reCAPTCHA Enterprise : 1 million d'évaluations gratuites par mois, puis tarif Cloud (typiquement 1 à 2 $ par 1 000 évaluations sur les features avancées, moins sur les évaluations basiques).
Pour une app avec 100 000 utilisateurs actifs mensuels qui fait 5 à 10 appels API/jour, tu restes très largement dans les quotas gratuits.
Cas concret : sécuriser une app de commande à Abidjan
Prenons un cas réel. Tu construis une app mobile Android de commande de repas pour Abidjan. Elle utilise Firebase (Auth SMS, Firestore, Storage, Cloud Functions pour appeler CinetPay).
Sans App Check :
- Un concurrent peut extraire ton APK, décompiler, extraire la clé API, et scraper ton catalogue Firestore en boucle.
- Un attaquant peut spammer ton endpoint
sendOtppour épuiser ton crédit Twilio (500 000 FCFA en une nuit possible). - Des faux comptes peuvent s'inscrire massivement pour toucher les bonus de bienvenue.
Avec App Check activé (Play Integrity + reCAPTCHA Enterprise web + App Attest iOS) :
- Un APK modifié ou décompilé ne peut plus émettre de token Play Integrity valide → les requêtes Firestore sont rejetées.
- L'endpoint
sendOtpest protégé parenforceAppCheck: true+consumeAppCheckToken: true→ un jeton ne peut être rejoué. - Les inscriptions frauduleuses sont largement filtrées par la combinaison Auth + App Check + rate limiting.
Coût mensuel additionnel : 0 FCFA (largement dans les quotas gratuits). ROI : évident.
Bonnes pratiques que je recommande
- Active App Check dès le début du projet, pas après un incident
- Reste 2 à 4 semaines en Monitoring avant de passer en Enforced
- Active
enforceAppCheck: truesur toutes les callable functions publiques - Active
consumeAppCheckToken: truesur les endpoints sensibles (paiement, OTP, inscription) - Utilise reCAPTCHA Enterprise plutôt que v3 pour la partie web
- Configure les debug tokens proprement pour tes équipes dev, ne partage jamais en clair
- Monitor la console App Check régulièrement pour détecter les anomalies (spikes de requêtes rejetées)
- Combine App Check avec règles Firestore strictes et rate limiting dans tes Functions
- Ne remplace jamais Firebase Auth par App Check. Les deux sont complémentaires.
- Rotate les clés reCAPTCHA Enterprise régulièrement, comme n'importe quel secret
Ressources officielles
- Firebase App Check (docs) : firebase.google.com/docs/app-check
- Play Integrity API : developer.android.com/google/play/integrity
- Apple App Attest : developer.apple.com/documentation/devicecheck/preparing-to-use-the-app-attest-service
- reCAPTCHA Enterprise : cloud.google.com/recaptcha-enterprise/docs
En 2026, une app Firebase sérieuse doit avoir App Check activé. Ce n'est plus une option de confort mais une exigence de base, au même titre que les règles Firestore ou l'HTTPS. La combinaison App Check + reCAPTCHA Enterprise te protège du scraping, du replay, des faux comptes et de l'épuisement de ressources — trois problèmes qui coûtent réellement de l'argent dans le contexte africain où le coût du SMS et de la donnée n'est pas anodin. Le coût de mise en œuvre est faible, le coût du non-usage peut être élevé. Ne remets pas à plus tard.