sunuid-sdk 1.0.50 → 1.0.52

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,368 @@
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 `secure-init.php` :
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é
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 secure-init.php
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
+ header('Content-Type: application/json');
119
+ header('Access-Control-Allow-Origin: *');
120
+ header('Access-Control-Allow-Methods: POST');
121
+ header('Access-Control-Allow-Headers: Content-Type');
122
+
123
+ // Configuration sécurisée
124
+ $config = [
125
+ 'client_id' => $_ENV['SUNUID_CLIENT_ID'],
126
+ 'secret_id' => $_ENV['SUNUID_SECRET_ID'],
127
+ 'api_url' => 'https://api.sunuid.fayma.sn'
128
+ ];
129
+
130
+ // Récupérer les données de la requête
131
+ $input = json_decode(file_get_contents('php://input'), true);
132
+ $endpoint = $_GET['endpoint'] ?? '';
133
+
134
+ // Valider l'endpoint
135
+ $allowedEndpoints = ['qr-generate', 'qr-status', 'debug'];
136
+ if (!in_array($endpoint, $allowedEndpoints)) {
137
+ http_response_code(400);
138
+ echo json_encode(['error' => 'Endpoint non autorisé']);
139
+ exit;
140
+ }
141
+
142
+ // Faire la requête vers l'API SunuID
143
+ $ch = curl_init();
144
+ curl_setopt($ch, CURLOPT_URL, $config['api_url'] . '/' . $endpoint);
145
+ curl_setopt($ch, CURLOPT_POST, true);
146
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($input));
147
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
148
+ 'Content-Type: application/json'
149
+ ]);
150
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
151
+
152
+ $response = curl_exec($ch);
153
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
154
+ curl_close($ch);
155
+
156
+ http_response_code($httpCode);
157
+ echo $response;
158
+ ?>
159
+ ```
160
+
161
+ #### Configuration côté client
162
+
163
+ ```javascript
164
+ // Configuration avec proxy
165
+ const proxyConfig = {
166
+ type: 2,
167
+ partnerName: 'MonApplication',
168
+
169
+ // Utiliser le proxy au lieu de l'API directe
170
+ apiUrl: '/proxy-sunuid.php',
171
+
172
+ // Les credentials sont gérés côté serveur
173
+ secureInit: false // Désactiver car on utilise le proxy
174
+ };
175
+
176
+ const sunuid = new SunuID(proxyConfig);
177
+ await sunuid.init();
178
+ ```
179
+
180
+ ### 4. Chiffrement côté client (Moins sécurisé)
181
+
182
+ ⚠️ **ATTENTION** : Cette méthode est moins sécurisée car le chiffrement peut être inversé.
183
+
184
+ ```javascript
185
+ // Chiffrement simple (à éviter en production)
186
+ function encryptCredentials(clientId, secretId, key) {
187
+ const data = clientId + '|' + secretId;
188
+ return btoa(data + '|' + key);
189
+ }
190
+
191
+ function decryptCredentials(encrypted, key) {
192
+ try {
193
+ const decoded = atob(encrypted);
194
+ const parts = decoded.split('|');
195
+ if (parts[2] === key) {
196
+ return {
197
+ clientId: parts[0],
198
+ secretId: parts[1]
199
+ };
200
+ }
201
+ } catch (e) {
202
+ console.error('Erreur déchiffrement:', e);
203
+ }
204
+ return null;
205
+ }
206
+
207
+ // Utilisation (moins sécurisé)
208
+ const encrypted = encryptCredentials('clientId', 'secretId', 'maCleSecrete');
209
+ const credentials = decryptCredentials(encrypted, 'maCleSecrete');
210
+
211
+ const config = {
212
+ clientId: credentials.clientId,
213
+ secretId: credentials.secretId,
214
+ type: 2
215
+ };
216
+ ```
217
+
218
+ ## 🔧 Configuration Recommandée
219
+
220
+ ### Pour le Développement
221
+
222
+ ```javascript
223
+ // Utiliser l'initialisation sécurisée avec secure-init.php
224
+ const devConfig = {
225
+ type: 2,
226
+ partnerName: 'DevApp',
227
+ secureInit: true,
228
+ secureInitUrl: '/secure-init.php',
229
+ enableSecurityLogs: true
230
+ };
231
+ ```
232
+
233
+ ### Pour la Production
234
+
235
+ ```javascript
236
+ // Utiliser des variables d'environnement + initialisation sécurisée
237
+ const prodConfig = {
238
+ type: 2,
239
+ partnerName: 'ProdApp',
240
+ secureInit: true,
241
+ secureInitUrl: '/api/secure-init', // Endpoint sécurisé
242
+ enableSecurityLogs: true,
243
+ validateInputs: true,
244
+ maxRetries: 3,
245
+ requestTimeout: 10000
246
+ };
247
+ ```
248
+
249
+ ## 🛡️ Bonnes Pratiques de Sécurité
250
+
251
+ ### 1. Protection des Fichiers
252
+
253
+ ```apache
254
+ # .htaccess - Protéger les fichiers sensibles
255
+ <Files "secure-init.php">
256
+ Order Allow,Deny
257
+ Deny from all
258
+ </Files>
259
+
260
+ <Files ".env">
261
+ Order Allow,Deny
262
+ Deny from all
263
+ </Files>
264
+ ```
265
+
266
+ ### 2. Validation côté serveur
267
+
268
+ ```php
269
+ // Valider les paramètres d'entrée
270
+ function validateRequest($data) {
271
+ $errors = [];
272
+
273
+ if (!isset($data['type']) || !in_array($data['type'], [1, 2, 3])) {
274
+ $errors[] = 'Type invalide';
275
+ }
276
+
277
+ if (!isset($data['partnerName']) || strlen($data['partnerName']) < 2) {
278
+ $errors[] = 'Nom partenaire invalide';
279
+ }
280
+
281
+ return $errors;
282
+ }
283
+ ```
284
+
285
+ ### 3. Logs de Sécurité
286
+
287
+ ```php
288
+ // Logger les tentatives d'accès
289
+ function logSecurityEvent($event, $data) {
290
+ $log = [
291
+ 'timestamp' => date('c'),
292
+ 'event' => $event,
293
+ 'ip' => $_SERVER['REMOTE_ADDR'],
294
+ 'user_agent' => $_SERVER['HTTP_USER_AGENT'],
295
+ 'data' => $data
296
+ ];
297
+
298
+ error_log('SunuID Security: ' . json_encode($log));
299
+ }
300
+ ```
301
+
302
+ ### 4. Rate Limiting
303
+
304
+ ```php
305
+ // Limiter le nombre de requêtes par IP
306
+ function checkRateLimit($ip) {
307
+ $cacheFile = sys_get_temp_dir() . '/sunuid_rate_limit_' . md5($ip);
308
+ $limit = 10; // 10 requêtes
309
+ $window = 3600; // par heure
310
+
311
+ if (file_exists($cacheFile)) {
312
+ $data = json_decode(file_get_contents($cacheFile), true);
313
+ if ($data['count'] >= $limit && (time() - $data['start']) < $window) {
314
+ return false; // Limite dépassée
315
+ }
316
+ }
317
+
318
+ // Mettre à jour le compteur
319
+ file_put_contents($cacheFile, json_encode([
320
+ 'count' => ($data['count'] ?? 0) + 1,
321
+ 'start' => $data['start'] ?? time()
322
+ ]));
323
+
324
+ return true;
325
+ }
326
+ ```
327
+
328
+ ## 📋 Checklist de Sécurité
329
+
330
+ - [ ] ✅ Utiliser l'initialisation sécurisée (`secureInit: true`)
331
+ - [ ] ✅ Stocker les credentials dans des variables d'environnement
332
+ - [ ] ✅ Protéger les fichiers sensibles avec `.htaccess`
333
+ - [ ] ✅ Valider tous les paramètres d'entrée
334
+ - [ ] ✅ Implémenter des logs de sécurité
335
+ - [ ] ✅ Limiter le taux de requêtes
336
+ - [ ] ✅ Utiliser HTTPS en production
337
+ - [ ] ✅ Vérifier régulièrement les logs de sécurité
338
+ - [ ] ✅ Mettre à jour les credentials régulièrement
339
+ - [ ] ✅ Tester la sécurité avec des outils d'audit
340
+
341
+ ## 🚨 Signaux d'Alerte
342
+
343
+ Si vous voyez ces patterns dans votre code, c'est un signe de problème de sécurité :
344
+
345
+ ```javascript
346
+ // ❌ DANGEREUX
347
+ const clientId = '1754166754_221A57B46843D755';
348
+ const secretId = '56d40fe70507228b27f2640ae65894177c2fedbf246e2b30978fde1fc43953c5';
349
+
350
+ // ❌ DANGEREUX
351
+ const config = {
352
+ clientId: window.SUNUID_CLIENT_ID, // Variable globale
353
+ secretId: localStorage.getItem('sunuid_secret') // Stockage local
354
+ };
355
+ ```
356
+
357
+ ## 📞 Support
358
+
359
+ Si vous avez des questions sur la sécurisation, consultez :
360
+
361
+ 1. **Documentation officielle** : `/docs/`
362
+ 2. **Exemples sécurisés** : `/examples/secure-integration.html`
363
+ 3. **Code source** : `/src/sunuid-sdk.js`
364
+
365
+ ---
366
+
367
+ **⚠️ 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.
368
+