Auth0 et RGPD : guide d'implémentation complet pour la conformité

Implémentez Auth0 en conformité totale avec le RGPD : consentement, droit à l'oubli, portabilité des données, audit trails et DPA avec Okta.

Par Auth0.Expert · 2025-05-05 · 16 min de lecture

RGPD Conformité Auth0 Privacy

Auth0 et RGPD : guide d'implémentation complet

TL;DR

Le RGPD impose des obligations strictes sur le traitement des données personnelles. Auth0, en tant que sous-traitant, signe un DPA (Data Processing Agreement) avec Okta. Vous devez configurer la résidence des données, implémenter le droit à l'oubli, et maintenir des audit trails complets.

Points de douleur courants

Fondamentaux RGPD avec Auth0

Avant d'entrer dans chaque section, voici comment Auth0 s’adapte aux exigences RGPD pour chaque point clé.

1. Résidence des données (Data Residency)

Auth0 propose des tenants dans différentes régions :

Régions disponibles :
- US (us.auth0.com) — par défaut
- EU (eu.auth0.com) — Irlande (AWS eu-west-1)
- AU (au.auth0.com) — Australie
- JP (jp.auth0.com) — Japon (Private Cloud uniquement)

Important : La région ne peut pas être changée après création du tenant. Créez votre tenant EU dès le départ.

La commande suivante permet de vérifier dans quelle région votre tenant Auth0 a été créé, ce qui est essentiel pour la conformité RGPD.

# Vérifier la région de votre tenant
curl -s "https://YOUR_DOMAIN/.well-known/openid-configuration" | jq .issuer
# https://YOUR_DOMAIN.eu.auth0.com/ = tenant EU ✅
# https://YOUR_DOMAIN.us.auth0.com/ = tenant US ⚠️

2. Data Processing Agreement (DPA)

Okta/Auth0 fournit un DPA automatiquement accepté via les CGU :

DPA Okta disponible sur : https://www.okta.com/agreements/
- Inclut les clauses contractuelles types (SCC) pour les transferts hors UE
- Couvre Auth0 comme sous-traitant (Art. 28 RGPD)
- Sous-traitants d'Okta listés sur : https://www.okta.com/subprocessors/

Pour garantir la conformité RGPD auprès de votre DPO, le script suivant permet de générer un registre conforme du traitement des données personnelles avec Auth0.

# Script de documentation RGPD pour votre DPO
import json
from datetime import datetime

rgpd_record = {
    "traitement": "Authentification utilisateurs",
    "responsable_traitement": "Votre Entreprise SAS",
    "sous_traitant": "Okta Inc. (Auth0)",
    "dpa_reference": "Okta DPA v3.0",
    "base_legale": "Intérêt légitime / Consentement",
    "finalite": "Gestion des accès et authentification",
    "categories_donnees": [
        "email", "nom", "prénom", "identifiants",
        "logs de connexion", "device fingerprint"
    ],
    "localisation": "EU (Irlande - AWS eu-west-1)",
    "duree_retention": "Données actives + 1 an après suppression",
    "mesures_securite": [
        "Chiffrement AES-256 au repos",
        "TLS 1.2+ en transit",
        "MFA disponible",
        "SOC2 Type II certifié",
        "ISO 27001 certifié"
    ],
    "date_mise_a_jour": datetime.now().isoformat()
}

print(json.dumps(rgpd_record, indent=2, ensure_ascii=False))

Ce script automatise la documentation RGPD liée à Auth0 pour centraliser les principaux éléments de conformité.

3. Consentement explicite au signup

Avant le code, il est important de s'assurer que la collecte du consentement des utilisateurs est auditable lors de l'inscription, pour répondre aux exigences RGPD.

// Auth0 Action : Post-Registration — enregistrer le consentement
exports.onExecutePostUserRegistration = async (event) => {
  const { user, request } = event;

  // Vérifier que le consentement a été donné
  // (via paramètre dans le state ou les métadonnées)
  const consentGiven = event.user.user_metadata?.consent_given;
  const consentTimestamp = event.user.user_metadata?.consent_timestamp;

  if (!consentGiven) {
    // Logger l'absence de consentement
    console.log(`User ${user.user_id} registered without explicit consent`);
  }

  // Enregistrer dans votre système d'audit
  await fetch("https://api.votre-app.com/audit/consent", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${process.env.AUDIT_API_TOKEN}`
    },
    body: JSON.stringify({
      user_id: user.user_id,
      email: user.email,
      consent_given: consentGiven,
      consent_timestamp: consentTimestamp || new Date().toISOString(),
      ip_address: request.ip,
      user_agent: request.user_agent,
      consent_version: "v2.1",
      purposes: ["authentication", "service_emails"]
    })
  });
};

Ce code vérifie et journalise le consentement utilisateur juste après l'inscription, puis enregistre la preuve dans votre registre d'audit pour conformité.

Pour collecter ce consentement dans les pages Auth0 Universal Login, adaptez l’URL de connexion pour ajouter l’information nécessaire à la personnalisation du formulaire.

// Universal Login customization — ajouter checkbox consentement
// Dans le formulaire d'inscription (New Universal Login)
// Utilisez les custom fields ou le paramètre screen_hint

// Option 1 : Paramètre dans authorize URL
const loginUrl = new URL(`https://${AUTH0_DOMAIN}/authorize`);
loginUrl.searchParams.set("client_id", CLIENT_ID);
loginUrl.searchParams.set("redirect_uri", CALLBACK_URL);
loginUrl.searchParams.set("response_type", "code");
loginUrl.searchParams.set("scope", "openid profile email");
loginUrl.searchParams.set("screen_hint", "signup");
// Passer le consentement via state
loginUrl.searchParams.set("state", btoa(JSON.stringify({
  consent_required: true,
  consent_version: "v2.1"
})));

Ce code permet de préciser et de transmettre l'intention de demande de consentement à la page d'inscription d'Auth0.

4. Droit à l'oubli (Right to Erasure)

Voici un exemple de classe Python qui orchestre la suppression complète d’un utilisateur Auth0, incluant la révocation des tokens, la purge MFA et la notification des systèmes internes.

import requests
from datetime import datetime

class RGPDUserDeletion:
    def __init__(self, domain: str, mgmt_token: str):
        self.domain = domain
        self.headers = {"Authorization": f"Bearer {mgmt_token}"}
        self.base_url = f"https://{domain}/api/v2"

    def delete_user_complete(self, user_id: str, reason: str = "user_request") -> dict:
        """
        Suppression complète RGPD d'un utilisateur Auth0.
        Retourne un rapport de suppression.
        """
        report = {
            "user_id": user_id,
            "deletion_timestamp": datetime.utcnow().isoformat(),
            "reason": reason,
            "steps": []
        }

        # 1. Récupérer les données avant suppression (pour audit)
        user = self._get_user(user_id)
        report["email_hash"] = self._hash_email(user.get("email", ""))
        report["steps"].append("user_data_archived")

        # 2. Révoquer tous les refresh tokens
        self._revoke_grants(user_id)
        report["steps"].append("grants_revoked")

        # 3. Supprimer les Guardian enrollments (MFA)
        self._delete_guardian_enrollments(user_id)
        report["steps"].append("mfa_enrollments_deleted")

        # 4. Supprimer l'utilisateur Auth0
        resp = requests.delete(
            f"{self.base_url}/users/{user_id}",
            headers=self.headers
        )
        resp.raise_for_status()
        report["steps"].append("auth0_user_deleted")

        # 5. Notifier vos systèmes internes
        self._notify_internal_systems(user_id, user)
        report["steps"].append("internal_systems_notified")

        return report

    def _get_user(self, user_id: str) -> dict:
        resp = requests.get(
            f"{self.base_url}/users/{user_id}",
            headers=self.headers
        )
        return resp.json()

    def _revoke_grants(self, user_id: str):
        resp = requests.get(
            f"{self.base_url}/users/{user_id}/grants",
            headers=self.headers
        )
        grants = resp.json()
        for grant in grants:
            requests.delete(
                f"{self.base_url}/grants/{grant['id']}",
                headers=self.headers
            )

    def _delete_guardian_enrollments(self, user_id: str):
        resp = requests.get(
            f"{self.base_url}/users/{user_id}/enrollments",
            headers=self.headers
        )
        if resp.ok:
            for enrollment in resp.json():
                requests.delete(
                    f"{self.base_url}/guardian/enrollments/{enrollment['id']}",
                    headers=self.headers
                )

    def _notify_internal_systems(self, user_id: str, user_data: dict):
        # Déclencher vos webhooks internes
        import os
        webhook_url = os.getenv("DELETION_WEBHOOK_URL")
        if webhook_url:
            requests.post(webhook_url, json={
                "event": "user.deleted",
                "user_id": user_id,
                "email_hash": self._hash_email(user_data.get("email", "")),
                "timestamp": datetime.utcnow().isoformat()
            })

    @staticmethod
    def _hash_email(email: str) -> str:
        import hashlib
        return hashlib.sha256(email.encode()).hexdigest()

Ce script orchestre toutes les étapes nécessaires pour garantir la suppression RGPD d'un utilisateur Auth0 avec rapport détaillé.

5. Portabilité des données

Pour respecter le droit à la portabilité, voici comment extraire toutes les données d’un utilisateur (profil, logs, appareils, MFA) via Auth0 Management API en format JSON.

def export_user_data(user_id: str, mgmt_token: str, domain: str) -> dict:
    """
    Export complet des données d'un utilisateur (Art. 20 RGPD).
    """
    headers = {"Authorization": f"Bearer {mgmt_token}"}
    base = f"https://{domain}/api/v2"

    # Données de profil
    user = requests.get(f"{base}/users/{user_id}", headers=headers).json()

    # Logs de connexion (90 derniers jours max)
    logs = requests.get(
        f"{base}/users/{user_id}/logs",
        headers=headers,
        params={"per_page": 100}
    ).json()

    # Appareils enregistrés
    devices = requests.get(
        f"{base}/users/{user_id}/devices",
        headers=headers
    ).json()

    # MFA enrollments
    enrollments = requests.get(
        f"{base}/users/{user_id}/enrollments",
        headers=headers
    ).json()

    return {
        "export_date": datetime.utcnow().isoformat(),
        "format": "JSON - RGPD Art.20",
        "profile": {
            "user_id": user.get("user_id"),
            "email": user.get("email"),
            "name": user.get("name"),
            "given_name": user.get("given_name"),
            "family_name": user.get("family_name"),
            "picture": user.get("picture"),
            "created_at": user.get("created_at"),
            "updated_at": user.get("updated_at"),
            "user_metadata": user.get("user_metadata", {}),
        },
        "connection_logs": [
            {
                "date": log.get("date"),
                "type": log.get("type"),
                "ip": log.get("ip"),
                "location": log.get("location_info", {}),
            }
            for log in logs
        ],
        "mfa_devices": enrollments,
        "total_logins": user.get("logins_count", 0),
    }

Ce code centralise toutes les informations utilisateur nécessaires pour répondre à une demande de portabilité dans un format exploitable.

Rétention des logs Auth0

Avant de choisir votre plan Auth0, ce tableau récapitule les durées de conservation des logs pour garantir votre politique de rétention conforme au RGPD.

Politique de rétention par plan :
┌─────────────────┬──────────────────┬───────────────────┐
│ Plan            │ Rétention logs   │ Export            │
├─────────────────┼──────────────────┼───────────────────┤
│ Free            │ 2 jours          │ Non               │
│ Developer Pro   │ 7 jours          │ Non               │
│ Professional    │ 30 jours         │ Log Streaming     │
│ Enterprise      │ 30 jours + SSO   │ Log Streaming     │
└─────────────────┴──────────────────┴───────────────────┘

Pour conformité RGPD :
- Streamer les logs vers votre SIEM (max 90 jours recommandé)
- Anonymiser les IPs après 30 jours
- Supprimer les logs utilisateur sur demande de suppression

Tableau de conformité RGPD / Auth0

Retrouvez ici la correspondance entre les exigences légales RGPD et l’implémentation via Auth0.

| Obligation RGPD | Feature Auth0 | Action requise | |---|---|---| | Résidence données EU | EU tenant | Créer tenant eu.auth0.com | | DPA sous-traitant | DPA Okta (auto) | Vérifier DPA Okta | | Consentement | Actions | Implémenter Post-Registration | | Droit d'accès | Management API | Endpoint export utilisateur | | Droit à l'oubli | DELETE /users/{id} | Workflow suppression complet | | Portabilité | Management API | Export JSON des données | | Notification violation | Auth0 → SIEM | Log streaming + alerting | | Privacy by design | Auth0 natif | Minimisation champs profil |

Checklist DPO Auth0

Pour piloter la conformité Auth0 au RGPD, utilisez cette checklist opérationnelle pour le DPO.

✅ Tenant créé en région EU (eu.auth0.com)
✅ DPA Okta signé et archivé
✅ Sous-traitants Okta listés dans registre
✅ Consentement explicite au signup (Action)
✅ Endpoint droit d'accès implémenté
✅ Workflow droit à l'oubli testé
✅ Log streaming configuré (SIEM/storage)
✅ Rétention logs < 90 jours
✅ Notification violations (< 72h) testée
✅ Analyse d'impact (AIPD) documentée
✅ Privacy policy mise à jour (Auth0 en sous-traitant)

Auth0.Expert accompagne votre mise en conformité RGPD complète, de l'audit initial à la documentation DPO.


Autres articles