Files
THE-TIP-TOP/backend/src/app.js
Emma781227 464d666343 Connexion via Google (OAuth 2.0)
Ajoute l'authentification Google en complément de la connexion par mot de
passe. Le callback OAuth émet le même JWT que la connexion classique, donc
le middleware d'authentification et ProtectedRoute restent inchangés.

Backend
- stratégie passport-google-oauth20 dans src/config/passport.js
- routes GET /api/auth/google et /google/callback, documentées dans Swagger
- un compte existant avec le même email est rattaché automatiquement au
  compte Google, et son email passe vérifié
- les routes répondent 503 si les identifiants ne sont pas configurés,
  plutôt que de faire échouer le démarrage du serveur
- login et changePassword ne comparent plus un hash inexistant sur les
  comptes sans mot de passe

Base de données
- password devient nullable
- colonnes provider, providerId et avatarUrl, index unique sur le couple
  provider/providerId

Frontend
- page /auth/callback qui récupère le token et redirige selon le rôle
- boutons Google de Connexion et Inscription branchés
- boutons Facebook désactivés en attendant les identifiants Meta

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 00:23:18 +02:00

60 lines
2.1 KiB
JavaScript

const express = require("express");
const cors = require("cors");
const helmet = require("helmet");
const rateLimit = require("express-rate-limit");
require("dotenv").config();
const authRoutes = require("./routes/auth.routes");
const gameRoutes = require("./routes/game.routes");
const employeeRoutes = require("./routes/employee.routes");
const adminRoutes = require("./routes/admin.routes");
const swaggerUi = require("swagger-ui-express");
const swaggerSpec = require("./docs/swagger");
const { passport } = require("./config/passport");
const app = express();
const allowedOrigins = (process.env.FRONTEND_URL || "http://localhost:5173").split(",");
// La CSP par défaut de helmet bloque les scripts inline de Swagger UI :
// on l'applique partout sauf sur /api-docs, où une CSP dédiée (désactivée)
// est posée juste avant de monter Swagger, plus bas.
app.use((req, res, next) => {
if (req.path.startsWith("/api-docs")) return next();
return helmet()(req, res, next);
});
app.use(cors({ origin: allowedOrigins }));
app.use(express.json());
// OAuth stateless : initialize() suffit, aucune session n'est ouverte.
app.use(passport.initialize());
// Anti-bruteforce sur les routes d'authentification uniquement : 20
// tentatives par IP toutes les 15 minutes, sans limiter le reste de l'API
// (participation au jeu, consultation des gains, etc.).
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
limit: 20,
standardHeaders: true,
legacyHeaders: false,
message: { message: "Trop de tentatives, réessayez dans quelques minutes." },
});
app.use("/api/auth/login", authLimiter);
app.use("/api/auth/register", authLimiter);
app.use("/api/auth/forgot-password", authLimiter);
// routes
app.use("/api/auth", authRoutes);
app.use("/api/game", gameRoutes);
app.use("/api/employee", employeeRoutes);
app.use("/api/admin", adminRoutes);
// swagger
app.use("/api-docs", helmet({ contentSecurityPolicy: false }), swaggerUi.serve, swaggerUi.setup(swaggerSpec));
// test route
app.get("/", (req, res) => {
res.json({ message: "API Thé Tip Top opérationnelle" });
});
module.exports = app;