sunuid-sdk 1.0.51 → 1.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,334 @@
1
+ # SunuID SDK - Guide d'Intégration
2
+
3
+ ## 📦 Vue d'ensemble
4
+
5
+ Le SunuID SDK permet aux partenaires d'intégrer facilement les QR codes d'authentification et KYC dans leurs applications web. Ce package JavaScript offre une interface simple et moderne pour afficher les QR codes SunuID.
6
+
7
+ ## 🚀 Installation
8
+
9
+ ### 1. Inclure les fichiers
10
+
11
+ ```html
12
+ <!-- CSS -->
13
+ <link rel="stylesheet" href="https://sunuid.sn/css/sunuid-sdk.css">
14
+
15
+ <!-- JavaScript -->
16
+ <script src="https://sunuid.sn/js/sunuid-sdk.js"></script>
17
+
18
+ <!-- FontAwesome (pour les icônes) -->
19
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
20
+ ```
21
+
22
+ ### 2. Initialisation
23
+
24
+ ```javascript
25
+ // Configuration du SDK
26
+ const sunuidConfig = {
27
+ apiUrl: 'https://sunuid.sn/api',
28
+ partnerId: 'VOTRE_PARTNER_ID',
29
+ clientId: 'VOTRE_CLIENT_ID',
30
+ secretId: 'VOTRE_SECRET_ID',
31
+ theme: 'light', // 'light' ou 'dark'
32
+ language: 'fr',
33
+ autoRefresh: true,
34
+ refreshInterval: 30000, // 30 secondes
35
+ onSuccess: function(data) {
36
+ console.log('Authentification réussie:', data);
37
+ // Rediriger vers le dashboard
38
+ window.location.href = '/dashboard';
39
+ },
40
+ onError: function(error) {
41
+ console.error('Erreur:', error);
42
+ // Afficher un message d'erreur
43
+ showErrorMessage('Erreur de connexion');
44
+ },
45
+ onExpired: function() {
46
+ console.log('QR code expiré');
47
+ // Actualiser automatiquement ou afficher un message
48
+ showExpiredMessage();
49
+ }
50
+ };
51
+
52
+ // Initialiser le SDK
53
+ const sunuid = initSunuID(sunuidConfig);
54
+ ```
55
+
56
+ ## 🔐 Authentification
57
+
58
+ ### Générer un QR code d'authentification
59
+
60
+ ```html
61
+ <!-- Conteneur pour le QR code -->
62
+ <div id="auth-qr-container"></div>
63
+ ```
64
+
65
+ ```javascript
66
+ // Générer le QR code d'authentification
67
+ sunuid.generateAuthQR('auth-qr-container', {
68
+ theme: 'light',
69
+ redirectUrl: 'https://votre-site.com/dashboard',
70
+ customData: {
71
+ userAgent: navigator.userAgent,
72
+ timestamp: Date.now()
73
+ }
74
+ });
75
+ ```
76
+
77
+ ## 📋 KYC (Know Your Customer)
78
+
79
+ ### Générer un QR code KYC
80
+
81
+ ```html
82
+ <!-- Conteneur pour le QR code KYC -->
83
+ <div id="kyc-qr-container"></div>
84
+ ```
85
+
86
+ ```javascript
87
+ // Générer le QR code KYC
88
+ sunuid.generateKYCQR('kyc-qr-container', {
89
+ theme: 'dark',
90
+ kycType: 'full', // 'basic' ou 'full'
91
+ requiredFields: ['identity', 'address', 'phone'],
92
+ redirectUrl: 'https://votre-site.com/kyc-complete'
93
+ });
94
+ ```
95
+
96
+ ## 🎨 Personnalisation
97
+
98
+ ### Thèmes disponibles
99
+
100
+ ```javascript
101
+ // Thème clair (par défaut)
102
+ sunuid.generateAuthQR('container', { theme: 'light' });
103
+
104
+ // Thème sombre
105
+ sunuid.generateAuthQR('container', { theme: 'dark' });
106
+ ```
107
+
108
+ ### Options de configuration
109
+
110
+ ```javascript
111
+ const options = {
112
+ theme: 'light', // 'light' ou 'dark'
113
+ language: 'fr', // 'fr', 'en', 'ar'
114
+ autoRefresh: true, // Actualisation automatique
115
+ refreshInterval: 30000, // Intervalle en millisecondes
116
+ redirectUrl: 'https://...', // URL de redirection après succès
117
+ customData: {}, // Données personnalisées
118
+ onSuccess: function(data) {
119
+ // Callback en cas de succès
120
+ },
121
+ onError: function(error) {
122
+ // Callback en cas d'erreur
123
+ },
124
+ onExpired: function() {
125
+ // Callback quand le QR expire
126
+ }
127
+ };
128
+ ```
129
+
130
+ ## 📱 Exemples Complets
131
+
132
+ ### Page de Connexion
133
+
134
+ ```html
135
+ <!DOCTYPE html>
136
+ <html lang="fr">
137
+ <head>
138
+ <meta charset="UTF-8">
139
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
140
+ <title>Connexion - Mon Application</title>
141
+ <link rel="stylesheet" href="https://sunuid.sn/css/sunuid-sdk.css">
142
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
143
+ </head>
144
+ <body>
145
+ <div class="login-container">
146
+ <h1>Connexion Sécurisée</h1>
147
+ <p>Scannez le QR code avec l'application SunuID</p>
148
+
149
+ <!-- Conteneur pour le QR code -->
150
+ <div id="auth-qr-container"></div>
151
+
152
+ <div class="login-footer">
153
+ <p>Pas encore d'application SunuID ?</p>
154
+ <a href="https://sunuid.sn/download" target="_blank">Télécharger</a>
155
+ </div>
156
+ </div>
157
+
158
+ <script src="https://sunuid.sn/js/sunuid-sdk.js"></script>
159
+ <script>
160
+ // Configuration
161
+ const sunuid = initSunuID({
162
+ apiUrl: 'https://sunuid.sn/api',
163
+ partnerId: 'VOTRE_PARTNER_ID',
164
+ clientId: 'VOTRE_CLIENT_ID',
165
+ secretId: 'VOTRE_SECRET_ID',
166
+ theme: 'light',
167
+ onSuccess: function(data) {
168
+ // Rediriger vers le dashboard
169
+ window.location.href = '/dashboard?token=' + data.token;
170
+ },
171
+ onError: function(error) {
172
+ alert('Erreur de connexion: ' + error.message);
173
+ }
174
+ });
175
+
176
+ // Générer le QR code
177
+ sunuid.generateAuthQR('auth-qr-container');
178
+ </script>
179
+ </body>
180
+ </html>
181
+ ```
182
+
183
+ ### Processus KYC
184
+
185
+ ```html
186
+ <!DOCTYPE html>
187
+ <html lang="fr">
188
+ <head>
189
+ <meta charset="UTF-8">
190
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
191
+ <title>Vérification KYC</title>
192
+ <link rel="stylesheet" href="https://sunuid.sn/css/sunuid-sdk.css">
193
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
194
+ </head>
195
+ <body>
196
+ <div class="kyc-container">
197
+ <h1>Vérification d'Identité</h1>
198
+ <p>Complétez votre profil avec SunuID</p>
199
+
200
+ <!-- Conteneur pour le QR code KYC -->
201
+ <div id="kyc-qr-container"></div>
202
+
203
+ <div class="kyc-info">
204
+ <h3>Informations requises :</h3>
205
+ <ul>
206
+ <li>Pièce d'identité (CNI, Passeport)</li>
207
+ <li>Justificatif de domicile</li>
208
+ <li>Photo de profil</li>
209
+ </ul>
210
+ </div>
211
+ </div>
212
+
213
+ <script src="https://sunuid.sn/js/sunuid-sdk.js"></script>
214
+ <script>
215
+ const sunuid = initSunuID({
216
+ apiUrl: 'https://sunuid.sn/api',
217
+ partnerId: 'VOTRE_PARTNER_ID',
218
+ clientId: 'VOTRE_CLIENT_ID',
219
+ secretId: 'VOTRE_SECRET_ID',
220
+ theme: 'dark',
221
+ onSuccess: function(data) {
222
+ // KYC complété
223
+ window.location.href = '/kyc-complete?status=success';
224
+ },
225
+ onError: function(error) {
226
+ alert('Erreur KYC: ' + error.message);
227
+ }
228
+ });
229
+
230
+ // Générer le QR code KYC
231
+ sunuid.generateKYCQR('kyc-qr-container', {
232
+ kycType: 'full',
233
+ requiredFields: ['identity', 'address', 'phone', 'photo']
234
+ });
235
+ </script>
236
+ </body>
237
+ </html>
238
+ ```
239
+
240
+ ## 🔧 API Référence
241
+
242
+ ### Méthodes principales
243
+
244
+ #### `generateAuthQR(containerId, options)`
245
+ Génère un QR code d'authentification.
246
+
247
+ **Paramètres :**
248
+ - `containerId` (string) : ID du conteneur HTML
249
+ - `options` (object) : Options de configuration
250
+
251
+ #### `generateKYCQR(containerId, options)`
252
+ Génère un QR code KYC.
253
+
254
+ **Paramètres :**
255
+ - `containerId` (string) : ID du conteneur HTML
256
+ - `options` (object) : Options de configuration
257
+
258
+ #### `checkQRStatus(qrId)`
259
+ Vérifie le statut d'un QR code.
260
+
261
+ **Paramètres :**
262
+ - `qrId` (string) : ID du QR code
263
+
264
+ #### `refreshQR(containerId, type, options)`
265
+ Actualise un QR code.
266
+
267
+ **Paramètres :**
268
+ - `containerId` (string) : ID du conteneur HTML
269
+ - `type` (string) : 'auth' ou 'kyc'
270
+ - `options` (object) : Options de configuration
271
+
272
+ #### `destroy()`
273
+ Nettoie les ressources du SDK.
274
+
275
+ ### Événements
276
+
277
+ #### `onSuccess(data)`
278
+ Appelé quand l'authentification/KYC est réussie.
279
+
280
+ #### `onError(error)`
281
+ Appelé en cas d'erreur.
282
+
283
+ #### `onExpired()`
284
+ Appelé quand le QR code expire.
285
+
286
+ ## 🛡️ Sécurité
287
+
288
+ ### Authentification
289
+ Le SDK utilise les clés API du partenaire pour s'authentifier :
290
+ - `X-SunuID-Client-ID`
291
+ - `X-SunuID-Secret-ID`
292
+ - `X-SunuID-Partner-ID`
293
+
294
+ ### Validation
295
+ - Vérification des paramètres requis
296
+ - Validation des URLs de redirection
297
+ - Protection contre les attaques CSRF
298
+
299
+ ## 📊 Monitoring
300
+
301
+ ### Logs
302
+ Le SDK génère des logs pour le debugging :
303
+ ```javascript
304
+ console.log('SunuID SDK initialisé avec succès');
305
+ console.error('SunuID SDK Error:', error);
306
+ ```
307
+
308
+ ### Métriques
309
+ Les partenaires peuvent suivre :
310
+ - Nombre de QR codes générés
311
+ - Taux de succès d'authentification
312
+ - Temps de réponse de l'API
313
+
314
+ ## 🆘 Support
315
+
316
+ ### Documentation
317
+ - [Guide d'intégration](https://docs.sunuid.sn)
318
+ - [API Reference](https://api.sunuid.sn/docs)
319
+ - [Exemples](https://github.com/sunuid/sdk-examples)
320
+
321
+ ### Support technique
322
+ - Email : support@sunuid.sn
323
+ - Chat : https://chat.sunuid.sn
324
+ - Documentation : https://docs.sunuid.sn
325
+
326
+ ## 📄 Licence
327
+
328
+ Ce SDK est distribué sous licence MIT. Voir le fichier LICENSE pour plus de détails.
329
+
330
+ ---
331
+
332
+ **Version :** 1.0.0
333
+ **Dernière mise à jour :** Août 2025
334
+ **Compatibilité :** ES6+, IE11+
@@ -0,0 +1,369 @@
1
+ # 🔒 Guide de Sécurisation - SunuID SDK
2
+
3
+ Ce guide explique les différentes méthodes pour sécuriser les credentials lors de l'utilisation du SDK SunuID.
4
+
5
+ ## 🚨 Problème de Sécurité
6
+
7
+ **NE JAMAIS** exposer les credentials (`clientId` et `secretId`) directement dans le code JavaScript côté client, car ils seraient visibles par tous les utilisateurs.
8
+
9
+ ```javascript
10
+ // ❌ DANGEREUX - Ne jamais faire cela
11
+ const config = {
12
+ clientId: '1754166754_221A57B46843D755', // Visible par tous !
13
+ secretId: '56d40fe70507228b27f2640ae65894177c2fedbf246e2b30978fde1fc43953c5', // Visible par tous !
14
+ type: 2
15
+ };
16
+ ```
17
+
18
+ ## ✅ Solutions de Sécurisation
19
+
20
+ ### 1. Initialisation Sécurisée (Recommandée)
21
+
22
+ Le SDK dispose d'un système d'initialisation sécurisée qui récupère les credentials via un token temporaire.
23
+
24
+ #### Configuration côté serveur
25
+
26
+ 1. **Créer le fichier `secure-init.php`** (déjà fourni dans le SDK) :
27
+
28
+ ```php
29
+ <?php
30
+ // Configuration sécurisée (à stocker dans un fichier .env en production)
31
+ $SUNUID_CONFIG = [
32
+ 'client_id' => 'VOTRE_CLIENT_ID',
33
+ 'secret_id' => 'VOTRE_SECRET_ID',
34
+ 'api_url' => 'https://api.sunuid.fayma.sn',
35
+ 'token_expiry' => 3600, // 1 heure
36
+ 'max_requests_per_token' => 100
37
+ ];
38
+ ```
39
+
40
+ 2. **Configurer les credentials** dans votre endpoint sécurisé :
41
+ - Remplacez `VOTRE_CLIENT_ID` et `VOTRE_SECRET_ID` par vos vrais credentials
42
+ - Stockez ce fichier en dehors du répertoire public si possible
43
+ - Utilisez des variables d'environnement en production
44
+
45
+ #### Configuration côté client
46
+
47
+ ```javascript
48
+ // ✅ SÉCURISÉ - Aucun credential exposé
49
+ const secureConfig = {
50
+ type: 2, // 1=KYC, 2=AUTH, 3=SIGNATURE
51
+ partnerName: 'MonApplication',
52
+ theme: 'light',
53
+
54
+ // Activer l'initialisation sécurisée
55
+ secureInit: true,
56
+ secureInitUrl: '/secure-init.php', // URL vers votre endpoint sécurisé (à créer)
57
+
58
+ // Options de sécurité
59
+ enableSecurityLogs: true,
60
+ validateInputs: true,
61
+ maxRetries: 3,
62
+ requestTimeout: 10000
63
+ };
64
+
65
+ // Utilisation
66
+ const sunuid = new SunuID(secureConfig);
67
+ await sunuid.init(); // Les credentials sont récupérés automatiquement
68
+ ```
69
+
70
+ #### Avantages de l'initialisation sécurisée
71
+
72
+ - ✅ **Aucun credential exposé** dans le code client
73
+ - ✅ **Tokens temporaires** avec expiration
74
+ - ✅ **Limitation des requêtes** par token
75
+ - ✅ **Logs de sécurité** automatiques
76
+ - ✅ **Validation des paramètres** côté serveur
77
+
78
+ ### 2. Variables d'Environnement (Production)
79
+
80
+ Pour une sécurité maximale en production, utilisez des variables d'environnement :
81
+
82
+ #### Configuration serveur (.env)
83
+
84
+ ```env
85
+ SUNUID_CLIENT_ID=1754166754_221A57B46843D755
86
+ SUNUID_SECRET_ID=56d40fe70507228b27f2640ae65894177c2fedbf246e2b30978fde1fc43953c5
87
+ SUNUID_API_URL=https://api.sunuid.fayma.sn
88
+ SUNUID_TOKEN_EXPIRY=3600
89
+ SUNUID_MAX_REQUESTS=100
90
+ ```
91
+
92
+ #### Modification de votre endpoint sécurisé
93
+
94
+ ```php
95
+ <?php
96
+ // Charger les variables d'environnement
97
+ require_once 'vendor/autoload.php'; // Si vous utilisez Composer
98
+ $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
99
+ $dotenv->load();
100
+
101
+ $SUNUID_CONFIG = [
102
+ 'client_id' => $_ENV['SUNUID_CLIENT_ID'],
103
+ 'secret_id' => $_ENV['SUNUID_SECRET_ID'],
104
+ 'api_url' => $_ENV['SUNUID_API_URL'],
105
+ 'token_expiry' => (int)$_ENV['SUNUID_TOKEN_EXPIRY'],
106
+ 'max_requests_per_token' => (int)$_ENV['SUNUID_MAX_REQUESTS']
107
+ ];
108
+ ```
109
+
110
+ ### 3. Proxy API (Alternative)
111
+
112
+ Si vous ne pouvez pas utiliser l'initialisation sécurisée, créez un proxy API :
113
+
114
+ #### Proxy API (proxy-sunuid.php)
115
+
116
+ ```php
117
+ <?php
118
+ // proxy-sunuid.php - À créer selon vos besoins
119
+ header('Content-Type: application/json');
120
+ header('Access-Control-Allow-Origin: *');
121
+ header('Access-Control-Allow-Methods: POST');
122
+ header('Access-Control-Allow-Headers: Content-Type');
123
+
124
+ // Configuration sécurisée
125
+ $config = [
126
+ 'client_id' => $_ENV['SUNUID_CLIENT_ID'],
127
+ 'secret_id' => $_ENV['SUNUID_SECRET_ID'],
128
+ 'api_url' => 'https://api.sunuid.fayma.sn'
129
+ ];
130
+
131
+ // Récupérer les données de la requête
132
+ $input = json_decode(file_get_contents('php://input'), true);
133
+ $endpoint = $_GET['endpoint'] ?? '';
134
+
135
+ // Valider l'endpoint
136
+ $allowedEndpoints = ['qr-generate', 'qr-status', 'debug'];
137
+ if (!in_array($endpoint, $allowedEndpoints)) {
138
+ http_response_code(400);
139
+ echo json_encode(['error' => 'Endpoint non autorisé']);
140
+ exit;
141
+ }
142
+
143
+ // Faire la requête vers l'API SunuID
144
+ $ch = curl_init();
145
+ curl_setopt($ch, CURLOPT_URL, $config['api_url'] . '/' . $endpoint);
146
+ curl_setopt($ch, CURLOPT_POST, true);
147
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($input));
148
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
149
+ 'Content-Type: application/json'
150
+ ]);
151
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
152
+
153
+ $response = curl_exec($ch);
154
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
155
+ curl_close($ch);
156
+
157
+ http_response_code($httpCode);
158
+ echo $response;
159
+ ?>
160
+ ```
161
+
162
+ #### Configuration côté client
163
+
164
+ ```javascript
165
+ // Configuration avec proxy
166
+ const proxyConfig = {
167
+ type: 2,
168
+ partnerName: 'MonApplication',
169
+
170
+ // Utiliser le proxy au lieu de l'API directe
171
+ apiUrl: '/proxy-sunuid.php',
172
+
173
+ // Les credentials sont gérés côté serveur
174
+ secureInit: false // Désactiver car on utilise le proxy
175
+ };
176
+
177
+ const sunuid = new SunuID(proxyConfig);
178
+ await sunuid.init();
179
+ ```
180
+
181
+ ### 4. Chiffrement côté client (Moins sécurisé)
182
+
183
+ ⚠️ **ATTENTION** : Cette méthode est moins sécurisée car le chiffrement peut être inversé.
184
+
185
+ ```javascript
186
+ // Chiffrement simple (à éviter en production)
187
+ function encryptCredentials(clientId, secretId, key) {
188
+ const data = clientId + '|' + secretId;
189
+ return btoa(data + '|' + key);
190
+ }
191
+
192
+ function decryptCredentials(encrypted, key) {
193
+ try {
194
+ const decoded = atob(encrypted);
195
+ const parts = decoded.split('|');
196
+ if (parts[2] === key) {
197
+ return {
198
+ clientId: parts[0],
199
+ secretId: parts[1]
200
+ };
201
+ }
202
+ } catch (e) {
203
+ console.error('Erreur déchiffrement:', e);
204
+ }
205
+ return null;
206
+ }
207
+
208
+ // Utilisation (moins sécurisé)
209
+ const encrypted = encryptCredentials('clientId', 'secretId', 'maCleSecrete');
210
+ const credentials = decryptCredentials(encrypted, 'maCleSecrete');
211
+
212
+ const config = {
213
+ clientId: credentials.clientId,
214
+ secretId: credentials.secretId,
215
+ type: 2
216
+ };
217
+ ```
218
+
219
+ ## 🔧 Configuration Recommandée
220
+
221
+ ### Pour le Développement
222
+
223
+ ```javascript
224
+ // Utiliser l'initialisation sécurisée avec secure-init.php
225
+ const devConfig = {
226
+ type: 2,
227
+ partnerName: 'DevApp',
228
+ secureInit: true,
229
+ secureInitUrl: '/secure-init.php',
230
+ enableSecurityLogs: true
231
+ };
232
+ ```
233
+
234
+ ### Pour la Production
235
+
236
+ ```javascript
237
+ // Utiliser des variables d'environnement + initialisation sécurisée
238
+ const prodConfig = {
239
+ type: 2,
240
+ partnerName: 'ProdApp',
241
+ secureInit: true,
242
+ secureInitUrl: '/api/secure-init', // Endpoint sécurisé
243
+ enableSecurityLogs: true,
244
+ validateInputs: true,
245
+ maxRetries: 3,
246
+ requestTimeout: 10000
247
+ };
248
+ ```
249
+
250
+ ## 🛡️ Bonnes Pratiques de Sécurité
251
+
252
+ ### 1. Protection des Fichiers
253
+
254
+ ```apache
255
+ # .htaccess - Protéger les fichiers sensibles
256
+ <Files "secure-init.php">
257
+ Order Allow,Deny
258
+ Deny from all
259
+ </Files>
260
+
261
+ <Files ".env">
262
+ Order Allow,Deny
263
+ Deny from all
264
+ </Files>
265
+ ```
266
+
267
+ ### 2. Validation côté serveur
268
+
269
+ ```php
270
+ // Valider les paramètres d'entrée
271
+ function validateRequest($data) {
272
+ $errors = [];
273
+
274
+ if (!isset($data['type']) || !in_array($data['type'], [1, 2, 3])) {
275
+ $errors[] = 'Type invalide';
276
+ }
277
+
278
+ if (!isset($data['partnerName']) || strlen($data['partnerName']) < 2) {
279
+ $errors[] = 'Nom partenaire invalide';
280
+ }
281
+
282
+ return $errors;
283
+ }
284
+ ```
285
+
286
+ ### 3. Logs de Sécurité
287
+
288
+ ```php
289
+ // Logger les tentatives d'accès
290
+ function logSecurityEvent($event, $data) {
291
+ $log = [
292
+ 'timestamp' => date('c'),
293
+ 'event' => $event,
294
+ 'ip' => $_SERVER['REMOTE_ADDR'],
295
+ 'user_agent' => $_SERVER['HTTP_USER_AGENT'],
296
+ 'data' => $data
297
+ ];
298
+
299
+ error_log('SunuID Security: ' . json_encode($log));
300
+ }
301
+ ```
302
+
303
+ ### 4. Rate Limiting
304
+
305
+ ```php
306
+ // Limiter le nombre de requêtes par IP
307
+ function checkRateLimit($ip) {
308
+ $cacheFile = sys_get_temp_dir() . '/sunuid_rate_limit_' . md5($ip);
309
+ $limit = 10; // 10 requêtes
310
+ $window = 3600; // par heure
311
+
312
+ if (file_exists($cacheFile)) {
313
+ $data = json_decode(file_get_contents($cacheFile), true);
314
+ if ($data['count'] >= $limit && (time() - $data['start']) < $window) {
315
+ return false; // Limite dépassée
316
+ }
317
+ }
318
+
319
+ // Mettre à jour le compteur
320
+ file_put_contents($cacheFile, json_encode([
321
+ 'count' => ($data['count'] ?? 0) + 1,
322
+ 'start' => $data['start'] ?? time()
323
+ ]));
324
+
325
+ return true;
326
+ }
327
+ ```
328
+
329
+ ## 📋 Checklist de Sécurité
330
+
331
+ - [ ] ✅ Utiliser l'initialisation sécurisée (`secureInit: true`)
332
+ - [ ] ✅ Stocker les credentials dans des variables d'environnement
333
+ - [ ] ✅ Protéger les fichiers sensibles avec `.htaccess`
334
+ - [ ] ✅ Valider tous les paramètres d'entrée
335
+ - [ ] ✅ Implémenter des logs de sécurité
336
+ - [ ] ✅ Limiter le taux de requêtes
337
+ - [ ] ✅ Utiliser HTTPS en production
338
+ - [ ] ✅ Vérifier régulièrement les logs de sécurité
339
+ - [ ] ✅ Mettre à jour les credentials régulièrement
340
+ - [ ] ✅ Tester la sécurité avec des outils d'audit
341
+
342
+ ## 🚨 Signaux d'Alerte
343
+
344
+ Si vous voyez ces patterns dans votre code, c'est un signe de problème de sécurité :
345
+
346
+ ```javascript
347
+ // ❌ DANGEREUX
348
+ const clientId = '1754166754_221A57B46843D755';
349
+ const secretId = '56d40fe70507228b27f2640ae65894177c2fedbf246e2b30978fde1fc43953c5';
350
+
351
+ // ❌ DANGEREUX
352
+ const config = {
353
+ clientId: window.SUNUID_CLIENT_ID, // Variable globale
354
+ secretId: localStorage.getItem('sunuid_secret') // Stockage local
355
+ };
356
+ ```
357
+
358
+ ## 📞 Support
359
+
360
+ Si vous avez des questions sur la sécurisation, consultez :
361
+
362
+ 1. **Documentation officielle** : `/docs/`
363
+ 2. **Exemples sécurisés** : `/examples/secure-integration.html`
364
+ 3. **Code source** : `/src/sunuid-sdk.js`
365
+
366
+ ---
367
+
368
+ **⚠️ Rappel important** : La sécurité de vos credentials est de votre responsabilité. Suivez toujours les bonnes pratiques et testez votre implémentation avant la mise en production.
369
+