Comprenez les attaques CSRF et comment Angular les prévient avec les tokens XSRF. Configuration HttpClient, bonnes pratiques de sécurité et exemples pratiques.
Introduction
La sécurité des applications web est une préoccupation majeure pour tout développeur. Parmi les nombreuses vulnérabilités OWASP, les attaques CSRF (Cross-Site Request Forgery) représentent une menace sérieuse. Elles permettent à un attaquant de faire exécuter des actions à votre insu sur un site où vous êtes authentifié.
Bonne nouvelle : Angular offre une protection CSRF intégrée et automatique. Mais vous devez comprendre comment ça marche et configurer correctement votre backend pour que la défense soit complète.
Qu'est-ce que le CSRF ? (Scénario réel)
CSRF = Un attaquant pousse un utilisateur authentifié à exécuter des actions sans consentement. Exemple concret :
- Vous êtes connecté à votre banque (session active, cookies authentifiés)
- Un email vous propose de "vérifier votre compte" sur un site louche
- Le site contient du code caché :
<img src="https://votre-banque.com/api/transfer?to=attacker&amount=1000"> - Le navigateur envoie la requête AVEC vos cookies de session
- Boom : 1000€ viré de votre compte sans que vous ayez cliqué nulle part
Comment Angular protège contre le CSRF
Solution : Angular utilise une technique appelée token XSRF synchronisé. Voici le flux :
- ✅ Serveur génère un token aléatoire et le place dans un cookie
- ✅ Angular lit le token depuis le cookie
- ✅ Pour chaque POST/PUT/DELETE, Angular ajoute le token dans un en-tête HTTP
- ✅ Serveur vérifie : le token du cookie = le token de l'en-tête ?
- ✅ Si oui, la requête est autorisée. Si non, rejet (401/403)
Pourquoi ça marche : Un attaquant sur un autre domaine ne peut PAS lire le token du cookie (CORS le bloque). Il ne peut donc pas le mettre dans l'en-tête. Sans le token dans l'en-tête, le serveur rejette la requête.
Configuration XSRF en Angular
Angular 15+ : La protection XSRF est activée par défaut dans les nouvelles applications. Voici comment la configurer explicitement :
// app.config.ts (Angular 14+, standalone)
import { ApplicationConfig } from '@angular/core';
import { withHttpClient, withXsrfConfiguration } from '@angular/common/http';
export const appConfig: ApplicationConfig = {
providers: [
withHttpClient(
withXsrfConfiguration({
cookieName: 'XSRF-TOKEN', // Cookie où Angular lit le token
headerName: 'X-XSRF-TOKEN' // En-tête où Angular envoie le token
})
)
]
};
// app.module.ts (Angular < 14, modules)
import { NgModule } from '@angular/core';
import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http';
@NgModule({
imports: [
HttpClientModule,
HttpClientXsrfModule.withOptions({
cookieName: 'XSRF-TOKEN',
headerName: 'X-XSRF-TOKEN'
})
]
})
export class AppModule { }
Utilisez simplement HttpClient, Angular ajoute le token automatiquement :
// user.service.ts
@Injectable({ providedIn: 'root' })
export class UserService {
constructor(private http: HttpClient) {}
updateProfile(data: any) {
// Angular ajoute AUTOMATIQUEMENT le token XSRF
return this.http.post('/api/profile', data);
}
deleteAccount() {
// Token ajouté automatiquement
return this.http.delete('/api/account');
}
getPublicData() {
// GET = pas de token XSRF (pas nécessaire)
return this.http.get('/api/public');
}
}
Checklist de sécurité XSRF côté backend
Angular fait sa part, mais vous devez configurer votre serveur correctement. Voici comment :
import csurf from 'csurf';
import cookieParser from 'cookie-parser';
import express from 'express';
const app = express();
app.use(express.json());
app.use(cookieParser());
// Middleware CSRF — Valide tous les POST/PUT/DELETE
const csrfProtection = csurf({ cookie: false }); // false = lire du cookie
// Route pour récupérer le token initial
app.get('/api/csrf-token', csrfProtection, (req, res) => {
res.json({ token: req.csrfToken() });
});
// Routes protégées — Le middleware valide automatiquement
app.post('/api/profile', csrfProtection, (req, res) => {
// Si le token est valide, on arrive ici
// Si invalide, csurf lance une erreur 403
res.json({ message: 'Profil mis à jour' });
});
// Erreur handler pour CSRF
app.use((err, req, res, next) => {
if (err.code === 'EBADCSRFTOKEN') {
res.status(403).json({ error: 'Token XSRF invalide' });
} else {
next(err);
}
});
// Cookie sécurisé
res.cookie('XSRF-TOKEN', token, {
httpOnly: false, // Angular doit le lire en JS
secure: true, // HTTPS uniquement
sameSite: 'Strict', // Pas d'envoi cross-site
maxAge: 1000 * 60 * 60 * 24 // 24h
});
- ✅ Générez un token unique par session
- ✅ Validez le token sur TOUS les POST/PUT/DELETE
- ✅ Utilisez SameSite=Strict sur le cookie XSRF
- ✅ Utilisez HTTPS toujours
- ✅ Rejetez (403) si le token est invalide
Conclusion
CSRF est une vulnérabilité grave, mais Angular + bon backend = vous êtes protégé.
- ✅ Angular ajoute le token automatiquement (gratuit)
- ✅ Configurez votre backend pour valider le token
- ✅ Utilisez SameSite=Strict sur le cookie XSRF
- ✅ HTTPS toujours activé
- ✅ Testez : les POST sans token doivent échouer (403)
X-XSRF-TOKEN est présent. Si oui, vous êtes protégé ✅