Introduction à Codea Auth

Système d'authentification universel pour vos applications web

Qu'est-ce que Codea Auth ?

Codea Auth est un service d'authentification centralisé qui vous permet d'ajouter un système de connexion complet à vos applications web en quelques lignes de code.

Plutôt que de gérer vous-même les comptes utilisateurs, les mots de passe, la sécurité et toute la complexité associée, vous déléguez cette responsabilité à Codea Auth.

Analogie simple

Pensez à Codea Auth comme le "Se connecter avec Google" ou "Se connecter avec Facebook", mais pour vos propres applications.

Fonctionnalités principales

  • Authentification sécurisée - Gestion complète des comptes utilisateurs
  • OAuth 2.0 - Intégration facile avec tokens temporaires de 10 jours
  • Multi-plateforme - Frontend, Backend, Mobile
  • Protection anti-spam - Rate limiting et hCaptcha intégré
  • Gestion de profils - Photos, informations personnelles, confidentialité
  • Récupération de mot de passe - Envoi d'emails automatique
  • Popup élégante - Interface utilisateur moderne et responsive

Comment ça marche ?

1Vous créez une application dans le dashboard Codea Auth

2Vous intégrez le SDK dans votre site (1 ligne de code)

3Vos utilisateurs se connectent via une popup sécurisée

4Vous recevez leurs informations (nom, email, photo, etc.)

Comparaison avec d'autres solutions

Fonctionnalité Codea Auth Auth0 Firebase DIY
Gratuit Oui Limité Limité Oui
Facile à intégrer Très facile Moyen Facile Difficile
UI incluse Oui Non Non Non
OAuth sécurisé Oui Oui Oui À faire
Protection anti-spam hCaptcha Oui Limité À faire
Prêt à commencer ?

Passez à la section Démarrage rapide pour créer votre première application en 5 minutes !

Démarrage rapide

Intégrez Codea Auth en 5 minutes chrono

� Prérequis

Étape 1 : Créer une application

1Connectez-vous à votre compte

Allez sur Mes Applications

2Cliquez sur "Créer une application"

Remplissez les informations :

  • Nom : Mon Super Site
  • Description : (optionnel)
  • URL de redirection : https://mon-site.com

3Récupérez vos credentials

Vous obtiendrez :

  • App ID : 590551 (6 chiffres)
  • Secret Key : 00a75ea7f31ee... (64 caractères)
Important

Ne partagez JAMAIS votre Secret Key publiquement. Stockez-la dans un fichier .env ou dans les variables d'environnement de votre serveur.

Étape 2 : Intégrer le SDK

Option A : Frontend simple (HTML/JavaScript)

HTML
<!DOCTYPE html>
<html>
<head>
    <title>Mon Site</title>
</head>
<body>
    <button onclick="auth.login()">Se connecter</button>
    <div id="user-info" style="display:none;">
        <p>Bienvenue <span id="username"></span></p>
    </div>

    <!-- SDK Codea Auth -->
    <script src="https://auth.codealuxz.fr/codea-auth-sdk.js"></script>

    <script>
        const auth = new CodeaAuth({
            appId: '590551',
            secretKey: 'VOTRE_SECRET_KEY',
            onSuccess: function(result) {
                console.log('Utilisateur connecté:', result.user);

                // Stocker le token
                localStorage.setItem('userToken', result.token);

                // Afficher les infos
                document.getElementById('username').textContent = result.user.username;
                document.getElementById('user-info').style.display = 'block';
            },
            onError: function(error) {
                console.error('Erreur:', error);
                alert('Erreur de connexion: ' + error.message);
            }
        });
    </script>
</body>
</html>

Option B : Backend sécurisé (Recommandé)

Pour ne pas exposer votre Secret Key, utilisez le système OAuth :

JavaScript (Frontend)
// Frontend : Récupérer le token utilisateur
const auth = new CodeaAuth({
    appId: '590551',  // Public - OK d'exposer
    secretKey: 'SECRET', //  NE PAS EXPOSER EN PROD
    onSuccess: async function(result) {
        // Envoyer le token à votre backend pour vérification
        const response = await fetch('/api/verify-user', {
            method: 'POST',
            headers: { 'Authorization': `Bearer ${result.token}` }
        });

        const data = await response.json();
        console.log('Utilisateur vérifié:', data.user);
    }
});
JavaScript (Backend - Node.js)
// Backend : Vérifier le token utilisateur
app.post('/api/verify-user', async (req, res) => {
    const userToken = req.headers.authorization?.replace('Bearer ', '');

    // 1. Obtenir un access token (caché 10 jours)
    const accessTokenResponse = await fetch('https://auth.codealuxz.fr/api/oauth/token', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            appId: process.env.CODEA_APP_ID,
            secretKey: process.env.CODEA_SECRET_KEY
        })
    });

    const { access_token } = await accessTokenResponse.json();

    // 2. Vérifier l'utilisateur
    const verifyResponse = await fetch('https://auth.codealuxz.fr/api/oauth/verify-user', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            access_token: access_token,
            user_token: userToken
        })
    });

    const data = await verifyResponse.json();

    if (data.valid) {
        res.json({ user: data.user });
    } else {
        res.status(401).json({ error: data.error });
    }
});

C'est tout !

Vous avez maintenant un système d'authentification complet qui gère :

  • Inscription des utilisateurs
  • Connexion / Déconnexion
  • Gestion des profils
  • Récupération de mot de passe
  • Sessions multiples
  • Protection anti-spam
Pour aller plus loin

Consultez la section Comprendre OAuth pour sécuriser votre intégration avec des tokens temporaires.

Comprendre le système OAuth

Sécurisez vos credentials avec des tokens temporaires

Pourquoi OAuth ?

Imaginons que vous intégriez Codea Auth dans votre site. Vous avez deux credentials importants :

  • App ID : 590551 (public, OK de partager)
  • Secret Key : 00a75ea7... (privé, NE JAMAIS partager)
Problème de sécurité

Si vous utilisez directement votre Secret Key dans le frontend (navigateur), n'importe qui peut l'inspecter dans le code source et usurper votre application !

Solution : Tokens temporaires

Au lieu d'utiliser directement votre Secret Key, vous l'échangez contre un Access Token temporaire qui :

  • Expire après 10 jours
  • Peut être révoqué à tout moment
  • Ne compromet pas votre Secret Key
  • Est stocké seulement côté backend

Flux OAuth

┌──────────────┐
│   Frontend   │
│  (Navigateur)│
└──────┬───────┘
       │
       │ 1. Utilisateur se connecte
       │    via popup Codea Auth
       │
       ▼
┌──────────────┐
│ Popup Codea  │ ─────┐
│   Auth       │      │ 2. Retourne token utilisateur
└──────────────┘      │
                      │
       ┌──────────────┘
       │
       ▼
┌──────────────┐
│   Frontend   │ ────────────────┐
└──────────────┘                 │
                                 │ 3. Envoie token au backend
                                 │
       ┌─────────────────────────┘
       │
       ▼
┌──────────────┐
│   Backend    │
│  (Serveur)   │
└──────┬───────┘
       │
       │ 4. Échange Secret Key
       │    contre Access Token
       │
       ▼
┌──────────────┐
│  Codea Auth  │
│     API      │
└──────┬───────┘
       │
       │ 5. Retourne Access Token
       │    (valide 10 jours)
       │
       ▼
┌──────────────┐
│   Backend    │
│  (cache)     │
└──────┬───────┘
       │
       │ 6. Vérifie token utilisateur
       │    avec Access Token
       │
       ▼
┌──────────────┐
│  Codea Auth  │
│     API      │
└──────┬───────┘
       │
       │ 7. Retourne infos utilisateur
       │
       ▼
┌──────────────┐
│   Backend    │ ──────┐
└──────────────┘       │ 8. Envoie au frontend
                       │
       ┌───────────────┘
       │
       ▼
┌──────────────┐
│   Frontend   │
│   (résultat) │
└──────────────┘
    

Les 3 types de tokens

Type Description Durée Où stocker
Secret Key Credential permanent de votre app Illimité Backend seulement (.env)
Access Token Token temporaire pour l'app 10 jours Backend (cache/DB)
User Token Token de session utilisateur Jusqu'à déco Frontend (localStorage)

Implémentation

1. Obtenir un Access Token (Backend)

POST /api/oauth/token
const response = await fetch('https://auth.codealuxz.fr/api/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        appId: process.env.CODEA_APP_ID,
        secretKey: process.env.CODEA_SECRET_KEY
    })
});

const data = await response.json();
// {
//   "access_token": "a1b2c3d4...",
//   "token_type": "Bearer",
//   "expires_in": 864000,  // 10 jours en secondes
//   "expires_at": "2025-10-16T..."
// }

2. Vérifier un utilisateur avec l'Access Token

POST /api/oauth/verify-user
const response = await fetch('https://auth.codealuxz.fr/api/oauth/verify-user', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        access_token: 'VOTRE_ACCESS_TOKEN',
        user_token: 'TOKEN_UTILISATEUR'
    })
});

const data = await response.json();
// {
//   "valid": true,
//   "user": {
//     "username": "johndoe",
//     "firstName": "John",
//     "lastName": "Doe",
//     "email": "[email protected]",
//     ...
//   },
//   "app": {
//     "appId": "590551",
//     "name": "Mon Application"
//   }
// }

3. Utiliser le SDK (automatique)

JavaScript - SDK Backend
const auth = new CodeaAuth({
    appId: process.env.CODEA_APP_ID,
    secretKey: process.env.CODEA_SECRET_KEY,
    mode: 'backend'
});

// Le SDK gère automatiquement l'Access Token
const result = await auth.verifyUserToken(userToken);

if (result.valid) {
    console.log('Utilisateur:', result.user);
} else {
    console.error('Token invalide:', result.error);
}
Astuce

Le SDK cache automatiquement l'Access Token pendant 10 jours. Vous n'avez pas besoin de le gérer manuellement !

Gestion de l'expiration

Les Access Tokens expirent après 10 jours. Voici comment gérer le renouvellement :

JavaScript
class TokenManager {
    constructor(appId, secretKey) {
        this.appId = appId;
        this.secretKey = secretKey;
        this.token = null;
        this.expiry = null;
    }

    async getToken() {
        // Si token valide, le retourner
        if (this.token && this.expiry && new Date() < new Date(this.expiry)) {
            return this.token;
        }

        // Sinon, en générer un nouveau
        const response = await fetch('https://auth.codealuxz.fr/api/oauth/token', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                appId: this.appId,
                secretKey: this.secretKey
            })
        });

        const data = await response.json();
        this.token = data.access_token;
        this.expiry = data.expires_at;

        return this.token;
    }
}

// Utilisation
const tokenManager = new TokenManager(
    process.env.CODEA_APP_ID,
    process.env.CODEA_SECRET_KEY
);

// Automatiquement renouvelé si expiré
const accessToken = await tokenManager.getToken();

Révoquer un Access Token

Si vous pensez qu'un Access Token a été compromis, vous pouvez le révoquer :

POST /api/oauth/revoke
await fetch('https://auth.codealuxz.fr/api/oauth/revoke', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        access_token: 'TOKEN_A_REVOQUER'
    })
});

// Le token est immédiatement invalidé
Prochaine étape

Maintenant que vous comprenez OAuth, apprenez comment intégrer Codea Auth côté backend de manière sécurisée.

Intégration Frontend

Intégrer la popup de connexion dans votre site web

� Vue d'ensemble

L'intégration frontend utilise le SDK JavaScript de Codea Auth pour afficher une popup élégante qui gère toute l'authentification. C'est la méthode la plus simple et la plus rapide.

Quand utiliser l'intégration frontend ?
  • Sites statiques (HTML, CSS, JS)
  • Applications Single Page (React, Vue, Angular)
  • Prototypage rapide
  • Projets sans backend

Installation

Méthode 1 : CDN (Recommandé)

HTML
<script src="https://auth.codealuxz.fr/codea-auth-sdk.js"></script>

Méthode 2 : NPM (Pour React, Vue, etc.)

Bash
npm install @codealuxz/auth-sdk
JavaScript
import CodeaAuth from '@codealuxz/auth-sdk';

Configuration

JavaScript
const auth = new CodeaAuth({
    appId: '590551',              // Votre App ID (requis)
    secretKey: 'your_secret_key', // Votre Secret Key (requis)
    redirectUri: 'https://mon-site.com', // URL de redirection (optionnel)
    mode: 'frontend',             // Mode d'utilisation (optionnel)

    // Callbacks
    onSuccess: function(result) {
        // Appelé quand l'utilisateur se connecte avec succès
        console.log('Token:', result.token);
        console.log('Utilisateur:', result.user);
    },

    onError: function(error) {
        // Appelé en cas d'erreur
        console.error('Erreur:', error.message);
    }
});

Objets retournés

onSuccess - Objet result

JSON
{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
        "id": "507f1f77bcf86cd799439011",
        "username": "johndoe",
        "firstName": "John",
        "lastName": "Doe",
        "email": "[email protected]",
        "phoneNumber": "+33612345678",
        "dateOfBirth": "1990-01-01",
        "profilePicture": "data:image/jpeg;base64,...",
        "createdAt": "2025-01-01T00:00:00.000Z",
        "privacy": {
            "hideFirstName": false,
            "hideLastName": false,
            "hideDateOfBirth": true,
            "hideEmail": false
        }
    }
}

Méthodes du SDK

Méthode Description Retour
auth.login() Ouvre la popup de connexion/inscription void
auth.verifyApp() Vérifie les credentials de l'app Promise<Object>
auth.getAuthorizedUsers() Récupère les utilisateurs autorisés Promise<Array>
auth.getAccessToken() Obtient un access token (mode backend) Promise<string>
auth.verifyUserToken(token) Vérifie un token utilisateur Promise<Object>

Exemples d'utilisation

Exemple 1 : HTML/Vanilla JS

HTML
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Mon Site</title>
    <style>
        .hidden { display: none; }
        .user-card {
            background: #f5f5f5;
            padding: 20px;
            border-radius: 8px;
            margin: 20px 0;
        }
    </style>
</head>
<body>
    <div id="login-section">
        <h1>Bienvenue</h1>
        <button onclick="auth.login()" class="btn-login">
            Se connecter avec Codea Auth
        </button>
    </div>

    <div id="user-section" class="hidden">
        <div class="user-card">
            <img id="user-avatar" src="" alt="Avatar" width="80" height="80">
            <h2>Bienvenue <span id="user-name"></span></h2>
            <p>Email : <span id="user-email"></span></p>
            <p>Membre depuis : <span id="user-since"></span></p>
            <button onclick="logout()">Déconnexion</button>
        </div>
    </div>

    <script src="https://auth.codealuxz.fr/codea-auth-sdk.js"></script>
    <script>
        const auth = new CodeaAuth({
            appId: '590551',
            secretKey: 'votre_secret_key',
            onSuccess: function(result) {
                // Stocker le token
                localStorage.setItem('userToken', result.token);
                localStorage.setItem('userData', JSON.stringify(result.user));

                // Afficher l'utilisateur
                displayUser(result.user);
            },
            onError: function(error) {
                alert('Erreur de connexion : ' + error.message);
            }
        });

        // Afficher les informations utilisateur
        function displayUser(user) {
            document.getElementById('login-section').classList.add('hidden');
            document.getElementById('user-section').classList.remove('hidden');

            document.getElementById('user-name').textContent = user.username;
            document.getElementById('user-email').textContent = user.email || 'Non renseigné';
            document.getElementById('user-avatar').src = user.profilePicture || 'default-avatar.png';

            const since = new Date(user.createdAt).toLocaleDateString('fr-FR');
            document.getElementById('user-since').textContent = since;
        }

        // Déconnexion
        function logout() {
            localStorage.removeItem('userToken');
            localStorage.removeItem('userData');

            document.getElementById('login-section').classList.remove('hidden');
            document.getElementById('user-section').classList.add('hidden');
        }

        // Vérifier si déjà connecté au chargement
        window.addEventListener('DOMContentLoaded', function() {
            const userData = localStorage.getItem('userData');
            if (userData) {
                try {
                    const user = JSON.parse(userData);
                    displayUser(user);
                } catch (e) {
                    console.error('Erreur parsing user data:', e);
                }
            }
        });
    </script>
</body>
</html>

Exemple 2 : React

JSX - App.jsx
import { useState, useEffect } from 'react';

function App() {
    const [user, setUser] = useState(null);
    const [auth, setAuth] = useState(null);

    useEffect(() => {
        // Initialiser le SDK
        const codeaAuth = new window.CodeaAuth({
            appId: '590551',
            secretKey: process.env.REACT_APP_CODEA_SECRET,
            onSuccess: (result) => {
                setUser(result.user);
                localStorage.setItem('userToken', result.token);
            },
            onError: (error) => {
                alert('Erreur : ' + error.message);
            }
        });

        setAuth(codeaAuth);

        // Vérifier si déjà connecté
        const savedUser = localStorage.getItem('userData');
        if (savedUser) {
            setUser(JSON.parse(savedUser));
        }
    }, []);

    const handleLogin = () => {
        auth?.login();
    };

    const handleLogout = () => {
        setUser(null);
        localStorage.removeItem('userToken');
        localStorage.removeItem('userData');
    };

    if (user) {
        return (
            <div className="user-dashboard">
                <img src={user.profilePicture} alt="Avatar" />
                <h1>Bienvenue {user.username}</h1>
                <p>Email : {user.email}</p>
                <button onClick={handleLogout}>Déconnexion</button>
            </div>
        );
    }

    return (
        <div className="login-page">
            <h1>Mon Application</h1>
            <button onClick={handleLogin}>
                Se connecter avec Codea Auth
            </button>
        </div>
    );
}

export default App;

Exemple 3 : Vue.js

Vue - App.vue
<template>
  <div id="app">
    <div v-if="!user" class="login-section">
      <h1>Bienvenue</h1>
      <button @click="login">Se connecter avec Codea Auth</button>
    </div>

    <div v-else class="user-section">
      <img :src="user.profilePicture" alt="Avatar" width="80" />
      <h2>Bienvenue {{ user.username }}</h2>
      <p>Email : {{ user.email }}</p>
      <button @click="logout">Déconnexion</button>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      user: null,
      auth: null
    }
  },
  mounted() {
    this.auth = new window.CodeaAuth({
      appId: '590551',
      secretKey: process.env.VUE_APP_CODEA_SECRET,
      onSuccess: (result) => {
        this.user = result.user;
        localStorage.setItem('userToken', result.token);
        localStorage.setItem('userData', JSON.stringify(result.user));
      },
      onError: (error) => {
        alert('Erreur : ' + error.message);
      }
    });

    // Vérifier si déjà connecté
    const savedUser = localStorage.getItem('userData');
    if (savedUser) {
      this.user = JSON.parse(savedUser);
    }
  },
  methods: {
    login() {
      this.auth.login();
    },
    logout() {
      this.user = null;
      localStorage.removeItem('userToken');
      localStorage.removeItem('userData');
    }
  }
}
</script>
Sécurité

En mode frontend, votre Secret Key est exposée dans le code JavaScript. Pour une sécurité maximale, utilisez plutôt l'intégration backend avec OAuth.

Gestion des sessions

Le token utilisateur doit être stocké et vérifié à chaque chargement de page :

JavaScript
// Au chargement de la page
window.addEventListener('DOMContentLoaded', async function() {
    const token = localStorage.getItem('userToken');

    if (token) {
        // Vérifier si le token est toujours valide
        const response = await fetch('https://auth.codealuxz.fr/api/auth/verify-token', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ token })
        });

        const data = await response.json();

        if (data.valid) {
            // Token valide, afficher l'interface utilisateur
            displayUser(data.user);
        } else {
            // Token invalide, nettoyer
            localStorage.removeItem('userToken');
            localStorage.removeItem('userData');
        }
    }
});
Prochaine étape

Vous savez maintenant intégrer Codea Auth côté frontend ! Pour une architecture plus sécurisée, consultez l'intégration backend.

Intégration Backend

Vérifier et gérer les utilisateurs côté serveur

� Vue d'ensemble

L'intégration backend vous permet de sécuriser vos credentials et de vérifier les utilisateurs côté serveur. Cette approche est fortement recommandée pour la production.

Avantages du backend
  • Secret Key jamais exposée publiquement
  • Tokens OAuth temporaires (10 jours)
  • Validation serveur des utilisateurs
  • Contrôle total sur l'authentification

Architecture

Frontend (Browser)           Backend (Server)           Codea Auth API
       │                            │                          │
       │  1. User clicks login      │                          │
       │─────────────────────────>  │                          │
       │                            │                          │
       │  2. Open Codea popup       │                          │
       │<─────────────────────────  │                          │
       │                            │                          │
       │  3. User authenticates     │                          │
       │────────────────────────────────────────────────────>  │
       │                            │                          │
       │  4. Return user token      │                          │
       │<────────────────────────────────────────────────────  │
       │                            │                          │
       │  5. Send token to backend  │                          │
       │─────────────────────────>  │                          │
       │                            │  6. Get access token     │
       │                            │─────────────────────────>│
       │                            │                          │
       │                            │  7. Return access token  │
       │                            │<─────────────────────────│
       │                            │                          │
       │                            │  8. Verify user token    │
       │                            │─────────────────────────>│
       │                            │                          │
       │                            │  9. Return user data     │
       │                            │<─────────────────────────│
       │                            │                          │
       │  10. Return user to front  │                          │
       │<─────────────────────────  │                          │
    

Configuration

Étape 1 : Variables d'environnement

.env
CODEA_APP_ID=590551
CODEA_SECRET_KEY=00a75ea7f31ee220ea6414d69de7b85b8113b65276e62f74f0403930f333bdb8
CODEA_AUTH_URL=https://auth.codealuxz.fr
Sécurité critique

Ne JAMAIS committer le fichier .env dans Git ! Ajoutez-le au .gitignore

Étape 2 : Installation des dépendances

Node.js

Bash
npm install dotenv node-fetch express

Python

Bash
pip install python-dotenv requests flask

PHP

Bash
composer require vlucas/phpdotenv guzzlehttp/guzzle

Implémentation

Node.js / Express

JavaScript - server.js
require('dotenv').config();
const express = require('express');
const fetch = require('node-fetch');
const app = express();

app.use(express.json());

// Cache pour l'access token
let cachedAccessToken = null;
let tokenExpiry = null;

// Fonction pour obtenir un access token valide
async function getValidAccessToken() {
    // Si le token est encore valide, le retourner
    if (cachedAccessToken && tokenExpiry && new Date() < new Date(tokenExpiry)) {
        return cachedAccessToken;
    }

    // Sinon, en générer un nouveau
    const response = await fetch(`${process.env.CODEA_AUTH_URL}/api/oauth/token`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            appId: process.env.CODEA_APP_ID,
            secretKey: process.env.CODEA_SECRET_KEY
        })
    });

    const data = await response.json();

    if (!response.ok) {
        throw new Error(data.error || 'Erreur génération token');
    }

    cachedAccessToken = data.access_token;
    tokenExpiry = data.expires_at;

    return cachedAccessToken;
}

// Route pour vérifier un utilisateur
app.post('/api/verify-user', async (req, res) => {
    try {
        const userToken = req.headers.authorization?.replace('Bearer ', '');

        if (!userToken) {
            return res.status(401).json({ error: 'Token requis' });
        }

        // Obtenir un access token
        const accessToken = await getValidAccessToken();

        // Vérifier l'utilisateur
        const response = await fetch(`${process.env.CODEA_AUTH_URL}/api/oauth/verify-user`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                access_token: accessToken,
                user_token: userToken
            })
        });

        const data = await response.json();

        if (data.valid) {
            res.json({
                success: true,
                user: data.user
            });
        } else {
            res.status(401).json({
                success: false,
                error: data.error
            });
        }
    } catch (error) {
        console.error('Erreur vérification:', error);
        res.status(500).json({ error: 'Erreur serveur' });
    }
});

// Middleware d'authentification réutilisable
async function authenticateUser(req, res, next) {
    try {
        const userToken = req.headers.authorization?.replace('Bearer ', '');

        if (!userToken) {
            return res.status(401).json({ error: 'Non authentifié' });
        }

        const accessToken = await getValidAccessToken();

        const response = await fetch(`${process.env.CODEA_AUTH_URL}/api/oauth/verify-user`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                access_token: accessToken,
                user_token: userToken
            })
        });

        const data = await response.json();

        if (data.valid) {
            req.user = data.user;
            next();
        } else {
            res.status(401).json({ error: 'Token invalide' });
        }
    } catch (error) {
        res.status(500).json({ error: 'Erreur serveur' });
    }
}

// Route protégée exemple
app.get('/api/user/profile', authenticateUser, (req, res) => {
    res.json({
        message: 'Profil utilisateur',
        user: req.user
    });
});

app.listen(3000, () => {
    console.log('Serveur démarré sur le port 3000');
});

Python / Flask

Python - app.py
import os
from datetime import datetime
from flask import Flask, request, jsonify
from dotenv import load_dotenv
import requests

load_dotenv()

app = Flask(__name__)

# Cache pour l'access token
cached_access_token = None
token_expiry = None

def get_valid_access_token():
    """Obtient un access token valide (avec cache)"""
    global cached_access_token, token_expiry

    # Si le token est encore valide, le retourner
    if cached_access_token and token_expiry:
        if datetime.now() < datetime.fromisoformat(token_expiry.replace('Z', '+00:00')):
            return cached_access_token

    # Sinon, en générer un nouveau
    response = requests.post(
        f"{os.getenv('CODEA_AUTH_URL')}/api/oauth/token",
        json={
            'appId': os.getenv('CODEA_APP_ID'),
            'secretKey': os.getenv('CODEA_SECRET_KEY')
        }
    )

    data = response.json()

    if response.status_code != 200:
        raise Exception(data.get('error', 'Erreur génération token'))

    cached_access_token = data['access_token']
    token_expiry = data['expires_at']

    return cached_access_token

@app.route('/api/verify-user', methods=['POST'])
def verify_user():
    """Vérifie un token utilisateur"""
    try:
        auth_header = request.headers.get('Authorization', '')
        user_token = auth_header.replace('Bearer ', '')

        if not user_token:
            return jsonify({'error': 'Token requis'}), 401

        # Obtenir un access token
        access_token = get_valid_access_token()

        # Vérifier l'utilisateur
        response = requests.post(
            f"{os.getenv('CODEA_AUTH_URL')}/api/oauth/verify-user",
            json={
                'access_token': access_token,
                'user_token': user_token
            }
        )

        data = response.json()

        if data.get('valid'):
            return jsonify({
                'success': True,
                'user': data['user']
            })
        else:
            return jsonify({
                'success': False,
                'error': data.get('error')
            }), 401

    except Exception as e:
        return jsonify({'error': str(e)}), 500

# Décorateur d'authentification
def require_auth(f):
    """Décorateur pour protéger les routes"""
    from functools import wraps

    @wraps(f)
    def decorated_function(*args, **kwargs):
        auth_header = request.headers.get('Authorization', '')
        user_token = auth_header.replace('Bearer ', '')

        if not user_token:
            return jsonify({'error': 'Non authentifié'}), 401

        try:
            access_token = get_valid_access_token()

            response = requests.post(
                f"{os.getenv('CODEA_AUTH_URL')}/api/oauth/verify-user",
                json={
                    'access_token': access_token,
                    'user_token': user_token
                }
            )

            data = response.json()

            if data.get('valid'):
                request.user = data['user']
                return f(*args, **kwargs)
            else:
                return jsonify({'error': 'Token invalide'}), 401

        except Exception as e:
            return jsonify({'error': str(e)}), 500

    return decorated_function

# Route protégée exemple
@app.route('/api/user/profile')
@require_auth
def get_profile():
    return jsonify({
        'message': 'Profil utilisateur',
        'user': request.user
    })

if __name__ == '__main__':
    app.run(debug=True, port=3000)

PHP

PHP - api.php
<?php
require 'vendor/autoload.php';

use Dotenv\Dotenv;

$dotenv = Dotenv::createImmutable(__DIR__);
$dotenv->load();

// Cache pour l'access token (utiliser Redis en production)
$cacheFile = __DIR__ . '/cache/access_token.json';

function getValidAccessToken() {
    global $cacheFile;

    // Vérifier le cache
    if (file_exists($cacheFile)) {
        $cache = json_decode(file_get_contents($cacheFile), true);

        if (strtotime($cache['expires_at']) > time()) {
            return $cache['access_token'];
        }
    }

    // Générer un nouveau token
    $ch = curl_init($_ENV['CODEA_AUTH_URL'] . '/api/oauth/token');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'appId' => $_ENV['CODEA_APP_ID'],
        'secretKey' => $_ENV['CODEA_SECRET_KEY']
    ]));
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $data = json_decode($response, true);

    if ($httpCode !== 200) {
        throw new Exception($data['error'] ?? 'Erreur génération token');
    }

    // Sauvegarder en cache
    if (!is_dir(dirname($cacheFile))) {
        mkdir(dirname($cacheFile), 0755, true);
    }
    file_put_contents($cacheFile, json_encode($data));

    return $data['access_token'];
}

function verifyUserToken($userToken) {
    $accessToken = getValidAccessToken();

    $ch = curl_init($_ENV['CODEA_AUTH_URL'] . '/api/oauth/verify-user');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'access_token' => $accessToken,
        'user_token' => $userToken
    ]));
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

// Router simple
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

header('Content-Type: application/json');

if ($method === 'POST' && $path === '/api/verify-user') {
    $headers = getallheaders();
    $authHeader = $headers['Authorization'] ?? '';
    $userToken = str_replace('Bearer ', '', $authHeader);

    if (empty($userToken)) {
        http_response_code(401);
        echo json_encode(['error' => 'Token requis']);
        exit;
    }

    try {
        $result = verifyUserToken($userToken);

        if ($result['valid']) {
            echo json_encode([
                'success' => true,
                'user' => $result['user']
            ]);
        } else {
            http_response_code(401);
            echo json_encode([
                'success' => false,
                'error' => $result['error']
            ]);
        }
    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode(['error' => $e->getMessage()]);
    }

    exit;
}

// Route protégée exemple
if ($method === 'GET' && $path === '/api/user/profile') {
    $headers = getallheaders();
    $authHeader = $headers['Authorization'] ?? '';
    $userToken = str_replace('Bearer ', '', $authHeader);

    if (empty($userToken)) {
        http_response_code(401);
        echo json_encode(['error' => 'Non authentifié']);
        exit;
    }

    try {
        $result = verifyUserToken($userToken);

        if ($result['valid']) {
            echo json_encode([
                'message' => 'Profil utilisateur',
                'user' => $result['user']
            ]);
        } else {
            http_response_code(401);
            echo json_encode(['error' => 'Token invalide']);
        }
    } catch (Exception $e) {
        http_response_code(500);
        echo json_encode(['error' => $e->getMessage()]);
    }

    exit;
}

http_response_code(404);
echo json_encode(['error' => 'Route non trouvée']);
?>

Utilisation avec le frontend

JavaScript - Frontend
const auth = new CodeaAuth({
    appId: '590551', // Public - OK d'exposer
    secretKey: 'FAKE_KEY', // Pas utilisé par le backend
    onSuccess: async function(result) {
        const userToken = result.token;

        // Envoyer le token au backend pour vérification
        const response = await fetch('/api/verify-user', {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${userToken}`,
                'Content-Type': 'application/json'
            }
        });

        const data = await response.json();

        if (data.success) {
            console.log('Utilisateur vérifié:', data.user);
            // Stocker le token pour les futures requêtes
            localStorage.setItem('userToken', userToken);
        } else {
            alert('Erreur de vérification : ' + data.error);
        }
    }
});

// Utiliser le token pour les requêtes protégées
async function getUserProfile() {
    const token = localStorage.getItem('userToken');

    const response = await fetch('/api/user/profile', {
        headers: {
            'Authorization': `Bearer ${token}`
        }
    });

    const data = await response.json();
    console.log('Profil:', data.user);
}
Félicitations !

Vous avez maintenant une architecture backend sécurisée. Consultez la section Full-Stack pour voir un exemple complet.

Intégration Backend

Vérifier les utilisateurs côté serveur

Section complétée

Voir ci-dessus pour le contenu complet

Intégration Full-Stack

Architecture complète frontend + backend

Architecture Full-Stack Recommandée

Voici l'architecture complète combinant frontend et backend pour une sécurité maximale.

� Structure du projet

my-app/
├── frontend/
│   └── index.html
├── backend/
│   ├── server.js
│   ├── .env
│   └── package.json
└── README.md
    

Frontend (index.html)

HTML
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Mon App Full-Stack</title>
    <style>
        .hidden { display: none; }
        .container { max-width: 800px; margin: 50px auto; padding: 20px; }
        .user-card { background: #f5f5f5; padding: 20px; border-radius: 8px; }
        .btn { padding: 10px 20px; cursor: pointer; }
    </style>
</head>
<body>
    <div class="container">
        <div id="login-section">
            <h1>Bienvenue sur Mon App</h1>
            <button class="btn" onclick="auth.login()">
                 Se connecter avec Codea Auth
            </button>
        </div>

        <div id="user-section" class="hidden">
            <div class="user-card">
                <h2>Tableau de bord</h2>
                <img id="avatar" width="80" height="80" />
                <p><strong>Nom :</strong> <span id="name"></span></p>
                <p><strong>Email :</strong> <span id="email"></span></p>
                <button class="btn" onclick="logout()">Déconnexion</button>
            </div>
        </div>
    </div>

    <script src="https://auth.codealuxz.fr/codea-auth-sdk.js"></script>
    <script>
        const API_URL = 'http://localhost:3000';

        const auth = new CodeaAuth({
            appId: '590551',
            secretKey: 'PUBLIC_FAKE_KEY', // Ne sera pas utilisé par le backend
            onSuccess: async (result) => {
                const userToken = result.token;

                // Envoyer au backend pour vérification sécurisée
                try {
                    const response = await fetch(`${API_URL}/api/verify`, {
                        method: 'POST',
                        headers: {
                            'Authorization': `Bearer ${userToken}`,
                            'Content-Type': 'application/json'
                        }
                    });

                    const data = await response.json();

                    if (data.valid) {
                        // Stocker le token
                        localStorage.setItem('userToken', userToken);
                        localStorage.setItem('userData', JSON.stringify(data.user));

                        // Afficher l'utilisateur
                        displayUser(data.user);
                    } else {
                        alert('Erreur de vérification : ' + data.error);
                    }
                } catch (error) {
                    console.error('Erreur:', error);
                    alert('Erreur de connexion au serveur');
                }
            },
            onError: (error) => {
                alert('Erreur : ' + error.message);
            }
        });

        function displayUser(user) {
            document.getElementById('login-section').classList.add('hidden');
            document.getElementById('user-section').classList.remove('hidden');

            document.getElementById('name').textContent = `${user.firstName} ${user.lastName}`;
            document.getElementById('email').textContent = user.email || 'Non renseigné';
            document.getElementById('avatar').src = user.profilePicture || 'default.png';
        }

        function logout() {
            localStorage.clear();
            document.getElementById('login-section').classList.remove('hidden');
            document.getElementById('user-section').classList.add('hidden');
        }

        // Vérifier au chargement si déjà connecté
        window.addEventListener('DOMContentLoaded', async () => {
            const token = localStorage.getItem('userToken');
            if (token) {
                try {
                    const res = await fetch(`${API_URL}/api/verify`, {
                        method: 'POST',
                        headers: { 'Authorization': `Bearer ${token}` }
                    });
                    const data = await res.json();
                    if (data.valid) {
                        displayUser(data.user);
                    } else {
                        localStorage.clear();
                    }
                } catch (e) {
                    localStorage.clear();
                }
            }
        });
    </script>
</body>
</html>

Backend (server.js)

JavaScript - Node.js/Express
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const fetch = require('node-fetch');

const app = express();
app.use(cors());
app.use(express.json());

// Cache pour l'access token
let cachedAccessToken = null;
let tokenExpiry = null;

// Fonction pour obtenir un access token valide
async function getValidAccessToken() {
    if (cachedAccessToken && tokenExpiry && new Date() < new Date(tokenExpiry)) {
        console.log(' Utilisation du token en cache');
        return cachedAccessToken;
    }

    console.log(' Génération d\'un nouveau access token...');

    const response = await fetch('https://auth.codealuxz.fr/api/oauth/token', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            appId: process.env.CODEA_APP_ID,
            secretKey: process.env.CODEA_SECRET_KEY
        })
    });

    if (!response.ok) {
        throw new Error('Erreur génération access token');
    }

    const data = await response.json();
    cachedAccessToken = data.access_token;
    tokenExpiry = data.expires_at;

    console.log(` Access token généré (expire: ${tokenExpiry})`);
    return cachedAccessToken;
}

// Route de vérification
app.post('/api/verify', async (req, res) => {
    try {
        const userToken = req.headers.authorization?.replace('Bearer ', '');

        if (!userToken) {
            return res.status(401).json({
                valid: false,
                error: 'Token manquant'
            });
        }

        // Obtenir access token
        const accessToken = await getValidAccessToken();

        // Vérifier le token utilisateur
        const verifyResponse = await fetch('https://auth.codealuxz.fr/api/oauth/verify-user', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                access_token: accessToken,
                user_token: userToken
            })
        });

        const data = await verifyResponse.json();

        if (data.valid) {
            console.log(` Utilisateur vérifié: ${data.user.username}`);
            res.json({
                valid: true,
                user: data.user
            });
        } else {
            console.log(' Token invalide');
            res.status(401).json({
                valid: false,
                error: data.error
            });
        }
    } catch (error) {
        console.error(' Erreur:', error);
        res.status(500).json({
            valid: false,
            error: 'Erreur serveur'
        });
    }
});

// Middleware d'authentification réutilisable
async function requireAuth(req, res, next) {
    try {
        const userToken = req.headers.authorization?.replace('Bearer ', '');

        if (!userToken) {
            return res.status(401).json({ error: 'Non authentifié' });
        }

        const accessToken = await getValidAccessToken();

        const response = await fetch('https://auth.codealuxz.fr/api/oauth/verify-user', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                access_token: accessToken,
                user_token: userToken
            })
        });

        const data = await response.json();

        if (data.valid) {
            req.user = data.user;
            next();
        } else {
            res.status(401).json({ error: 'Token invalide' });
        }
    } catch (error) {
        res.status(500).json({ error: 'Erreur serveur' });
    }
}

// Exemple de route protégée
app.get('/api/user/profile', requireAuth, (req, res) => {
    res.json({
        message: 'Profil utilisateur',
        user: req.user
    });
});

// Exemple de route protégée avec données
app.get('/api/user/dashboard', requireAuth, (req, res) => {
    res.json({
        user: req.user,
        stats: {
            loginCount: 42,
            lastLogin: new Date()
        }
    });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(` Serveur démarré sur http://localhost:${PORT}`);
});

Fichier .env

.env
CODEA_APP_ID=590551
CODEA_SECRET_KEY=00a75ea7f31ee220ea6414d69de7b85b8113b65276e62f74f0403930f333bdb8
PORT=3000

package.json

JSON
{
  "name": "my-fullstack-app",
  "version": "1.0.0",
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js"
  },
  "dependencies": {
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "dotenv": "^16.0.3",
    "node-fetch": "^2.6.7"
  },
  "devDependencies": {
    "nodemon": "^3.0.1"
  }
}

Lancement

Bash
# Installer les dépendances
npm install

# Lancer le serveur
npm start

# Ouvrir frontend/index.html dans votre navigateur
Architecture sécurisée

Cette architecture garantit que votre Secret Key n'est jamais exposée au client et que toutes les vérifications sont faites côté serveur.

API OAuth & Tokens

Référence complète de l'API OAuth

API OAuth - Référence complète

L'API OAuth permet de sécuriser vos credentials avec des tokens temporaires de 10 jours.

POST /api/oauth/token

Obtenir un access token en échangeant vos credentials.

Request

JSON
{
  "appId": "590551",
  "secretKey": "00a75ea7f31ee220ea6414d69de7b85b8113b65276e62f74f0403930f333bdb8"
}

Response (200 OK)

JSON
{
  "access_token": "a1b2c3d4e5f6789012345678901234567890123456789012345678901234",
  "token_type": "Bearer",
  "expires_in": 864000,
  "expires_at": "2025-10-16T20:00:00.000Z"
}

Erreurs possibles

Code Erreur Description
400 appId et secretKey requis Champs manquants
401 Application non trouvée ou inactive App ID invalide
401 Credentials invalides Secret Key incorrecte

POST /api/oauth/verify

Vérifier si un access token est valide et non expiré.

Request

JSON
{
  "access_token": "a1b2c3d4..."
}

Response (200 OK)

JSON
{
  "valid": true,
  "appId": "590551",
  "appName": "Mon Application",
  "expiresAt": "2025-10-16T20:00:00.000Z",
  "expires_in": 850000
}

POST /api/oauth/verify-user

Vérifier un token utilisateur avec votre access token d'application.

Request

JSON
{
  "access_token": "a1b2c3d4...",
  "user_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response (200 OK)

JSON
{
  "valid": true,
  "user": {
    "id": "507f1f77bcf86cd799439011",
    "username": "johndoe",
    "firstName": "John",
    "lastName": "Doe",
    "email": "[email protected]",
    "profilePicture": "data:image/jpeg;base64,...",
    "createdAt": "2025-01-01T00:00:00.000Z"
  },
  "app": {
    "appId": "590551",
    "name": "Mon Application"
  }
}

POST /api/oauth/revoke

Révoquer un access token immédiatement.

Request

JSON
{
  "access_token": "token_a_revoquer"
}

Response (200 OK)

JSON
{
  "message": "Token révoqué avec succès"
}
Conseil

Les access tokens ont une durée de vie de 10 jours. Pensez à les renouveler automatiquement avant expiration dans votre application.

API Authentification

Endpoints d'inscription et connexion

API Authentification - Référence complète

Endpoints pour l'inscription, la connexion et la gestion des sessions utilisateurs.

POST /api/auth/register

Créer un nouveau compte utilisateur.

Paramètres

Champ Type Requis Description
firstName string Prénom de l'utilisateur
lastName string Nom de famille
username string Nom d'utilisateur unique (min 3 caractères, lettres/chiffres/_)
email string Adresse email (format valide)
password string Mot de passe (min 6 caractères)
dateOfBirth date Date de naissance (format: YYYY-MM-DD)
profilePicture file Image de profil (max 5MB, jpeg/png/gif/webp)
hcaptchaToken string Token hCaptcha de validation

Request (multipart/form-data ou JSON)

JavaScript
const response = await fetch('https://auth.codealuxz.fr/api/auth/register', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        firstName: 'John',
        lastName: 'Doe',
        username: 'johndoe',
        email: '[email protected]',
        password: 'motdepasse123',
        dateOfBirth: '1990-01-01',
        hcaptchaToken: 'P1_eyJ0eXAiOiJKV1QiLCJhbGc...'
    })
});

Response (201 Created)

JSON
{
  "message": "Compte créé avec succès",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": "507f1f77bcf86cd799439011",
    "username": "johndoe",
    "firstName": "John",
    "lastName": "Doe",
    "email": "[email protected]",
    "dateOfBirth": "1990-01-01",
    "createdAt": "2025-01-06T00:00:00.000Z"
  }
}

POST /api/auth/login

Connexion utilisateur avec username/email et mot de passe.

Request

JSON
{
  "identifier": "johndoe",
  "password": "motdepasse123"
}

Response (200 OK)

JSON
{
  "message": "Connexion réussie",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": { ... }
}

POST /api/auth/verify-token

Vérifier la validité d'un token utilisateur.

Request

JSON
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response (200 OK)

JSON
{
  "valid": true,
  "user": { ... }
}

POST /api/auth/forgot-password

Demander un code de réinitialisation de mot de passe (envoyé par email).

Request

JSON
{
  "identifier": "[email protected]"
}

Response (200 OK)

JSON
{
  "message": "Code de réinitialisation envoyé par email",
  "emailSent": true
}

POST /api/auth/reset-password

Réinitialiser le mot de passe avec le code reçu par email.

Request

JSON
{
  "identifier": "[email protected]",
  "code": "123456",
  "newPassword": "nouveaumotdepasse"
}

Response (200 OK)

JSON
{
  "message": "Mot de passe réinitialisé avec succès"
}
Rate Limiting

L'inscription est limitée à 1 compte par heure par IP pour prévenir les abus.

API Gestion Utilisateurs

Profils, sessions, et paramètres

Gestion des utilisateurs

Routes protégées pour gérer le profil et les sessions de l'utilisateur connecté.

Routes protégées

Toutes ces routes nécessitent un token utilisateur valide dans le header Authorization: Bearer TOKEN

GET /api/auth/profile

Récupérer le profil complet de l'utilisateur connecté.

Request

JavaScript
const response = await fetch('https://auth.codealuxz.fr/api/auth/profile', {
    headers: {
        'Authorization': 'Bearer ' + userToken
    }
});

Response (200 OK)

JSON
{
  "user": {
    "id": "507f1f77bcf86cd799439011",
    "username": "johndoe",
    "firstName": "John",
    "lastName": "Doe",
    "email": "[email protected]",
    "dateOfBirth": "1990-01-01",
    "profilePicture": "data:image/jpeg;base64,...",
    "privacy": {
      "hideFirstName": false,
      "hideLastName": false,
      "hideDateOfBirth": true,
      "hideEmail": false
    },
    "createdAt": "2025-01-01T00:00:00.000Z"
  }
}

PUT /api/auth/profile

Mettre à jour le profil utilisateur.

Paramètres (tous optionnels)

Champ Type Description
firstName string Nouveau prénom
lastName string Nouveau nom
email string Nouvel email
dateOfBirth date Nouvelle date de naissance
profilePicture file/base64 Nouvelle photo de profil
privacy object Paramètres de confidentialité

GET /api/auth/sessions

Liste de toutes les sessions actives de l'utilisateur.

Response (200 OK)

JSON
{
  "user": { ... },
  "sessions": [
    {
      "deviceInfo": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
      "lastActive": "2025-01-06T10:30:00.000Z",
      "createdAt": "2025-01-05T08:00:00.000Z"
    },
    {
      "deviceInfo": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0...)...",
      "lastActive": "2025-01-06T09:15:00.000Z",
      "createdAt": "2025-01-04T15:20:00.000Z"
    }
  ],
  "totalSessions": 2
}

POST /api/auth/logout

Déconnexion de la session actuelle uniquement.

Response (200 OK)

JSON
{
  "message": "Déconnexion réussie"
}

POST /api/auth/logout-all

Déconnexion de TOUTES les sessions (tous les appareils).

Response (200 OK)

JSON
{
  "message": "Déconnexion de toutes les sessions réussie"
}
Cas d'usage

Utilisez /logout-all si l'utilisateur pense que son compte a été compromis.

Exemples JavaScript/Node.js

Exemples complets en JavaScript

Exemples JavaScript/Node.js complets

Exemple 1 : Express.js avec middleware personnalisé

JavaScript
require('dotenv').config();
const express = require('express');
const fetch = require('node-fetch');
const app = express();

app.use(express.json());

// Cache global pour l'access token
class TokenManager {
    constructor() {
        this.token = null;
        this.expiry = null;
    }

    async getToken() {
        if (this.token && this.expiry && new Date() < new Date(this.expiry)) {
            return this.token;
        }

        const res = await fetch('https://auth.codealuxz.fr/api/oauth/token', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                appId: process.env.CODEA_APP_ID,
                secretKey: process.env.CODEA_SECRET_KEY
            })
        });

        const data = await res.json();
        this.token = data.access_token;
        this.expiry = data.expires_at;

        return this.token;
    }
}

const tokenManager = new TokenManager();

// Middleware d'authentification
async function authenticate(req, res, next) {
    try {
        const userToken = req.headers.authorization?.replace('Bearer ', '');

        if (!userToken) {
            return res.status(401).json({ error: 'Token requis' });
        }

        const accessToken = await tokenManager.getToken();

        const verifyRes = await fetch('https://auth.codealuxz.fr/api/oauth/verify-user', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                access_token: accessToken,
                user_token: userToken
            })
        });

        const data = await verifyRes.json();

        if (data.valid) {
            req.user = data.user;
            next();
        } else {
            res.status(401).json({ error: 'Token invalide' });
        }
    } catch (error) {
        res.status(500).json({ error: 'Erreur serveur' });
    }
}

// Routes
app.get('/api/dashboard', authenticate, (req, res) => {
    res.json({
        message: `Bienvenue ${req.user.username}`,
        user: req.user
    });
});

app.get('/api/protected', authenticate, (req, res) => {
    res.json({
        data: 'Données sensibles',
        user: req.user.username
    });
});

app.listen(3000, () => console.log('Serveur démarré sur :3000'));

Exemple 2 : Next.js API Route

JavaScript - pages/api/user.js
// pages/api/user.js
let accessToken = null;
let tokenExpiry = null;

async function getAccessToken() {
    if (accessToken && tokenExpiry && new Date() < new Date(tokenExpiry)) {
        return accessToken;
    }

    const res = await fetch('https://auth.codealuxz.fr/api/oauth/token', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            appId: process.env.CODEA_APP_ID,
            secretKey: process.env.CODEA_SECRET_KEY
        })
    });

    const data = await res.json();
    accessToken = data.access_token;
    tokenExpiry = data.expires_at;

    return accessToken;
}

export default async function handler(req, res) {
    if (req.method !== 'GET') {
        return res.status(405).json({ error: 'Method not allowed' });
    }

    const userToken = req.headers.authorization?.replace('Bearer ', '');

    if (!userToken) {
        return res.status(401).json({ error: 'Non authentifié' });
    }

    try {
        const at = await getAccessToken();

        const verifyRes = await fetch('https://auth.codealuxz.fr/api/oauth/verify-user', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                access_token: at,
                user_token: userToken
            })
        });

        const data = await verifyRes.json();

        if (data.valid) {
            res.status(200).json({ user: data.user });
        } else {
            res.status(401).json({ error: 'Token invalide' });
        }
    } catch (error) {
        res.status(500).json({ error: 'Erreur serveur' });
    }
}

Exemple 3 : Vanilla JavaScript (Frontend)

JavaScript
// Classe pour gérer l'authentification
class AuthManager {
    constructor(appId, secretKey) {
        this.auth = new CodeaAuth({
            appId,
            secretKey,
            onSuccess: this.handleSuccess.bind(this),
            onError: this.handleError.bind(this)
        });

        this.userToken = localStorage.getItem('userToken');
        this.user = null;
    }

    handleSuccess(result) {
        this.userToken = result.token;
        this.user = result.user;

        localStorage.setItem('userToken', this.userToken);
        localStorage.setItem('user', JSON.stringify(this.user));

        this.onAuthChange(this.user);
    }

    handleError(error) {
        console.error('Erreur auth:', error);
        alert('Erreur : ' + error.message);
    }

    login() {
        this.auth.login();
    }

    logout() {
        this.userToken = null;
        this.user = null;

        localStorage.removeItem('userToken');
        localStorage.removeItem('user');

        this.onAuthChange(null);
    }

    async checkAuth() {
        if (!this.userToken) return false;

        try {
            const res = await fetch('https://auth.codealuxz.fr/api/auth/verify-token', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ token: this.userToken })
            });

            const data = await res.json();

            if (data.valid) {
                this.user = data.user;
                this.onAuthChange(this.user);
                return true;
            } else {
                this.logout();
                return false;
            }
        } catch (error) {
            console.error('Erreur vérification:', error);
            return false;
        }
    }

    onAuthChange(user) {
        // À implémenter par l'utilisateur
        console.log('État auth changé:', user);
    }
}

// Utilisation
const authManager = new AuthManager('590551', 'YOUR_SECRET');

authManager.onAuthChange = (user) => {
    if (user) {
        document.getElementById('login-btn').style.display = 'none';
        document.getElementById('user-info').style.display = 'block';
        document.getElementById('username').textContent = user.username;
    } else {
        document.getElementById('login-btn').style.display = 'block';
        document.getElementById('user-info').style.display = 'none';
    }
};

// Vérifier au chargement
authManager.checkAuth();

Exemples Python

Exemples complets en Python

Exemples Python complets

Exemple 1 : Flask avec décorateur personnalisé

Python
import os
from datetime import datetime
from functools import wraps
from flask import Flask, request, jsonify
from dotenv import load_dotenv
import requests

load_dotenv()

app = Flask(__name__)

# Cache pour l'access token
class TokenManager:
    def __init__(self):
        self.token = None
        self.expiry = None

    def get_token(self):
        if self.token and self.expiry:
            if datetime.now() < datetime.fromisoformat(self.expiry.replace('Z', '+00:00')):
                return self.token

        response = requests.post(
            f"{os.getenv('CODEA_AUTH_URL')}/api/oauth/token",
            json={
                'appId': os.getenv('CODEA_APP_ID'),
                'secretKey': os.getenv('CODEA_SECRET_KEY')
            }
        )

        data = response.json()
        self.token = data['access_token']
        self.expiry = data['expires_at']

        return self.token

token_manager = TokenManager()

# Décorateur d'authentification
def require_auth(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        auth_header = request.headers.get('Authorization', '')
        user_token = auth_header.replace('Bearer ', '')

        if not user_token:
            return jsonify({'error': 'Non authentifié'}), 401

        try:
            access_token = token_manager.get_token()

            response = requests.post(
                f"{os.getenv('CODEA_AUTH_URL')}/api/oauth/verify-user",
                json={
                    'access_token': access_token,
                    'user_token': user_token
                }
            )

            data = response.json()

            if data.get('valid'):
                request.user = data['user']
                return f(*args, **kwargs)
            else:
                return jsonify({'error': 'Token invalide'}), 401

        except Exception as e:
            return jsonify({'error': str(e)}), 500

    return decorated_function

# Routes protégées
@app.route('/api/dashboard')
@require_auth
def dashboard():
    return jsonify({
        'message': f"Bienvenue {request.user['username']}",
        'user': request.user
    })

@app.route('/api/protected')
@require_auth
def protected():
    return jsonify({
        'data': 'Données sensibles',
        'user': request.user['username']
    })

if __name__ == '__main__':
    app.run(debug=True, port=3000)

Exemple 2 : Django View

Python - views.py
import os
import requests
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt

# Cache global
_access_token = None
_token_expiry = None

def get_access_token():
    global _access_token, _token_expiry

    if _access_token and _token_expiry:
        from datetime import datetime
        if datetime.now() < datetime.fromisoformat(_token_expiry.replace('Z', '+00:00')):
            return _access_token

    response = requests.post(
        'https://auth.codealuxz.fr/api/oauth/token',
        json={
            'appId': os.getenv('CODEA_APP_ID'),
            'secretKey': os.getenv('CODEA_SECRET_KEY')
        }
    )

    data = response.json()
    _access_token = data['access_token']
    _token_expiry = data['expires_at']

    return _access_token

def verify_user_token(user_token):
    access_token = get_access_token()

    response = requests.post(
        'https://auth.codealuxz.fr/api/oauth/verify-user',
        json={
            'access_token': access_token,
            'user_token': user_token
        }
    )

    return response.json()

@csrf_exempt
@require_http_methods(['POST'])
def verify_user(request):
    auth_header = request.META.get('HTTP_AUTHORIZATION', '')
    user_token = auth_header.replace('Bearer ', '')

    if not user_token:
        return JsonResponse({'error': 'Token requis'}, status=401)

    try:
        data = verify_user_token(user_token)

        if data.get('valid'):
            return JsonResponse({
                'success': True,
                'user': data['user']
            })
        else:
            return JsonResponse({
                'success': False,
                'error': data.get('error')
            }, status=401)

    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)

Exemple 3 : FastAPI

Python
import os
from fastapi import FastAPI, Depends, HTTPException, Header
from pydantic import BaseModel
import requests

app = FastAPI()

# Cache
_access_token = None
_token_expiry = None

async def get_access_token():
    global _access_token, _token_expiry

    if _access_token and _token_expiry:
        from datetime import datetime
        if datetime.now() < datetime.fromisoformat(_token_expiry.replace('Z', '+00:00')):
            return _access_token

    response = requests.post(
        'https://auth.codealuxz.fr/api/oauth/token',
        json={
            'appId': os.getenv('CODEA_APP_ID'),
            'secretKey': os.getenv('CODEA_SECRET_KEY')
        }
    )

    data = response.json()
    _access_token = data['access_token']
    _token_expiry = data['expires_at']

    return _access_token

async def get_current_user(authorization: str = Header(None)):
    if not authorization or not authorization.startswith('Bearer '):
        raise HTTPException(status_code=401, detail='Non authentifié')

    user_token = authorization.replace('Bearer ', '')
    access_token = await get_access_token()

    response = requests.post(
        'https://auth.codealuxz.fr/api/oauth/verify-user',
        json={
            'access_token': access_token,
            'user_token': user_token
        }
    )

    data = response.json()

    if not data.get('valid'):
        raise HTTPException(status_code=401, detail='Token invalide')

    return data['user']

@app.get('/api/dashboard')
async def dashboard(user: dict = Depends(get_current_user)):
    return {
        'message': f"Bienvenue {user['username']}",
        'user': user
    }

@app.get('/api/protected')
async def protected(user: dict = Depends(get_current_user)):
    return {
        'data': 'Données sensibles',
        'user': user['username']
    }

Exemples PHP

Exemples complets en PHP

Exemples PHP complets

Exemple 1 : PHP avec fonction helper

PHP
<?php
require 'vendor/autoload.php';

use Dotenv\Dotenv;

$dotenv = Dotenv::createImmutable(__DIR__);
$dotenv->load();

// Cache pour l'access token (utiliser Redis/Memcached en production)
$cacheFile = __DIR__ . '/cache/codea_token.json';

function getAccessToken() {
    global $cacheFile;

    // Vérifier le cache
    if (file_exists($cacheFile)) {
        $cache = json_decode(file_get_contents($cacheFile), true);

        if (strtotime($cache['expires_at']) > time()) {
            return $cache['access_token'];
        }
    }

    // Générer un nouveau token
    $ch = curl_init($_ENV['CODEA_AUTH_URL'] . '/api/oauth/token');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'appId' => $_ENV['CODEA_APP_ID'],
        'secretKey' => $_ENV['CODEA_SECRET_KEY']
    ]));
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode !== 200) {
        throw new Exception('Erreur génération token');
    }

    $data = json_decode($response, true);

    // Sauvegarder en cache
    if (!is_dir(dirname($cacheFile))) {
        mkdir(dirname($cacheFile), 0755, true);
    }
    file_put_contents($cacheFile, json_encode($data));

    return $data['access_token'];
}

function verifyUserToken($userToken) {
    $accessToken = getAccessToken();

    $ch = curl_init($_ENV['CODEA_AUTH_URL'] . '/api/oauth/verify-user');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'access_token' => $accessToken,
        'user_token' => $userToken
    ]));
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

function requireAuth() {
    $headers = getallheaders();
    $authHeader = $headers['Authorization'] ?? '';
    $userToken = str_replace('Bearer ', '', $authHeader);

    if (empty($userToken)) {
        http_response_code(401);
        echo json_encode(['error' => 'Non authentifié']);
        exit;
    }

    $result = verifyUserToken($userToken);

    if (!$result['valid']) {
        http_response_code(401);
        echo json_encode(['error' => $result['error'] ?? 'Token invalide']);
        exit;
    }

    return $result['user'];
}

// Utilisation
header('Content-Type: application/json');

$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

if ($method === 'GET' && $path === '/api/dashboard') {
    $user = requireAuth();

    echo json_encode([
        'message' => "Bienvenue {$user['username']}",
        'user' => $user
    ]);
    exit;
}

if ($method === 'GET' && $path === '/api/protected') {
    $user = requireAuth();

    echo json_encode([
        'data' => 'Données sensibles',
        'user' => $user['username']
    ]);
    exit;
}

http_response_code(404);
echo json_encode(['error' => 'Route non trouvée']);
?>

Exemple 2 : Laravel Middleware

PHP - CodeaAuthMiddleware.php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;

class CodeaAuthMiddleware
{
    public function handle(Request $request, Closure $next)
    {
        $userToken = $request->bearerToken();

        if (!$userToken) {
            return response()->json(['error' => 'Non authentifié'], 401);
        }

        $user = $this->verifyUserToken($userToken);

        if (!$user) {
            return response()->json(['error' => 'Token invalide'], 401);
        }

        $request->merge(['user' => $user]);

        return $next($request);
    }

    private function getAccessToken()
    {
        return Cache::remember('codea_access_token', 864000, function () {
            $response = Http::post(env('CODEA_AUTH_URL') . '/api/oauth/token', [
                'appId' => env('CODEA_APP_ID'),
                'secretKey' => env('CODEA_SECRET_KEY')
            ]);

            if ($response->successful()) {
                return $response->json()['access_token'];
            }

            throw new \Exception('Erreur génération token');
        });
    }

    private function verifyUserToken($userToken)
    {
        $accessToken = $this->getAccessToken();

        $response = Http::post(env('CODEA_AUTH_URL') . '/api/oauth/verify-user', [
            'access_token' => $accessToken,
            'user_token' => $userToken
        ]);

        if ($response->successful() && $response->json()['valid']) {
            return $response->json()['user'];
        }

        return null;
    }
}
?>

Bonnes pratiques de sécurité

Sécurisez votre intégration

Bonnes pratiques de sécurité

À FAIRE impérativement

1Protéger votre Secret Key

  • Stocker dans un fichier .env (jamais dans le code)
  • Ajouter .env au .gitignore
  • Utiliser des variables d'environnement sur le serveur
  • Ne jamais commit dans Git
  • Ne jamais exposer côté client/frontend

2Utiliser HTTPS uniquement

  • Obligatoire en production
  • Certificat SSL/TLS valide
  • Rediriger HTTP → HTTPS automatiquement

3Implémenter OAuth côté backend

  • Utiliser des access tokens temporaires (10 jours)
  • Vérifier les tokens utilisateurs côté serveur
  • Ne jamais faire confiance au frontend seul

4Valider les données utilisateur

  • Toujours vérifier les tokens avant d'autoriser l'accès
  • Valider les permissions/rôles si nécessaire
  • Vérifier que le token n'a pas expiré

5Gérer les sessions proprement

  • Stocker les tokens dans localStorage ou cookies sécurisés
  • Nettoyer les tokens à la déconnexion
  • Vérifier les tokens au chargement de l'application

À NE JAMAIS FAIRE

Mauvaise pratique Solution
Hardcoder Secret Key dans le code Utiliser process.env.SECRET_KEY
Exposer Secret Key côté client Utiliser OAuth avec access tokens
Commit .env dans Git Ajouter .env au .gitignore
Faire confiance au frontend Toujours vérifier côté backend
Utiliser HTTP en production Obligatoire HTTPS
Stocker passwords en clair Codea Auth les hash avec bcrypt

Exemple de configuration sécurisée

.env (Backend)
#  Fichier .env (à ajouter au .gitignore)
CODEA_APP_ID=590551
CODEA_SECRET_KEY=00a75ea7f31ee220ea6414d69de7b85b8113b65276e62f74f0403930f333bdb8
CODEA_AUTH_URL=https://auth.codealuxz.fr

# Autres variables
NODE_ENV=production
PORT=3000
.gitignore
#  Toujours ignorer ces fichiers
.env
.env.local
.env.production
.env.*.local

node_modules/
dist/
build/
Alerte sécurité

Si votre Secret Key a été compromise (commit Git, exposure publique), créez immédiatement une nouvelle application dans votre dashboard et mettez à jour vos credentials.

Checklist de sécurité

  • Secret Key dans .env (pas dans le code)
  • .env dans .gitignore
  • HTTPS activé en production
  • OAuth avec access tokens temporaires
  • Validation tokens côté backend
  • Certificat SSL valide
  • CORS configuré correctement
  • Rate limiting activé (déjà inclus dans Codea Auth)
  • hCaptcha activé sur l'inscription
  • Sessions nettoyées à la déconnexion

Anti-spam & hCaptcha

Protection contre les abus

Protection anti-spam & hCaptcha

Protections intégrées

Codea Auth inclut plusieurs mécanismes de protection contre les abus :

1hCaptcha (99.9% Passive)

  • Protection automatique lors de l'inscription
  • Mode passif : invisible pour 99.9% des utilisateurs légitimes
  • Challenge uniquement pour les comportements suspects
  • Site Key : 576eee9a-3966-44da-8972-d77627e67e7e

2Rate Limiting (1 compte/heure/IP)

  • Limite stricte : 1 inscription par heure par adresse IP
  • Appliqué APRÈS validation du hCaptcha
  • Basé sur l'IP réelle (compatible avec proxies/CDN)
  • Message d'erreur clair pour l'utilisateur

3Validation des données

  • Username : min 3 caractères, lettres/chiffres/underscore uniquement
  • Email : format valide vérifié
  • Password : minimum 6 caractères
  • Unicité : username et email doivent être uniques

Configuration hCaptcha

Frontend - Intégration automatique

Le formulaire d'inscription sur /register.html inclut déjà hCaptcha :

HTML
<!-- Déjà inclus dans le formulaire d'inscription -->
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>

<form id="registerForm">
    <!-- ... autres champs ... -->

    <div class="h-captcha" data-sitekey="576eee9a-3966-44da-8972-d77627e67e7e"></div>

    <button type="submit">S'inscrire</button>
</form>

Backend - Vérification automatique

Le backend vérifie automatiquement le token hCaptcha :

JavaScript - Middleware
// Middleware hCaptcha (déjà intégré)
const verifyHCaptcha = async (req, res, next) => {
    const hcaptchaToken = req.body.hcaptchaToken;

    if (!hcaptchaToken) {
        return res.status(400).json({
            error: 'Vérification hCaptcha requise'
        });
    }

    const verification = await verify(
        process.env.HCAPTCHA_SECRET_KEY,
        hcaptchaToken
    );

    if (!verification.success) {
        return res.status(400).json({
            error: 'Échec de la vérification hCaptcha'
        });
    }

    next();
};

Statistiques de protection

Protection Type Efficacité
hCaptcha Bot detection 99.9%
Rate Limiting Spam accounts 100%
Email validation Format invalide 100%
Username uniqueness Duplicates 100%

Gestion des erreurs

Erreur hCaptcha

JSON - Response 400
{
  "error": "Vérification hCaptcha requise"
}

Erreur Rate Limiting

JSON - Response 429
{
  "error": "Limite d'inscription atteinte. Réessayez dans 1 heure."
}
Protection automatique

Toutes ces protections sont actives par défaut. Vous n'avez rien à configurer !

Dépannage

Solutions aux problèmes courants

Guide de dépannage

Erreur : "Token invalide"

Causes possibles

  • Le token a expiré (session fermée)
  • Le token a été révoqué (déconnexion)
  • Format de token incorrect
  • Utilisateur supprimé

Solution

JavaScript
// Vérifier et nettoyer si invalide
const token = localStorage.getItem('userToken');

const res = await fetch('https://auth.codealuxz.fr/api/auth/verify-token', {
    method: 'POST',
    body: JSON.stringify({ token })
});

const data = await res.json();

if (!data.valid) {
    // Token invalide, nettoyer et redemander connexion
    localStorage.clear();
    window.location.href = '/login';
}

Erreur : "Application non trouvée"

Causes possibles

  • App ID incorrect
  • Application désactivée
  • Application supprimée

Solution

  • Vérifier l'App ID dans votre dashboard
  • Vérifier que l'application est active
  • Recréer l'application si nécessaire

Erreur : "Credentials invalides"

Causes possibles

  • Secret Key incorrecte
  • Mauvaise variable d'environnement

Solution

Bash
# Vérifier les variables d'environnement
echo $CODEA_APP_ID
echo $CODEA_SECRET_KEY

# S'assurer que .env est chargé
node -e "require('dotenv').config(); console.log(process.env.CODEA_SECRET_KEY)"

Erreur : "Access token expiré"

Causes possibles

  • Token a dépassé 10 jours
  • Token révoqué manuellement

Solution

Régénérer automatiquement :

JavaScript
let cachedToken = null;
let tokenExpiry = null;

async function getValidToken() {
    // Vérifier si le token est encore valide
    if (cachedToken && tokenExpiry && new Date() < new Date(tokenExpiry)) {
        return cachedToken;
    }

    // Régénérer
    const res = await fetch('https://auth.codealuxz.fr/api/oauth/token', {
        method: 'POST',
        body: JSON.stringify({ appId, secretKey })
    });

    const data = await res.json();
    cachedToken = data.access_token;
    tokenExpiry = data.expires_at;

    return cachedToken;
}

La popup ne s'ouvre pas

Causes possibles

  • Popups bloquées par le navigateur
  • Script SDK non chargé
  • Erreur JavaScript

Solution

  1. Vérifier la console navigateur (F12)
  2. Autoriser les popups pour votre site
  3. Vérifier que le SDK est bien chargé : <script src="https://auth.codealuxz.fr/codea-auth-sdk.js">

Erreur CORS

Causes possibles

  • Requête depuis un domaine non autorisé
  • Headers manquants

Solution

Codea Auth autorise tous les origins. Si vous rencontrez une erreur CORS, vérifiez votre configuration backend :

JavaScript
// Express.js
const cors = require('cors');
app.use(cors());

// Ou spécifique
app.use(cors({
    origin: 'https://mon-site.com',
    credentials: true
}));

Support

Si votre problème persiste :

FAQ

Questions fréquemment posées

Questions fréquemment posées (FAQ)

Tarification

Q : Codea Auth est-il gratuit ?

Oui, complètement gratuit et sans limite d'utilisateurs ou d'applications.

Q : Y a-t-il des frais cachés ou des limitations ?

Non, aucun frais caché. Le service est totalement gratuit.

Sécurité

Q : Les mots de passe sont-ils sécurisés ?

Oui, tous les mots de passe sont hachés avec bcrypt (10 salt rounds) avant d'être stockés.

Q : Mes données utilisateur sont-elles partagées ?

Non, jamais. Vos données restent privées et ne sont jamais vendues ou partagées.

Q : Puis-je exporter les données de mes utilisateurs ?

Actuellement non, mais cette fonctionnalité est prévue prochainement.

Durée de vie

Q : Combien de temps dure un token utilisateur ?

Illimité jusqu'à déconnexion manuelle.

Q : Combien de temps dure un access token (OAuth) ?

10 jours. Il se renouvelle automatiquement si vous utilisez le SDK.

Q : Que se passe-t-il si mon token expire ?

Pour les access tokens : régénérez-en un nouveau. Pour les tokens utilisateurs : l'utilisateur doit se reconnecter.

Personnalisation

Q : Puis-je personnaliser l'interface de connexion ?

L'interface de la popup est standardisée pour l'instant. Personnalisation prévue dans une future version.

Q : Puis-je ajouter mon logo dans la popup ?

Pas encore disponible, mais en développement.

Compatibilité

Q : Codea Auth fonctionne-t-il sur mobile ?

Oui, l'interface est responsive et fonctionne sur tous les appareils.

Q : Puis-je utiliser Codea Auth dans une application mobile native ?

Oui, utilisez l'API REST directement depuis votre app (iOS, Android, React Native, etc.)

Q : Quels navigateurs sont supportés ?

Tous les navigateurs modernes (Chrome, Firefox, Safari, Edge). IE11 non supporté.

Technique

Q : Puis-je avoir plusieurs applications ?

Oui, créez autant d'applications que vous voulez depuis votre dashboard.

Q : Un utilisateur peut-il se connecter à plusieurs de mes applications ?

Oui, un compte Codea Auth peut autoriser plusieurs applications.

Q : Puis-je utiliser Codea Auth avec React/Vue/Angular ?

Oui, le SDK JavaScript fonctionne avec tous les frameworks. Voir les exemples.

Q : Dois-je avoir un backend ?

Pas obligatoire, mais fortement recommandé pour la sécurité (OAuth).

� Récupération de mot de passe

Q : Que faire si un utilisateur perd son mot de passe ?

Utilisez la fonction "Mot de passe oublié" qui envoie un code par email (valide 15 minutes).

Q : Les emails fonctionnent-ils ?

Oui, les emails de récupération et de bienvenue sont envoyés automatiquement.

Stockage et sauvegarde

Q : Où sont stockées les données ?

� MongoDB avec réplication pour la haute disponibilité.

Q : Les données sont-elles sauvegardées ?

Oui, sauvegardes automatiques quotidiennes.

Q : Quelle est la disponibilité du service ?

Disponibilité cible de 99.9% (SLA).

Performance

Q : Y a-t-il une limite d'utilisateurs ?

Non, aucune limite.

Q : Y a-t-il une limite de requêtes par seconde ?

Rate limiting uniquement sur l'inscription (1/heure/IP). Les autres endpoints sont illimités.

Développement

Q : Puis-je tester en local (localhost) ?

Oui, Codea Auth fonctionne parfaitement en développement local.

Q : Y a-t-il un environnement de staging ?

Créez simplement une application de test dans votre dashboard.

Support

Q : Comment obtenir de l'aide ?

� Email : [email protected]
Documentation : docs.html
Troubleshooting : Guide de dépannage

� Question non listée ?

Contactez-nous à [email protected] et nous ajouterons la réponse à cette FAQ !