Aller au contenu principal

Authentification et sécurité

Sécuriser votre application ChatGPT

Une application qui manipule des données utilisateur, se connecte à des API et traite des paiements doit être sécurisée dès la conception. Le Apps SDK intègre des mécanismes d’authentification et de sécurité que vous devez comprendre et configurer correctement.

Les modes d’authentification

Le SDK supporte trois modes d’authentification selon votre cas d’usage :

Mode Cas d'usage Complexité
Aucune App publique sans données personnelles Minimale
Clé API Service tiers avec clé utilisateur Simple
OAuth 2.0 Connexion à un compte utilisateur Standard

OAuth 2.0 : le standard recommandé

Pour la plupart des applications, OAuth 2.0 est le choix approprié. Il permet à l’utilisateur de connecter son compte sans partager son mot de passe.

Configuration dans le manifest

{
  "auth": {
    "type": "oauth2",
    "clientId": "${OAUTH_CLIENT_ID}",
    "authorizationUrl": "https://monsite.com/oauth/authorize",
    "tokenUrl": "https://monsite.com/oauth/token",
    "scopes": ["read:profile", "write:orders"],
    "pkce": true
  }
}

Flux côté serveur

// Votre serveur OAuth
app.get("/oauth/authorize", (req, res) => {
  const { client_id, redirect_uri, state, code_challenge } = req.query;

  // Vérifier le client_id
  if (client_id !== process.env.CHATGPT_APP_CLIENT_ID) {
    return res.status(400).json({ error: "Client inconnu" });
  }

  // Afficher la page de connexion / consentement
  res.render("authorize", { state, redirect_uri, scopes: req.query.scope });
});

app.post("/oauth/token", async (req, res) => {
  const { code, code_verifier } = req.body;

  // Vérifier le code et le PKCE verifier
  const session = await validateAuthCode(code, code_verifier);

  res.json({
    access_token: session.accessToken,
    refresh_token: session.refreshToken,
    expires_in: 3600,
    token_type: "Bearer",
  });
});

Utiliser le token dans les actions

app.action("getMyOrders", {
  description: "Récupère les commandes de l'utilisateur connecté",
  auth: "required", // Force l'authentification
  handler: async (_, context) => {
    // Le token est automatiquement disponible
    const response = await fetch("https://api.monsite.com/me/orders", {
      headers: {
        Authorization: `Bearer ${context.auth.accessToken}`,
      },
    });
    return response.json();
  },
});

Authentification par clé API

Pour les services tiers (Notion, GitHub, etc.), l’utilisateur fournit sa propre clé :

{
  "auth": {
    "type": "api_key",
    "header": "X-API-Key",
    "instructions": "Entrez votre clé API depuis les paramètres de votre compte"
  }
}

Le SDK stocke la clé de manière sécurisée côté OpenAI. Elle est injectée dans le context de vos actions.

Sécurité des actions

Validation des entrées

Validez toujours les données reçues, même si le schema les type :

import { z } from "zod";

const orderSchema = z.object({
  productId: z.string().uuid(),
  quantity: z.number().int().min(1).max(100),
  couponCode: z.string().optional(),
});

handler: async (params) => {
  const validated = orderSchema.parse(params);
  // Utiliser validated, pas params
}

Rate limiting

Protégez vos endpoints contre les abus :

export const searchAction = defineAction({
  name: "search",
  description: "Recherche dans le catalogue",
  rateLimit: {
    maxCalls: 20,       // 20 appels max
    windowMs: 60_000,   // par minute
    perUser: true,       // par utilisateur
  },
  handler: async ({ query }) => { /* ... */ },
});

Protection CSRF et vérification des signatures

Le SDK signe chaque requête envoyée à votre serveur. Vérifiez ces signatures :

import { verifyWebhookSignature } from "@openai/apps-sdk";

app.post("/webhook", (req, res) => {
  const isValid = verifyWebhookSignature(
    req.body,
    req.headers["x-openai-signature"],
    process.env.WEBHOOK_SECRET
  );

  if (!isValid) {
    return res.status(401).json({ error: "Signature invalide" });
  }

  // Traiter le webhook
});

Bonnes pratiques de sécurité

  • Ne stockez jamais de tokens en clair dans votre code ou vos logs
  • Activez PKCE pour tous les flux OAuth (protection contre l’interception)
  • Validez les entrées avec un schema strict (zod, joi) en plus du typage SDK
  • Limitez les scopes OAuth au strict minimum nécessaire
  • Vérifiez les signatures de chaque webhook reçu
  • Utilisez HTTPS pour tous vos endpoints sans exception
  • Expirez les tokens : access_token court (1h), refresh_token plus long (30j)

Mise en pratique

Configurez l’authentification OAuth pour une app qui se connecte à un CRM :

  1. Définissez les scopes nécessaires (lecture contacts, création opportunités)
  2. Implémentez les endpoints /authorize et /token
  3. Ajoutez une action getContacts qui utilise le token pour appeler le CRM
  4. Gérez le cas du token expiré avec un refresh automatique

Points clés à retenir

  • OAuth 2.0 avec PKCE est le mode recommandé pour la plupart des apps
  • Le context des actions contient automatiquement les tokens d’authentification
  • Validez les entrées côté serveur même si le SDK les type
  • Le rate limiting protège vos endpoints contre les abus
  • Vérifiez les signatures des webhooks pour authentifier les requêtes OpenAI