// Node.js avec jsonwebtoken
const jwt = require('jsonwebtoken');
// Création d'un token
const generateToken = (user) => {
return jwt.sign(
{
id: user.id,
email: user.email,
role: user.role
},
process.env.JWT_SECRET,
{ expiresIn: '24h' }
);
};
// Middleware de vérification
const verifyToken = (req, res, next) => {
try {
const token = req.headers.authorization.split(' ')[1];
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (error) {
res.status(401).json({ message: 'Invalid token' });
}
};
// Utilisation dans les routes
app.post('/login', async (req, res) => {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user || !user.comparePassword(password)) {
return res.status(401).json({
message: 'Invalid credentials'
});
}
const token = generateToken(user);
res.json({ token });
});
// Route protégée
app.get('/profile', verifyToken, (req, res) => {
res.json({ user: req.user });
});
// Configuration Passport avec Google OAuth2
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "/auth/google/callback"
},
async (accessToken, refreshToken, profile, done) => {
try {
let user = await User.findOne({ googleId: profile.id });
if (!user) {
user = await User.create({
googleId: profile.id,
email: profile.emails[0].value,
name: profile.displayName
});
}
return done(null, user);
} catch (error) {
return done(error, null);
}
}
));
// Routes OAuth2
app.get('/auth/google',
passport.authenticate('google', {
scope: ['profile', 'email']
})
);
app.get('/auth/google/callback',
passport.authenticate('google', {
failureRedirect: '/login'
}),
(req, res) => {
const token = generateToken(req.user);
res.redirect(`/dashboard?token=${token}`);
}
);
// bcrypt
const bcrypt = require('bcrypt');
class User {
async hashPassword(password) {
const salt = await bcrypt.genSalt(12);
return bcrypt.hash(password, salt);
}
async comparePassword(password) {
return bcrypt.compare(password, this.password);
}
}
// argon2
const argon2 = require('argon2');
class User {
async hashPassword(password) {
return argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 2 ** 16,
timeCost: 3,
parallelism: 1
});
}
async comparePassword(password) {
return argon2.verify(this.password, password);
}
}
// Configuration CORS
const cors = require('cors');
app.use(cors({
origin: ['https://example.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization']
}));
// Protection CSRF
const csrf = require('csurf');
const cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(csrf({ cookie: true }));
app.get('/form', (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
// Frontend
<form action="/submit" method="POST">
<input type="hidden"
name="_csrf"
value="{{csrfToken}}">
<!-- autres champs -->
</form>
const helmet = require('helmet');
// Configuration de base
app.use(helmet());
// Configuration avancée
app.use(
helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'", "https://api.example.com"]
}
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
},
frameguard: {
action: "deny"
},
referrerPolicy: {
policy: "strict-origin-when-cross-origin"
}
})
);
// Rate limiting
const rateLimit = require('express-rate-limit');
app.use(
rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limite par IP
message: 'Too many requests, please try again later.'
})
);