ITSkillsCenter
Cybersécurité

Sécuriser ses API : bonnes pratiques pour développeurs

3 min de lecture
Miniature - Sécuriser ses API : bonnes pratiques pour développeurs

Ce que vous saurez faire à la fin

  1. Sécuriser l’auth avec Argon2id + JWT rotatifs
  2. Implémenter OAuth 2.1 + PKCE
  3. Protéger contre OWASP Top 10
  4. Rate-limit et audit log immuable
  5. Scan secrets automatique en CI

Étape 1 — Argon2id

import argon2 from "argon2";

const hash = await argon2.hash(pwd, {
  type: argon2.argon2id,
  memoryCost: 65536,
  timeCost: 3,
  parallelism: 2,
});

if (!(await argon2.verify(hash, pwdFourni))) {
  await new Promise(r => setTimeout(r, 300));
  throw new Error("identifiants invalides");
}

Étape 2 — JWT avec refresh rotatif

import jwt from "jsonwebtoken";
import crypto from "crypto";

function issueTokens(user: { id: number }) {
  const access = jwt.sign({ sub: user.id }, process.env.ACCESS_SECRET!, 
    { expiresIn: "15m" });
  const jti = crypto.randomUUID();
  const refresh = jwt.sign({ sub: user.id, jti }, process.env.REFRESH_SECRET!,
    { expiresIn: "7d" });
  db.query("INSERT INTO refresh_tokens(jti,user_id,expires_at) VALUES($1,$2,now()+interval '7 days')",
    [jti, user.id]);
  return { access, refresh };
}

Étape 3 — Validation Zod

import { z } from "zod";
const CreerUser = z.object({
  email: z.string().email().max(255),
  telephone: z.string().regex(/^\+221 ?[0-9]{9}$/),
});

app.post("/users", (req, res) => {
  const r = CreerUser.safeParse(req.body);
  if (!r.success) return res.status(422).json({ errors: r.error.errors });
});

Étape 4 — Rate limiting

import { rateLimit } from "express-rate-limit";

const loginLimiter = rateLimit({
  windowMs: 15 * 60_000,
  max: 5,
  keyGenerator: req => req.ip + ":" + (req.body.email || ""),
});
app.post("/auth/login", loginLimiter, loginHandler);

Étape 5 — SQL paramétré

// JAMAIS
db.query(`SELECT * FROM users WHERE email='${req.body.email}'`);

// TOUJOURS
db.query("SELECT * FROM users WHERE email = $1", [req.body.email]);

Étape 6 — Anti-SSRF

const BLOQUES = [/^10\./, /^192\.168\./, /^127\./, /^169\.254\./];

async function fetchExterne(url: string) {
  const ip = await dns.lookup(new URL(url).hostname);
  if (BLOQUES.some(re => re.test(ip.address))) throw new Error("IP interne");
  return fetch(url, { redirect: "error" });
}

Étape 7 — CORS strict

import cors from "cors";
app.use(cors({
  origin: ["https://app.example.sn"],
  credentials: true,
}));

Étape 8 — Audit log immuable

CREATE TABLE audit_log (
  id BIGSERIAL PRIMARY KEY,
  ts TIMESTAMPTZ DEFAULT now(),
  user_id BIGINT,
  action TEXT NOT NULL,
  ressource TEXT NOT NULL,
  ip INET,
  result TEXT
);
REVOKE UPDATE, DELETE ON audit_log FROM PUBLIC;

Étape 9 — Webhooks signés

function verifyWebhook(req, secret: string) {
  const ts = parseInt(req.headers["x-timestamp"]);
  if (Math.abs(Date.now() - ts) > 5 * 60_000) throw new Error("stale");
  const expected = crypto.createHmac("sha256", secret)
    .update(`${ts}.${req.rawBody}`).digest("hex");
  if (!crypto.timingSafeEqual(Buffer.from(expected),
    Buffer.from(req.headers["x-signature"])))
    throw new Error("invalid signature");
}

Étape 10 — Scan secrets gitleaks

brew install gitleaks
gitleaks detect --source . --verbose

# Pre-commit hook
echo "gitleaks protect --staged --verbose" > .husky/pre-commit

Checklist

✓ Argon2id
✓ JWT 15 min + refresh 7j révocable
✓ Zod sur 100% des endpoints
✓ Rate limit login + global
✓ SQL paramétré uniquement
✓ CORS whitelist
✓ Audit log append-only
✓ gitleaks pre-commit
✓ Secrets dans vault
Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité