sunuid-sdk 1.0.52 → 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.
- package/README.md +4 -4
- package/dist/sunuid-sdk.esm.js +5 -5
- package/dist/sunuid-sdk.esm.js.map +1 -1
- package/dist/sunuid-sdk.js +5 -5
- package/dist/sunuid-sdk.js.map +1 -1
- package/dist/sunuid-sdk.min.js +1 -1
- package/dist/sunuid-sdk.min.js.map +1 -1
- package/docs/SECURITY_GUIDE.md +4 -3
- package/examples/.htaccess.example +9 -6
- package/examples/partner-name-config.js +3 -3
- package/examples/production-config.js +1 -1
- package/examples/secure-init.php +154 -0
- package/examples/secure-integration-example.js +2 -2
- package/examples/secure-integration.html +1 -1
- package/examples/test-production.html +3 -3
- package/package.json +1 -1
- package/examples/basic-usage.php +0 -42
- package/examples/local-qr.php +0 -49
- package/examples/secure-usage.php +0 -309
- package/examples/web-integration.php +0 -138
package/docs/SECURITY_GUIDE.md
CHANGED
|
@@ -37,7 +37,7 @@ $SUNUID_CONFIG = [
|
|
|
37
37
|
];
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
2. **Configurer les credentials** dans
|
|
40
|
+
2. **Configurer les credentials** dans votre endpoint sécurisé :
|
|
41
41
|
- Remplacez `VOTRE_CLIENT_ID` et `VOTRE_SECRET_ID` par vos vrais credentials
|
|
42
42
|
- Stockez ce fichier en dehors du répertoire public si possible
|
|
43
43
|
- Utilisez des variables d'environnement en production
|
|
@@ -53,7 +53,7 @@ const secureConfig = {
|
|
|
53
53
|
|
|
54
54
|
// Activer l'initialisation sécurisée
|
|
55
55
|
secureInit: true,
|
|
56
|
-
secureInitUrl: '/secure-init.php', // URL vers votre endpoint sécurisé
|
|
56
|
+
secureInitUrl: '/secure-init.php', // URL vers votre endpoint sécurisé (à créer)
|
|
57
57
|
|
|
58
58
|
// Options de sécurité
|
|
59
59
|
enableSecurityLogs: true,
|
|
@@ -89,7 +89,7 @@ SUNUID_TOKEN_EXPIRY=3600
|
|
|
89
89
|
SUNUID_MAX_REQUESTS=100
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
#### Modification de
|
|
92
|
+
#### Modification de votre endpoint sécurisé
|
|
93
93
|
|
|
94
94
|
```php
|
|
95
95
|
<?php
|
|
@@ -115,6 +115,7 @@ Si vous ne pouvez pas utiliser l'initialisation sécurisée, créez un proxy API
|
|
|
115
115
|
|
|
116
116
|
```php
|
|
117
117
|
<?php
|
|
118
|
+
// proxy-sunuid.php - À créer selon vos besoins
|
|
118
119
|
header('Content-Type: application/json');
|
|
119
120
|
header('Access-Control-Allow-Origin: *');
|
|
120
121
|
header('Access-Control-Allow-Methods: POST');
|
|
@@ -9,9 +9,12 @@
|
|
|
9
9
|
Deny from all
|
|
10
10
|
</Files>
|
|
11
11
|
|
|
12
|
+
# Note: secure-init.php doit être accessible pour l'initialisation sécurisée
|
|
13
|
+
# mais protégez-le avec une authentification appropriée en production
|
|
12
14
|
<Files "secure-init.php">
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
# En production, utilisez une authentification appropriée
|
|
16
|
+
# Order Allow,Deny
|
|
17
|
+
# Deny from all
|
|
15
18
|
</Files>
|
|
16
19
|
|
|
17
20
|
<Files "*.log">
|
|
@@ -20,12 +23,12 @@
|
|
|
20
23
|
</Files>
|
|
21
24
|
|
|
22
25
|
# Protection des fichiers de développement
|
|
23
|
-
<Files "
|
|
26
|
+
<Files "package.json">
|
|
24
27
|
Order Allow,Deny
|
|
25
28
|
Deny from all
|
|
26
29
|
</Files>
|
|
27
30
|
|
|
28
|
-
<Files "
|
|
31
|
+
<Files "package-lock.json">
|
|
29
32
|
Order Allow,Deny
|
|
30
33
|
Deny from all
|
|
31
34
|
</Files>
|
|
@@ -52,7 +55,7 @@
|
|
|
52
55
|
</Files>
|
|
53
56
|
|
|
54
57
|
# Protection des fichiers de test
|
|
55
|
-
<Files "
|
|
58
|
+
<Files "*.test.js">
|
|
56
59
|
Order Allow,Deny
|
|
57
60
|
Deny from all
|
|
58
61
|
</Files>
|
|
@@ -63,7 +66,7 @@
|
|
|
63
66
|
</Files>
|
|
64
67
|
|
|
65
68
|
# Protection des fichiers de source
|
|
66
|
-
<Files "src/*.
|
|
69
|
+
<Files "src/*.js">
|
|
67
70
|
Order Allow,Deny
|
|
68
71
|
Deny from all
|
|
69
72
|
</Files>
|
|
@@ -31,7 +31,7 @@ const banqueConfig = {
|
|
|
31
31
|
|
|
32
32
|
// Configuration pour la production
|
|
33
33
|
apiUrl: 'https://api.sunuid.fayma.sn',
|
|
34
|
-
secureInitUrl: 'https://sunuid.fayma.sn/secure-init
|
|
34
|
+
secureInitUrl: 'https://sunuid.fayma.sn/secure-init',
|
|
35
35
|
|
|
36
36
|
// Callbacks
|
|
37
37
|
onSuccess: (data) => {
|
|
@@ -53,7 +53,7 @@ const ecommerceConfig = {
|
|
|
53
53
|
|
|
54
54
|
// Configuration pour la production
|
|
55
55
|
apiUrl: 'https://api.sunuid.fayma.sn',
|
|
56
|
-
secureInitUrl: 'https://sunuid.fayma.sn/secure-init
|
|
56
|
+
secureInitUrl: 'https://sunuid.fayma.sn/secure-init',
|
|
57
57
|
|
|
58
58
|
// Callbacks
|
|
59
59
|
onSuccess: (data) => {
|
|
@@ -75,7 +75,7 @@ const adminConfig = {
|
|
|
75
75
|
|
|
76
76
|
// Configuration pour la production
|
|
77
77
|
apiUrl: 'https://api.sunuid.fayma.sn',
|
|
78
|
-
secureInitUrl: 'https://sunuid.fayma.sn/secure-init
|
|
78
|
+
secureInitUrl: 'https://sunuid.fayma.sn/secure-init',
|
|
79
79
|
|
|
80
80
|
// Callbacks
|
|
81
81
|
onSuccess: (data) => {
|
|
@@ -41,7 +41,7 @@ const sunuid = new SunuID({
|
|
|
41
41
|
|
|
42
42
|
// Configuration pour la production
|
|
43
43
|
apiUrl: 'https://api.sunuid.fayma.sn',
|
|
44
|
-
secureInitUrl: 'https://sunuid.fayma.sn/secure-init
|
|
44
|
+
secureInitUrl: 'https://sunuid.fayma.sn/secure-init',
|
|
45
45
|
|
|
46
46
|
// Callbacks
|
|
47
47
|
onSuccess: (data) => {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
/**
|
|
3
|
+
* SunuID SDK - Endpoint d'initialisation sécurisée
|
|
4
|
+
*
|
|
5
|
+
* Ce fichier permet au SDK JavaScript de récupérer des tokens temporaires
|
|
6
|
+
* contenant les credentials sans les exposer directement dans le code client.
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT :
|
|
9
|
+
* - Remplacez les credentials par vos vrais credentials
|
|
10
|
+
* - Stockez ce fichier en dehors du répertoire public si possible
|
|
11
|
+
* - Utilisez des variables d'environnement en production
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Headers CORS pour permettre les requêtes depuis le SDK JavaScript
|
|
15
|
+
header('Content-Type: application/json');
|
|
16
|
+
header('Access-Control-Allow-Origin: *');
|
|
17
|
+
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
|
|
18
|
+
header('Access-Control-Allow-Headers: Content-Type, Authorization');
|
|
19
|
+
|
|
20
|
+
// Gérer les requêtes OPTIONS (preflight)
|
|
21
|
+
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
22
|
+
http_response_code(200);
|
|
23
|
+
exit();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Configuration SunuID (à remplacer par vos vrais credentials)
|
|
27
|
+
$SUNUID_CONFIG = [
|
|
28
|
+
'client_id' => $_ENV['SUNUID_CLIENT_ID'] ?? 'your_client_id_here',
|
|
29
|
+
'secret_id' => $_ENV['SUNUID_SECRET_ID'] ?? 'your_secret_id_here',
|
|
30
|
+
'api_url' => $_ENV['SUNUID_API_URL'] ?? 'https://api.sunuid.fayma.sn',
|
|
31
|
+
'token_expiry' => $_ENV['SUNUID_TOKEN_EXPIRY'] ?? 300, // 5 minutes
|
|
32
|
+
'max_requests' => $_ENV['SUNUID_MAX_REQUESTS'] ?? 10
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Valider les paramètres d'initialisation
|
|
37
|
+
*/
|
|
38
|
+
function validateInitParams($data) {
|
|
39
|
+
$required = ['timestamp', 'nonce'];
|
|
40
|
+
|
|
41
|
+
foreach ($required as $field) {
|
|
42
|
+
if (!isset($data[$field])) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Vérifier que le timestamp n'est pas trop ancien (5 minutes)
|
|
48
|
+
if (time() - $data['timestamp'] > 300) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Générer un token sécurisé contenant les credentials
|
|
57
|
+
*/
|
|
58
|
+
function generateSecureToken($config) {
|
|
59
|
+
$payload = [
|
|
60
|
+
'client_id' => $config['client_id'],
|
|
61
|
+
'secret_id' => $config['secret_id'],
|
|
62
|
+
'api_url' => $config['api_url'],
|
|
63
|
+
'exp' => time() + $config['token_expiry'],
|
|
64
|
+
'iat' => time(),
|
|
65
|
+
'nonce' => bin2hex(random_bytes(16))
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
// Encoder en base64 pour simplicité
|
|
69
|
+
// En production, utilisez JWT ou un chiffrement plus robuste
|
|
70
|
+
return base64_encode(json_encode($payload));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Valider un token reçu
|
|
75
|
+
*/
|
|
76
|
+
function validateToken($token) {
|
|
77
|
+
try {
|
|
78
|
+
$decoded = json_decode(base64_decode($token), true);
|
|
79
|
+
|
|
80
|
+
if (!$decoded) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Vérifier l'expiration
|
|
85
|
+
if (isset($decoded['exp']) && $decoded['exp'] < time()) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return $decoded;
|
|
90
|
+
} catch (Exception $e) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Traitement des requêtes
|
|
96
|
+
$method = $_SERVER['REQUEST_METHOD'];
|
|
97
|
+
$input = json_decode(file_get_contents('php://input'), true) ?? [];
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
switch ($method) {
|
|
101
|
+
case 'POST':
|
|
102
|
+
// Générer un token pour l'initialisation sécurisée
|
|
103
|
+
if (!validateInitParams($input)) {
|
|
104
|
+
throw new Exception('Paramètres invalides');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
$token = generateSecureToken($SUNUID_CONFIG);
|
|
108
|
+
|
|
109
|
+
echo json_encode([
|
|
110
|
+
'success' => true,
|
|
111
|
+
'token' => $token,
|
|
112
|
+
'expires_in' => $SUNUID_CONFIG['token_expiry'],
|
|
113
|
+
'timestamp' => time()
|
|
114
|
+
]);
|
|
115
|
+
break;
|
|
116
|
+
|
|
117
|
+
case 'GET':
|
|
118
|
+
// Valider un token (pour usage côté serveur)
|
|
119
|
+
$token = $_GET['token'] ?? null;
|
|
120
|
+
|
|
121
|
+
if (!$token) {
|
|
122
|
+
throw new Exception('Token manquant');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
$decoded = validateToken($token);
|
|
126
|
+
|
|
127
|
+
if (!$decoded) {
|
|
128
|
+
throw new Exception('Token invalide ou expiré');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
echo json_encode([
|
|
132
|
+
'success' => true,
|
|
133
|
+
'credentials' => [
|
|
134
|
+
'client_id' => $decoded['client_id'],
|
|
135
|
+
'secret_id' => $decoded['secret_id'],
|
|
136
|
+
'api_url' => $decoded['api_url']
|
|
137
|
+
],
|
|
138
|
+
'expires_at' => $decoded['exp']
|
|
139
|
+
]);
|
|
140
|
+
break;
|
|
141
|
+
|
|
142
|
+
default:
|
|
143
|
+
throw new Exception('Méthode non supportée');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
} catch (Exception $e) {
|
|
147
|
+
http_response_code(400);
|
|
148
|
+
echo json_encode([
|
|
149
|
+
'success' => false,
|
|
150
|
+
'error' => $e->getMessage(),
|
|
151
|
+
'timestamp' => time()
|
|
152
|
+
]);
|
|
153
|
+
}
|
|
154
|
+
?>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
// 2. CONFIGURATION SÉCURISÉE (sans credentials)
|
|
13
13
|
const secureConfig = {
|
|
14
|
-
// Aucun credential ici - ils seront récupérés via
|
|
14
|
+
// Aucun credential ici - ils seront récupérés via votre endpoint sécurisé
|
|
15
15
|
type: 2, // 1=KYC, 2=AUTH, 3=SIGNATURE
|
|
16
16
|
partnerName: 'MonApplication', // Nom de votre application
|
|
17
17
|
theme: 'light',
|
|
@@ -19,7 +19,7 @@ const secureConfig = {
|
|
|
19
19
|
|
|
20
20
|
// Activer l'initialisation sécurisée
|
|
21
21
|
secureInit: true,
|
|
22
|
-
secureInitUrl: '/secure-init.php', // URL vers votre endpoint sécurisé
|
|
22
|
+
secureInitUrl: '/secure-init.php', // URL vers votre endpoint sécurisé (voir examples/secure-init.php)
|
|
23
23
|
|
|
24
24
|
// Options de sécurité
|
|
25
25
|
enableSecurityLogs: true,
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
|
|
197
197
|
// Activer l'initialisation sécurisée
|
|
198
198
|
secureInit: true,
|
|
199
|
-
secureInitUrl: '../secure-init.php', // Chemin vers votre endpoint sécurisé
|
|
199
|
+
secureInitUrl: '../secure-init.php', // Chemin vers votre endpoint sécurisé (voir examples/secure-init.php)
|
|
200
200
|
|
|
201
201
|
// Options de sécurité
|
|
202
202
|
enableSecurityLogs: true,
|
|
@@ -121,8 +121,8 @@
|
|
|
121
121
|
|
|
122
122
|
function updateConfigDisplay() {
|
|
123
123
|
document.getElementById('api-url').textContent = window.SunuIDConfig.apiUrl;
|
|
124
|
-
document.getElementById('qr-url').textContent = window.SunuIDConfig.apiUrl.replace('/api', '') + '/qr-generator
|
|
125
|
-
|
|
124
|
+
document.getElementById('qr-url').textContent = window.SunuIDConfig.apiUrl.replace('/api', '') + '/qr-generator';
|
|
125
|
+
document.getElementById('secure-url').textContent = window.SunuIDConfig.apiUrl.replace('/api', '') + '/secure-init';
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
async function testConfiguration() {
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// Vérifier que l'URL de génération QR n'est pas locale
|
|
172
|
-
const qrGeneratorUrl = sunuid.config.apiUrl.replace('/api', '') + '/qr-generator
|
|
172
|
+
const qrGeneratorUrl = sunuid.config.apiUrl.replace('/api', '') + '/qr-generator';
|
|
173
173
|
log(`📡 URL QR Generator: ${qrGeneratorUrl}`);
|
|
174
174
|
|
|
175
175
|
if (qrGeneratorUrl.includes('localhost')) {
|
package/package.json
CHANGED
package/examples/basic-usage.php
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
require_once __DIR__ . '/../vendor/autoload.php';
|
|
4
|
-
|
|
5
|
-
use SunuID\SunuID;
|
|
6
|
-
|
|
7
|
-
// Configuration
|
|
8
|
-
$config = [
|
|
9
|
-
'client_id' => '1754166754_221A57B46843D755',
|
|
10
|
-
'secret_id' => '56d40fe70507228b27f2640ae65894177c2fedbf246e2b30978fde1fc43953c5',
|
|
11
|
-
'type' => 2, // Authentification
|
|
12
|
-
'enable_logs' => true,
|
|
13
|
-
'log_file' => 'sunuid.log'
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
// Créer l'instance SDK
|
|
18
|
-
$sunuid = new SunuID($config);
|
|
19
|
-
|
|
20
|
-
// Initialiser le SDK
|
|
21
|
-
$sunuid->init();
|
|
22
|
-
|
|
23
|
-
echo "✅ SDK initialisé avec succès\n";
|
|
24
|
-
echo "📋 Informations partenaire: " . json_encode($sunuid->getPartnerInfo(), JSON_PRETTY_PRINT) . "\n";
|
|
25
|
-
|
|
26
|
-
// Générer un QR code
|
|
27
|
-
$qrResult = $sunuid->generateQR();
|
|
28
|
-
|
|
29
|
-
echo "🎯 QR Code généré:\n";
|
|
30
|
-
echo " - URL: " . $qrResult['qr_code_url'] . "\n";
|
|
31
|
-
echo " - Contenu: " . $qrResult['content'] . "\n";
|
|
32
|
-
echo " - Session ID: " . $qrResult['session_id'] . "\n";
|
|
33
|
-
echo " - Label: " . $qrResult['label'] . "\n";
|
|
34
|
-
|
|
35
|
-
// Vérifier le statut du QR code
|
|
36
|
-
$status = $sunuid->checkQRStatus($qrResult['session_id']);
|
|
37
|
-
echo "📊 Statut QR: " . json_encode($status, JSON_PRETTY_PRINT) . "\n";
|
|
38
|
-
|
|
39
|
-
} catch (Exception $e) {
|
|
40
|
-
echo "❌ Erreur: " . $e->getMessage() . "\n";
|
|
41
|
-
echo "📍 Fichier: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
|
42
|
-
}
|
package/examples/local-qr.php
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
<?php
|
|
2
|
-
|
|
3
|
-
require_once __DIR__ . '/../vendor/autoload.php';
|
|
4
|
-
|
|
5
|
-
use SunuID\SunuID;
|
|
6
|
-
|
|
7
|
-
// Configuration minimale pour QR local
|
|
8
|
-
$config = [
|
|
9
|
-
'client_id' => '1754166754_221A57B46843D755',
|
|
10
|
-
'secret_id' => '56d40fe70507228b27f2640ae65894177c2fedbf246e2b30978fde1fc43953c5',
|
|
11
|
-
'type' => 2,
|
|
12
|
-
'enable_logs' => true
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
// Créer l'instance SDK
|
|
17
|
-
$sunuid = new SunuID($config);
|
|
18
|
-
|
|
19
|
-
// Initialiser le SDK
|
|
20
|
-
$sunuid->init();
|
|
21
|
-
|
|
22
|
-
echo "✅ SDK initialisé\n";
|
|
23
|
-
|
|
24
|
-
// Générer un QR code local
|
|
25
|
-
$content = "AUTH_" . time() . "_" . bin2hex(random_bytes(8));
|
|
26
|
-
$qrResult = $sunuid->generateQRLocal($content, [
|
|
27
|
-
'size' => 300,
|
|
28
|
-
'margin' => 10,
|
|
29
|
-
'label' => 'Authentification SunuID'
|
|
30
|
-
]);
|
|
31
|
-
|
|
32
|
-
echo "🎯 QR Code local généré:\n";
|
|
33
|
-
echo " - Contenu: " . $qrResult['content'] . "\n";
|
|
34
|
-
echo " - Session ID: " . $qrResult['session_id'] . "\n";
|
|
35
|
-
echo " - Label: " . $qrResult['label'] . "\n";
|
|
36
|
-
echo " - Généré localement: " . ($qrResult['generated_locally'] ? 'Oui' : 'Non') . "\n";
|
|
37
|
-
|
|
38
|
-
// Afficher l'image en base64 (début)
|
|
39
|
-
$dataUri = $qrResult['qr_code_url'];
|
|
40
|
-
echo " - Data URI (début): " . substr($dataUri, 0, 50) . "...\n";
|
|
41
|
-
|
|
42
|
-
// Sauvegarder l'image
|
|
43
|
-
$imageData = base64_decode(str_replace('data:image/png;base64,', '', $dataUri));
|
|
44
|
-
file_put_contents('qr-code-local.png', $imageData);
|
|
45
|
-
echo "💾 Image sauvegardée: qr-code-local.png\n";
|
|
46
|
-
|
|
47
|
-
} catch (Exception $e) {
|
|
48
|
-
echo "❌ Erreur: " . $e->getMessage() . "\n";
|
|
49
|
-
}
|