@ollaid/native-sso 2.5.0 → 2.6.0
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 +229 -43
- package/dist/components/AvatarCropModal.d.ts +1 -1
- package/dist/components/DebugPanel.d.ts +1 -1
- package/dist/components/LoginModal.d.ts +1 -1
- package/dist/components/NativeSSOPage.d.ts +4 -2
- package/dist/components/OnboardingModal.d.ts +1 -1
- package/dist/components/PasswordRecoveryModal.d.ts +1 -1
- package/dist/components/SignupModal.d.ts +1 -1
- package/dist/components/ui.d.ts +1 -1
- package/dist/hooks/useLogout.d.ts +1 -1
- package/dist/hooks/useMobilePassword.d.ts +1 -1
- package/dist/hooks/useMobileRegistration.d.ts +2 -2
- package/dist/hooks/useNativeAuth.d.ts +8 -5
- package/dist/hooks/useTokenHealthCheck.d.ts +1 -1
- package/dist/index-Bpixveaz.js +489 -0
- package/dist/index-Bpixveaz.js.map +1 -0
- package/dist/index-DDOXM37y.cjs +488 -0
- package/dist/index-DDOXM37y.cjs.map +1 -0
- package/dist/index.cjs +7118 -184
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +7118 -184
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts +4 -1
- package/dist/services/api.d.ts +52 -10
- package/dist/services/debugLogger.d.ts +1 -1
- package/dist/services/iamAccount.d.ts +1 -1
- package/dist/services/mobilePassword.d.ts +1 -1
- package/dist/services/mobileRegistration.d.ts +1 -1
- package/dist/services/nativeAuth.d.ts +1 -1
- package/dist/services/profile.d.ts +1 -1
- package/dist/services/profileChange.d.ts +1 -1
- package/dist/services/profileMedia.d.ts +1 -1
- package/dist/types/mobile.d.ts +1 -1
- package/dist/types/native.d.ts +1 -1
- package/dist/web-BQDVoI6q.cjs +146 -0
- package/dist/web-BQDVoI6q.cjs.map +1 -0
- package/dist/web-DPmAPlXS.js +146 -0
- package/dist/web-DPmAPlXS.js.map +1 -0
- package/package.json +10 -3
package/README.md
CHANGED
|
@@ -21,14 +21,16 @@ Package NPM Frontend-First pour l'authentification Native SSO Ollaid.
|
|
|
21
21
|
12. [Configuration .env Laravel](#configuration-env-laravel)
|
|
22
22
|
13. [Migration Laravel](#migration-laravel)
|
|
23
23
|
14. [Flux d'authentification](#flux-dauthentification)
|
|
24
|
-
|
|
24
|
+
15. [Session & storage](#session--storage)
|
|
25
25
|
16. [Déconnexion synchronisée](#déconnexion-synchronisée)
|
|
26
26
|
17. [OnboardingModal](#onboardingmodal)
|
|
27
27
|
18. [useTokenHealthCheck](#usetokenhealthcheck)
|
|
28
28
|
19. [Sécurité](#sécurité)
|
|
29
29
|
20. [Exports](#exports)
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
21. [Publication & Installation npm](#publication--installation-npm)
|
|
31
|
+
22. [Webhooks & Health Check (Backend)](#webhooks--health-check-backend)
|
|
32
|
+
23. [Migration sécurité Web / Capacitor](#migration-sécurité-web--capacitor)
|
|
33
|
+
24. [Métadonnées device](#métadonnées-device)
|
|
32
34
|
|
|
33
35
|
---
|
|
34
36
|
|
|
@@ -38,6 +40,69 @@ Package NPM Frontend-First pour l'authentification Native SSO Ollaid.
|
|
|
38
40
|
npm install @ollaid/native-sso
|
|
39
41
|
```
|
|
40
42
|
|
|
43
|
+
### Compatibilité Capacitor
|
|
44
|
+
|
|
45
|
+
Le package détecte les métadonnées device via `@capacitor/device` quand l'app consommatrice est une app Capacitor.
|
|
46
|
+
|
|
47
|
+
- Capacitor 7: installez `@capacitor/device@^7.x`
|
|
48
|
+
- Capacitor 8: installez `@capacitor/device@^8.x`
|
|
49
|
+
|
|
50
|
+
Le package déclare `@capacitor/device` comme **peer dependency optionnelle**. Il ne force donc pas une version unique pour tous les SaaS intégrateurs.
|
|
51
|
+
|
|
52
|
+
Par défaut, le package chiffre les données persistées dans `localStorage` avec un wrapper interne. Si votre app fournit un `storage` natif plus robuste, il sera utilisé à la place.
|
|
53
|
+
|
|
54
|
+
## Métadonnées device
|
|
55
|
+
|
|
56
|
+
Sur les nouvelles connexions, le package envoie automatiquement au backend SaaS les informations utiles pour identifier la session:
|
|
57
|
+
|
|
58
|
+
- `X-Device-Id`
|
|
59
|
+
- `X-Session-UUID`
|
|
60
|
+
- `X-Device-Name`
|
|
61
|
+
- `X-Device-Model`
|
|
62
|
+
- `X-Device-Manufacturer`
|
|
63
|
+
- `X-Device-Operating-System`
|
|
64
|
+
- `X-Device-Os-Version`
|
|
65
|
+
- `X-Device-Platform`
|
|
66
|
+
- `X-Device-Browser`
|
|
67
|
+
- `X-Device-Language`
|
|
68
|
+
- `X-Device-WebView-Version`
|
|
69
|
+
- `X-Device-Is-Native`
|
|
70
|
+
- `X-Device-Label`
|
|
71
|
+
|
|
72
|
+
Ces données servent à enrichir l'affichage backoffice et à rendre les sessions plus lisibles. Elles ne remplacent pas la géolocalisation IP côté backend, qui reste responsable de `city / region / country`.
|
|
73
|
+
|
|
74
|
+
## Migration sécurité Web / Capacitor
|
|
75
|
+
|
|
76
|
+
Cette section répond à la question la plus importante pour une montée de version en production :
|
|
77
|
+
|
|
78
|
+
- **Installer le nouveau package suffit-il ?**
|
|
79
|
+
- **Oui** pour les changements purement frontend qui gardent le même contrat API.
|
|
80
|
+
- **Non** pour les durcissements de sécurité qui changent le stockage de session, les cookies, ou la synchronisation backend.
|
|
81
|
+
|
|
82
|
+
- **Faut-il aussi modifier le SaaS ?**
|
|
83
|
+
- **Oui** si vous voulez appliquer les recommandations de sécurité de cet audit.
|
|
84
|
+
- **Oui** également si vous voulez une vraie stratégie différente entre **Web** et **Capacitor**.
|
|
85
|
+
|
|
86
|
+
### Règle simple
|
|
87
|
+
|
|
88
|
+
| Cas | Action |
|
|
89
|
+
|---|---|
|
|
90
|
+
| Mise à jour UI / corrections sans changement de contrat | Installer la nouvelle version du package suffit généralement |
|
|
91
|
+
| Sécurité Web avec cookies HttpOnly | Il faut aussi mettre à jour le backend SaaS |
|
|
92
|
+
| Sécurité Capacitor / mobile natif | Il faut adapter le SaaS et l'app mobile, pas seulement le package |
|
|
93
|
+
| Anti-rejeu webhook / durcissement IAM | Il faut modifier le backend SaaS et parfois l'IAM |
|
|
94
|
+
|
|
95
|
+
### Recommandation de déploiement
|
|
96
|
+
|
|
97
|
+
1. Garder la version actuelle compatible en prod.
|
|
98
|
+
2. Ajouter les migrations backend requises avant d'activer les nouvelles règles de sécurité.
|
|
99
|
+
3. Déployer le nouveau package sur un environnement de test.
|
|
100
|
+
4. Vérifier séparément les parcours :
|
|
101
|
+
- Web
|
|
102
|
+
- Capacitor iOS
|
|
103
|
+
- Capacitor Android
|
|
104
|
+
5. Basculer en production seulement après validation des webhooks, logout et refresh.
|
|
105
|
+
|
|
41
106
|
---
|
|
42
107
|
|
|
43
108
|
## Intégration rapide (3 étapes)
|
|
@@ -90,7 +155,7 @@ La page `/auth/native-sso` gère automatiquement :
|
|
|
90
155
|
- ✅ Récupération de mot de passe
|
|
91
156
|
- ✅ Grant access (inscription auto à une nouvelle app)
|
|
92
157
|
- ✅ 2FA (TOTP)
|
|
93
|
-
- ✅ Session persistée
|
|
158
|
+
- ✅ Session persistée via le storage configuré, par défaut `localStorage`
|
|
94
159
|
- ✅ Branding Ollaid SSO
|
|
95
160
|
|
|
96
161
|
---
|
|
@@ -101,10 +166,11 @@ La page `/auth/native-sso` gère automatiquement :
|
|
|
101
166
|
|------|------|--------|-------------|
|
|
102
167
|
| `saasApiUrl` | `string` | ✅ | URL du backend SaaS (ex: `https://mon-saas.com/api`) |
|
|
103
168
|
| `iamApiUrl` | `string` | ✅ | URL du backend IAM (ex: `https://identityam.ollaid.com/api`) |
|
|
104
|
-
| `accountType` | `'user' \| 'client'` | ❌ | Type de compte à persister dans
|
|
169
|
+
| `accountType` | `'user' \| 'client'` | ❌ | Type de compte à persister dans le storage configuré (défaut: `'user'`). Utile si vous avez plusieurs pages SSO avec des rôles différents. |
|
|
105
170
|
| `configPrefix` | `string` | ❌ | **Multi-tenant** : préfixe de configuration IAM côté backend (défaut: `'iam'`). Permet à un même backend SaaS de gérer N applications IAM. Voir [Multi-Tenant](#multi-tenant-plusieurs-applications-sur-le-même-backend). |
|
|
106
171
|
| `onLoginSuccess` | `(token: string, user: UserInfos) => void` | ❌ | Callback après connexion réussie |
|
|
107
172
|
| `onLogout` | `() => void` | ❌ | Callback après déconnexion |
|
|
173
|
+
| `storage` | `NativeStorageAdapter` | ❌ | Stockage injecté pour WebView / Capacitor / secure storage natif. Si absent, le package utilise un `localStorage` chiffré puis un fallback mémoire. |
|
|
108
174
|
| `title` | `string` | ❌ | Titre personnalisé (défaut: "Un compte pour toutes vos applications") |
|
|
109
175
|
| `description` | `string` | ❌ | Description personnalisée |
|
|
110
176
|
| `logoUrl` | `string` | ❌ | URL du logo (remplace le slider) |
|
|
@@ -115,6 +181,8 @@ La page `/auth/native-sso` gère automatiquement :
|
|
|
115
181
|
|
|
116
182
|
> **Note :** Le mode `debug` est contrôlé **uniquement** par le backend via la variable d'environnement `IAM_DEBUG` dans le `.env` du SaaS. Il n'y a plus de prop `debug` à passer au composant. Le `DebugPanel` est **réactif** : il apparaît automatiquement après le chargement des credentials si `debug: true` est retourné par le backend.
|
|
117
183
|
> Quand le `DebugPanel` est visible, il expose aussi des boutons de test pour ouvrir `Connexion`, `Inscription`, `Infos profile` et un reset du rappel profil.
|
|
184
|
+
>
|
|
185
|
+
> **Note Capacitor** : si votre app mobile utilise un secure storage natif, fournissez un adapter via `storage` afin d'aller au-delà du `localStorage` chiffré par défaut du package.
|
|
118
186
|
|
|
119
187
|
### Redirections automatiques (optionnel)
|
|
120
188
|
|
|
@@ -175,9 +243,9 @@ const handleLogout = async () => {
|
|
|
175
243
|
|
|
176
244
|
### Que fait `logout()` ?
|
|
177
245
|
|
|
178
|
-
1. **Révoque
|
|
179
|
-
2. **Révoque la session IAM** — `POST /api/iam/disconnect` (avec `
|
|
180
|
-
3. **Nettoie le
|
|
246
|
+
1. **Révoque la session SaaS** — `POST /api/native/logout`
|
|
247
|
+
2. **Révoque la session IAM** — `POST /api/iam/disconnect` (avec `app_access_token_ref`)
|
|
248
|
+
3. **Nettoie le stockage local** — supprime les clés de session du package
|
|
181
249
|
|
|
182
250
|
Les appels réseau sont en `Promise.allSettled` (best-effort) : même si le serveur est injoignable, le localStorage est **toujours** nettoyé.
|
|
183
251
|
|
|
@@ -185,7 +253,7 @@ Les appels réseau sont en `Promise.allSettled` (best-effort) : même si le serv
|
|
|
185
253
|
|
|
186
254
|
| Clé | Description |
|
|
187
255
|
|-----|-------------|
|
|
188
|
-
| `auth_token` | Token
|
|
256
|
+
| `auth_token` | Token de session SaaS actif |
|
|
189
257
|
| `token` | Token legacy |
|
|
190
258
|
| `user` | Objet utilisateur (avec `iam_reference`, `alias_reference`) |
|
|
191
259
|
| `account_type` | Type de compte (`user` ou `client`) |
|
|
@@ -381,9 +449,27 @@ class NativeConfigController extends Controller
|
|
|
381
449
|
|
|
382
450
|
> **⚠️ Important** : Appliquez la même logique `X-IAM-Config-Prefix` dans `exchange`, `check-token`, `refresh` et `logout`.
|
|
383
451
|
|
|
384
|
-
|
|
452
|
+
## Device metadata & session identity
|
|
453
|
+
|
|
454
|
+
Le package envoie automatiquement des headers de contexte device sur les requêtes d'authentification et de session :
|
|
455
|
+
|
|
385
456
|
- `X-Device-Id` (stable par appareil / webview)
|
|
386
457
|
- `X-Session-UUID` (UUID stable par instance, pour différencier plusieurs sessions sur un même device)
|
|
458
|
+
- `X-Device-Name`
|
|
459
|
+
- `X-Device-Model`
|
|
460
|
+
- `X-Device-Manufacturer`
|
|
461
|
+
- `X-Device-Operating-System`
|
|
462
|
+
- `X-Device-Os-Version`
|
|
463
|
+
- `X-Device-Platform`
|
|
464
|
+
- `X-Device-Browser`
|
|
465
|
+
- `X-Device-Language`
|
|
466
|
+
- `X-Device-WebView-Version`
|
|
467
|
+
- `X-Device-Is-Native`
|
|
468
|
+
- `X-Device-Label`
|
|
469
|
+
|
|
470
|
+
Ces valeurs servent à enrichir la session IAM et l'affichage backoffice. Elles sont utiles pour la traçabilité, mais ne doivent pas être utilisées comme preuve d'identité ou comme facteur d'autorisation à elles seules.
|
|
471
|
+
|
|
472
|
+
> **Note** : la géolocalisation `city / region / country` n'est pas fournie par le package. Elle est calculée côté backend à partir de l'IP observée.
|
|
387
473
|
|
|
388
474
|
---
|
|
389
475
|
|
|
@@ -424,6 +510,14 @@ php artisan config:clear
|
|
|
424
510
|
php artisan config:cache
|
|
425
511
|
```
|
|
426
512
|
|
|
513
|
+
### Sécurité et stockage
|
|
514
|
+
|
|
515
|
+
- Les métadonnées device sont du contexte, pas des secrets.
|
|
516
|
+
- Les tokens d'authentification doivent rester dans un stockage adapté à votre plateforme.
|
|
517
|
+
- Sur Capacitor, utilisez un secure storage natif si vous manipulez des données sensibles longue durée.
|
|
518
|
+
- Ne déduisez jamais les droits utilisateur à partir des seuls headers device.
|
|
519
|
+
- Le package fournit désormais un socle fiable d'identité de session pour les nouvelles connexions; les seules variations restantes viennent du contexte réseau ou du terminal exposé par l'environnement, pas du flux SSO lui-même.
|
|
520
|
+
|
|
427
521
|
---
|
|
428
522
|
|
|
429
523
|
## Usage avancé (composants individuels)
|
|
@@ -1204,7 +1298,6 @@ class NativeAuthController extends Controller
|
|
|
1204
1298
|
$user = $request->user();
|
|
1205
1299
|
|
|
1206
1300
|
if ($user) {
|
|
1207
|
-
$sanctumTokenPlain = $request->bearerToken();
|
|
1208
1301
|
$currentToken = $user->currentAccessToken();
|
|
1209
1302
|
$appAccessTokenRef = $currentToken?->app_access_token_ref ?? null;
|
|
1210
1303
|
|
|
@@ -1212,14 +1305,13 @@ class NativeAuthController extends Controller
|
|
|
1212
1305
|
$currentToken?->delete();
|
|
1213
1306
|
|
|
1214
1307
|
// Notifier l'IAM (fire-and-forget, timeout 5s)
|
|
1215
|
-
if ($
|
|
1308
|
+
if ($appAccessTokenRef) {
|
|
1216
1309
|
$iamPrefix = $request->attributes->get('iam_prefix', 'iam');
|
|
1217
1310
|
$iamApiUrl = config("services.{$iamPrefix}.api_url", 'https://identityam.ollaid.com/api');
|
|
1218
1311
|
try {
|
|
1219
|
-
Http::timeout(5)->post("{$iamApiUrl}/iam/disconnect",
|
|
1220
|
-
'sanctum_token' => $sanctumTokenPlain,
|
|
1312
|
+
Http::timeout(5)->post("{$iamApiUrl}/iam/disconnect", [
|
|
1221
1313
|
'app_access_token_ref' => $appAccessTokenRef,
|
|
1222
|
-
])
|
|
1314
|
+
]);
|
|
1223
1315
|
} catch (\Exception $e) {
|
|
1224
1316
|
Log::warning("[NativeSSO] IAM disconnect failed (non-blocking)", ['error' => $e->getMessage()]);
|
|
1225
1317
|
}
|
|
@@ -1952,36 +2044,62 @@ Toutes les APIs IAM retournent le même objet `user_infos` avec exactement **9 c
|
|
|
1952
2044
|
|
|
1953
2045
|
---
|
|
1954
2046
|
|
|
1955
|
-
## Session &
|
|
2047
|
+
## Session & storage
|
|
1956
2048
|
|
|
1957
|
-
|
|
2049
|
+
Par défaut, le package utilise un petit ensemble de clés préfixées `sso_` dans `localStorage` pour persister la session et le suivi du profil.
|
|
2050
|
+
Vous pouvez injecter un `storage` différent via `NativeSSOPage`, `NativeSSOProvider`, `useNativeAuth` ou `setNativeStorage()`.
|
|
1958
2051
|
|
|
1959
2052
|
| Clé | Contenu | Source | Valeurs possibles |
|
|
1960
2053
|
|-----|---------|--------|-------------------|
|
|
1961
|
-
| `
|
|
1962
|
-
| `
|
|
1963
|
-
| `
|
|
1964
|
-
| `
|
|
1965
|
-
| `
|
|
1966
|
-
| `
|
|
2054
|
+
| `sso_auth_token` | Token Sanctum (bearer) canonique | Réponse de `/api/native/exchange` | Chaîne `"1\|abc123..."` |
|
|
2055
|
+
| `sso_token` | Alias rétrocompatible en lecture | Même source que `sso_auth_token` | Idem |
|
|
2056
|
+
| `sso_user` | Objet utilisateur enrichi sérialisé en JSON | Réponse de `/api/native/exchange` ou mise à jour via health check | `{"iam_reference":"USR-XXX","alias_reference":"ALI-XXX","name":"...","email":"...",...}` |
|
|
2057
|
+
| `sso_account_type` | Type de compte | Déterminé lors du `exchange` selon le mode d'inscription | `"user"` (défaut) ou `"client"` (inscription phone-only) |
|
|
2058
|
+
| `sso_alias_reference` | Référence alias utilisée lors de la connexion | Réponse de `/api/native/exchange` (champ `user.alias_reference`) | `"ALI-XXXXXXXX"` |
|
|
2059
|
+
| `sso_app_access_token_ref` | Référence de l'`AppAccessToken` IAM | Réponse de `/api/native/exchange` (champ `app_access_token_ref`) | `"42"` ou `"aat_ref_abc123"` |
|
|
2060
|
+
| `sso_device_id` | Identifiant stable de l'appareil | Généré par le package | Chaîne stable |
|
|
2061
|
+
| `sso_session_uuid` | UUID stable de la session | Généré par le package | UUID |
|
|
1967
2062
|
| `sso_image_last_status` | Statut du dernier onboarding profil | Mis à jour par `OnboardingModal` | `"true"` ou `"false"` |
|
|
1968
2063
|
| `sso_image_last_check` | Timestamp du dernier contrôle profil | Mis à jour par `OnboardingModal` / sync profil | Millisecondes Unix |
|
|
1969
2064
|
| `sso_image_recheck_at` | Timestamp de rappel après snooze | Mis à jour quand l'utilisateur passe l'onboarding | Millisecondes Unix |
|
|
1970
2065
|
|
|
1971
|
-
> **Note :** `
|
|
1972
|
-
> **Note :** `sso_image_last_status`, `sso_image_last_check` et `sso_image_recheck_at` vivent dans le
|
|
2066
|
+
> **Note :** `sso_account_type` et `sso_alias_reference` sont stockés **séparément** de l'objet `user` en plus d'être inclus dans le JSON de `sso_user`.
|
|
2067
|
+
> **Note :** `sso_image_last_status`, `sso_image_last_check` et `sso_image_recheck_at` vivent dans le storage configuré du SaaS et servent au rappel d'onboarding du profil.
|
|
2068
|
+
> **Note sécurité :** la règle d’activité doit être gérée côté backend avec `last_active_at`. Si `last_active_at` dépasse 6 mois, la session doit être révoquée côté SaaS puis côté IAM.
|
|
1973
2069
|
|
|
1974
2070
|
#### Champs enrichis dans l'objet `user`
|
|
1975
2071
|
|
|
1976
|
-
L'objet `user` stocké
|
|
2072
|
+
L'objet `user` stocké dans `sso_user` contient deux champs ajoutés automatiquement par le package :
|
|
1977
2073
|
- `iam_reference` : la référence IAM de l'utilisateur (`USR-XXXXXXXX`), extraite de `user.reference`
|
|
1978
2074
|
- `alias_reference` : la référence de l'alias utilisé lors de la connexion (`ALI-XXXXXXXX`), extraite de `user.alias_reference`
|
|
1979
2075
|
|
|
1980
2076
|
### Nettoyage
|
|
1981
2077
|
|
|
1982
|
-
Lors du `logout()`, les
|
|
2078
|
+
Lors du `logout()`, les clés de session sont supprimées via `clearAuthToken()`.
|
|
1983
2079
|
Les clés de rappel profil (`sso_image_*`) ne sont pas effacées, afin de conserver le comportement de relance après snooze.
|
|
1984
2080
|
|
|
2081
|
+
### API locale pour le frontend hôte
|
|
2082
|
+
|
|
2083
|
+
Quand votre frontend SaaS a besoin d'un état de session, il doit appeler le package au lieu de lire les clés du storage directement.
|
|
2084
|
+
|
|
2085
|
+
```ts
|
|
2086
|
+
import { getSsoSessionSnapshot } from '@ollaid/native-sso';
|
|
2087
|
+
|
|
2088
|
+
const session = getSsoSessionSnapshot();
|
|
2089
|
+
// {
|
|
2090
|
+
// authToken,
|
|
2091
|
+
// refreshToken,
|
|
2092
|
+
// appAccessTokenRef,
|
|
2093
|
+
// aliasReference,
|
|
2094
|
+
// accountType,
|
|
2095
|
+
// deviceId,
|
|
2096
|
+
// sessionUuid,
|
|
2097
|
+
// user
|
|
2098
|
+
// }
|
|
2099
|
+
```
|
|
2100
|
+
|
|
2101
|
+
Cette API retourne les valeurs déchiffrées par le package et évite au frontend hôte de dépendre du détail des clés `sso_`.
|
|
2102
|
+
|
|
1985
2103
|
### Accès programmatique
|
|
1986
2104
|
|
|
1987
2105
|
```ts
|
|
@@ -1993,6 +2111,28 @@ const type = getAccountType(); // string | null
|
|
|
1993
2111
|
const aliasRef = localStorage.getItem('alias_reference'); // string | null
|
|
1994
2112
|
```
|
|
1995
2113
|
|
|
2114
|
+
### Accès via l'API locale du package
|
|
2115
|
+
|
|
2116
|
+
Le frontend SaaS doit utiliser l'API locale du package pour récupérer l'état SSO, au lieu de lire le storage directement.
|
|
2117
|
+
|
|
2118
|
+
```ts
|
|
2119
|
+
import { getSsoSessionSnapshot, hasSsoSession } from '@ollaid/native-sso';
|
|
2120
|
+
|
|
2121
|
+
const session = getSsoSessionSnapshot();
|
|
2122
|
+
|
|
2123
|
+
if (hasSsoSession()) {
|
|
2124
|
+
console.log(session.authToken);
|
|
2125
|
+
console.log(session.refreshToken);
|
|
2126
|
+
console.log(session.appAccessTokenRef);
|
|
2127
|
+
console.log(session.aliasReference);
|
|
2128
|
+
console.log(session.deviceId);
|
|
2129
|
+
console.log(session.sessionUuid);
|
|
2130
|
+
console.log(session.user);
|
|
2131
|
+
}
|
|
2132
|
+
```
|
|
2133
|
+
|
|
2134
|
+
Cette API retourne les valeurs déchiffrées et garde le détail des clés `sso_` encapsulé dans le package.
|
|
2135
|
+
|
|
1996
2136
|
---
|
|
1997
2137
|
|
|
1998
2138
|
## Déconnexion synchronisée
|
|
@@ -2007,7 +2147,7 @@ Le package implémente une **double revocation** ultra-fiable : il contacte **en
|
|
|
2007
2147
|
│ logout() │ │
|
|
2008
2148
|
└──────┬──────────┘ │
|
|
2009
2149
|
│ ① POST /native/logout │ ② POST /iam/disconnect
|
|
2010
|
-
│ (Sanctum token) │ (
|
|
2150
|
+
│ (Sanctum token) │ (app_access_token_ref)
|
|
2011
2151
|
▼ ▼
|
|
2012
2152
|
┌─────────────────┐ ┌─────────────────┐
|
|
2013
2153
|
│ SaaS API │──③ fire-and-forget──────▶│ IAM API │
|
|
@@ -2029,9 +2169,9 @@ Le package implémente une **double revocation** ultra-fiable : il contacte **en
|
|
|
2029
2169
|
Quand `useNativeAuth.logout()` est appelé (ou que l'utilisateur clique "Se déconnecter" dans `NativeSSOPage`) :
|
|
2030
2170
|
|
|
2031
2171
|
1. **Appels parallèles** (via `Promise.allSettled`, jamais bloquants) :
|
|
2032
|
-
- `POST /api/native/logout` → SaaS
|
|
2033
|
-
- `POST /api/iam/disconnect` → IAM révoque directement l'`AppAccessToken` via `
|
|
2034
|
-
2. **Nettoyage local garanti** : les
|
|
2172
|
+
- `POST /api/native/logout` → SaaS révoque sa session locale
|
|
2173
|
+
- `POST /api/iam/disconnect` → IAM révoque directement l'`AppAccessToken` via `app_access_token_ref`
|
|
2174
|
+
2. **Nettoyage local garanti** : les clés de session sont supprimées (`auth_token`, `token`, `user`, `account_type`, `alias_reference`, `app_access_token_ref`)
|
|
2035
2175
|
3. **Aucun blocage** : même si les deux appels échouent (offline, timeout), la déconnexion locale est instantanée
|
|
2036
2176
|
|
|
2037
2177
|
> **Fiabilité** : `Promise.allSettled` + `.catch()` sur chaque appel. L'appel IAM a un timeout court (5s) pour ne jamais ralentir l'UX.
|
|
@@ -2042,10 +2182,9 @@ Le package contacte directement l'IAM pour révoquer l'`AppAccessToken` lié à
|
|
|
2042
2182
|
|
|
2043
2183
|
| Paramètre | Type | Description |
|
|
2044
2184
|
|-----------|------|-------------|
|
|
2045
|
-
| `
|
|
2046
|
-
| `app_access_token_ref` | `string` | (recommandé) Référence directe de l'`AppAccessToken` IAM — lookup instantané par PK |
|
|
2185
|
+
| `app_access_token_ref` | `string` | Référence directe de l'`AppAccessToken` IAM — lookup instantané par PK |
|
|
2047
2186
|
|
|
2048
|
-
L'IAM cherche
|
|
2187
|
+
L'IAM cherche par `app_access_token_ref` (lookup par PK, O(1)).
|
|
2049
2188
|
|
|
2050
2189
|
### Déconnexion externe (hors package)
|
|
2051
2190
|
|
|
@@ -2065,8 +2204,8 @@ navigate('/auth/login');
|
|
|
2065
2204
|
|
|
2066
2205
|
`logout()` effectue automatiquement :
|
|
2067
2206
|
1. `POST /api/native/logout` → révoque le Sanctum token
|
|
2068
|
-
2. `POST /api/iam/disconnect` → révoque l'AppAccessToken IAM
|
|
2069
|
-
3. `clearAuthToken()` → nettoie les
|
|
2207
|
+
2. `POST /api/iam/disconnect` → révoque l'AppAccessToken IAM via `app_access_token_ref`
|
|
2208
|
+
3. `clearAuthToken()` → nettoie les clés de session
|
|
2070
2209
|
|
|
2071
2210
|
### Hook `useLogout()` (recommandé pour React)
|
|
2072
2211
|
|
|
@@ -2106,14 +2245,14 @@ const LogoutButton = () => {
|
|
|
2106
2245
|
|
|
2107
2246
|
### Détection automatique des sessions révoquées
|
|
2108
2247
|
|
|
2109
|
-
Le [health check](#usetokenhealthcheck) (toutes les 2 min) détecte automatiquement si un token a été révoqué côté SaaS (par un admin, par la limite de sessions, etc.). Si le serveur répond `401`, le package **révoque aussi l'IAM** (`POST /api/iam/disconnect` avec `
|
|
2248
|
+
Le [health check](#usetokenhealthcheck) (toutes les 2 min) détecte automatiquement si un token a été révoqué côté SaaS (par un admin, par la limite de sessions, etc.). Si le serveur répond `401`, le package **révoque aussi l'IAM** (`POST /api/iam/disconnect` avec `app_access_token_ref`) puis déconnecte proprement l'utilisateur.
|
|
2110
2249
|
|
|
2111
2250
|
> **Important** : seul un `401` explicite déclenche la déconnexion automatique. Les erreurs réseau ou serveur (5xx) ne déclenchent **pas** de déconnexion pour éviter les déconnexions intempestives.
|
|
2112
2251
|
|
|
2113
2252
|
### Prérequis backend
|
|
2114
2253
|
|
|
2115
|
-
1. Votre endpoint `POST /api/native/logout` **doit** notifier l'IAM après avoir
|
|
2116
|
-
2. L'IAM **doit** exposer `POST /api/iam/disconnect` acceptant `{
|
|
2254
|
+
1. Votre endpoint `POST /api/native/logout` **doit** révoquer la session SaaS locale et peut notifier l'IAM de manière best-effort après avoir récupéré `app_access_token_ref` (voir [BACKEND_INTEGRATION.md](./BACKEND_INTEGRATION.md))
|
|
2255
|
+
2. L'IAM **doit** exposer `POST /api/iam/disconnect` acceptant `{ app_access_token_ref }`
|
|
2117
2256
|
|
|
2118
2257
|
---
|
|
2119
2258
|
|
|
@@ -2271,8 +2410,8 @@ Hook qui vérifie périodiquement la validité du token Sanctum via `POST /api/n
|
|
|
2271
2410
|
|
|
2272
2411
|
Quand le SaaS retourne un 401 (token révoqué par un admin, session expirée, etc.) :
|
|
2273
2412
|
|
|
2274
|
-
1. **Appel IAM** — Le package appelle `POST /api/iam/disconnect` avec `
|
|
2275
|
-
2. **Nettoyage localStorage** — Les
|
|
2413
|
+
1. **Appel IAM** — Le package appelle `POST /api/iam/disconnect` avec `app_access_token_ref` (fire-and-forget, 5s timeout) pour révoquer l'`AppAccessToken` correspondant
|
|
2414
|
+
2. **Nettoyage localStorage** — Les clés de session sont supprimées
|
|
2276
2415
|
3. **Réinitialisation de l'état** — L'interface revient à l'écran de connexion
|
|
2277
2416
|
|
|
2278
2417
|
> **Philosophie** : Ne déconnecter que sur un rejet explicite du serveur (401). Jamais sur un problème réseau.
|
|
@@ -2340,13 +2479,57 @@ if (config('services.iam.debug')) {
|
|
|
2340
2479
|
|
|
2341
2480
|
### Bonnes pratiques
|
|
2342
2481
|
|
|
2343
|
-
- ✅ Le token Sanctum est stocké
|
|
2482
|
+
- ✅ Le token Sanctum est stocké via le storage configuré, par défaut `localStorage`
|
|
2344
2483
|
- ✅ Les credentials IAM sont gardés **en mémoire uniquement** (jamais persistés)
|
|
2345
2484
|
- ✅ Le device ID est un identifiant aléatoire (pas de fingerprinting invasif)
|
|
2346
2485
|
- ✅ Le logout est single-session (ne déconnecte pas les autres appareils)
|
|
2347
2486
|
- ✅ Le health check ne déconnecte que sur 401 explicite
|
|
2348
2487
|
- ✅ Les photos sont validées à 2 Mo max côté client
|
|
2349
|
-
- ✅ Les lectures
|
|
2488
|
+
- ✅ Les lectures storage sont protégées par try/catch
|
|
2489
|
+
|
|
2490
|
+
---
|
|
2491
|
+
|
|
2492
|
+
## Migration sécurité Web / Capacitor
|
|
2493
|
+
|
|
2494
|
+
Cette section résume l'impact réel d'une mise à niveau en production.
|
|
2495
|
+
|
|
2496
|
+
### Est-ce qu'un simple `npm install` suffit ?
|
|
2497
|
+
|
|
2498
|
+
- **Oui**, si vous ne changez que des comportements frontend compatibles avec le contrat actuel.
|
|
2499
|
+
- **Non**, si vous voulez appliquer les recommandations de sécurité de l'audit ou changer le stockage de session.
|
|
2500
|
+
|
|
2501
|
+
### Est-ce qu'il faut modifier les SaaS ?
|
|
2502
|
+
|
|
2503
|
+
Oui dans les cas suivants :
|
|
2504
|
+
|
|
2505
|
+
- passage à des cookies HttpOnly côté Web
|
|
2506
|
+
- durcissement du logout et du refresh
|
|
2507
|
+
- ajout de l'anti-rejeu sur les webhooks
|
|
2508
|
+
- durcissement de la gestion des redirections
|
|
2509
|
+
- stratégie différente pour Capacitor / mobile natif
|
|
2510
|
+
|
|
2511
|
+
### Règle simple
|
|
2512
|
+
|
|
2513
|
+
| Cas | Action |
|
|
2514
|
+
|---|---|
|
|
2515
|
+
| Correction UI sans changement de contrat | Installer la nouvelle version du package suffit généralement |
|
|
2516
|
+
| Sécurité Web | Mettre à jour le package **et** le backend SaaS |
|
|
2517
|
+
| Sécurité Capacitor / mobile | Mettre à jour le package **et** l'application mobile, parfois aussi le backend SaaS |
|
|
2518
|
+
| Anti-rejeu webhook / intégrité crypto | Mettre à jour le backend SaaS et l'IAM |
|
|
2519
|
+
|
|
2520
|
+
### Compatibilité Web / Capacitor
|
|
2521
|
+
|
|
2522
|
+
- **Web** : `localStorage` fonctionne techniquement, mais ce n'est pas le modèle le plus sûr.
|
|
2523
|
+
- **Capacitor / WebView** : `localStorage` n'est pas un coffre-fort. Si vous avez besoin d'une sécurité plus forte, utilisez un stockage natif sécurisé ou évitez de conserver des secrets longue durée dans le WebView.
|
|
2524
|
+
- **Conclusion** : le package reste compatible avec les deux environnements, mais la stratégie de persistance de session doit être adaptée côté application consommatrice.
|
|
2525
|
+
|
|
2526
|
+
### Ordre de déploiement recommandé
|
|
2527
|
+
|
|
2528
|
+
1. Déployer les migrations backend nécessaires.
|
|
2529
|
+
2. Mettre à jour le package npm.
|
|
2530
|
+
3. Tester le Web.
|
|
2531
|
+
4. Tester Capacitor iOS et Android.
|
|
2532
|
+
5. Activer la nouvelle stratégie de sécurité en production.
|
|
2350
2533
|
|
|
2351
2534
|
---
|
|
2352
2535
|
|
|
@@ -2376,6 +2559,9 @@ if (config('services.iam.debug')) {
|
|
|
2376
2559
|
- `nativeAuthService` — Service d'authentification
|
|
2377
2560
|
- `mobilePasswordService` — Service mot de passe
|
|
2378
2561
|
- `setNativeAuthConfig` — Configuration manuelle des URLs
|
|
2562
|
+
- `getSsoSessionSnapshot` — Snapshot local déchiffré de la session
|
|
2563
|
+
- `hasSsoSession` — Vérifie si une session SSO locale existe
|
|
2564
|
+
- `setNativeStorage` / `getNativeStorage` — Injection du storage session pour WebView / Capacitor / secure storage natif
|
|
2379
2565
|
- `iamAccountService` — Service APIs IAM Account (link-phone, link-email, refresh-user-info, update-avatar, reset-avatar)
|
|
2380
2566
|
- `logout` — Déconnexion complète (double révocation SaaS + IAM + nettoyage localStorage)
|
|
2381
2567
|
- `getAuthToken` — Récupérer le token depuis localStorage
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* DebugPanel — Panneau de debug flottant pour @ollaid/native-sso
|
|
3
3
|
* Affiche l'historique des appels API en temps réel (style terminal)
|
|
4
4
|
* N'apparaît que quand debug=true
|
|
5
|
-
* @version 2.
|
|
5
|
+
* @version 2.6.0
|
|
6
6
|
*/
|
|
7
7
|
export type DebugOnboardingPreset = 'current' | 'photo' | 'phone' | 'email' | 'all';
|
|
8
8
|
interface DebugPanelProps {
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* NativeSSOPage — Page autonome complète pour @ollaid/native-sso
|
|
3
3
|
* Design aligné sur le parcours Native SSO (fond primary, card blanche, ShieldCheck branding)
|
|
4
4
|
*
|
|
5
|
-
* @version 2.
|
|
5
|
+
* @version 2.6.0
|
|
6
6
|
*/
|
|
7
7
|
import type { UserInfos } from '../types/native';
|
|
8
|
+
import type { NativeStorageAdapter } from '../services/api';
|
|
8
9
|
export interface NativeSSOPageProps {
|
|
9
10
|
saasApiUrl: string;
|
|
10
11
|
iamApiUrl: string;
|
|
@@ -29,6 +30,7 @@ export interface NativeSSOPageProps {
|
|
|
29
30
|
hideFooter?: boolean;
|
|
30
31
|
redirectAfterLogin?: string;
|
|
31
32
|
redirectAfterLogout?: string;
|
|
33
|
+
storage?: NativeStorageAdapter;
|
|
32
34
|
}
|
|
33
|
-
export declare function NativeSSOPage({ saasApiUrl, iamApiUrl, onLoginSuccess, onLogout, onOnboardingComplete, accountType, configPrefix, title, description, logoUrl, hideFooter, redirectAfterLogin, redirectAfterLogout, }: NativeSSOPageProps): import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
export declare function NativeSSOPage({ saasApiUrl, iamApiUrl, onLoginSuccess, onLogout, onOnboardingComplete, accountType, configPrefix, title, description, logoUrl, hideFooter, redirectAfterLogin, redirectAfterLogout, storage, }: NativeSSOPageProps): import("react/jsx-runtime").JSX.Element;
|
|
34
36
|
export default NativeSSOPage;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Signup Modal for @ollaid/native-sso — Design aligned with web SSO
|
|
3
3
|
* Full signup flow: intro → account-type → info → OTP → password → confirm → success
|
|
4
4
|
*
|
|
5
|
-
* @version 2.
|
|
5
|
+
* @version 2.6.0
|
|
6
6
|
*/
|
|
7
7
|
import type { UserInfos } from '../types/native';
|
|
8
8
|
export interface SignupModalProps {
|
package/dist/components/ui.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Lightweight replacements for shadcn/ui components + inline SVG icons
|
|
4
4
|
* No external dependencies required
|
|
5
5
|
*
|
|
6
|
-
* @version 2.
|
|
6
|
+
* @version 2.6.0
|
|
7
7
|
*/
|
|
8
8
|
import React from 'react';
|
|
9
9
|
export declare function IconShieldCheck(props: React.SVGProps<SVGSVGElement>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Hook d'inscription Mobile SSO v1.0
|
|
3
3
|
* Gère le flow: init → verify-otp → complete
|
|
4
4
|
*
|
|
5
|
-
* @version 2.
|
|
5
|
+
* @version 2.6.0
|
|
6
6
|
*/
|
|
7
7
|
import type { MobileRegistrationFormData, AccountType } from '../types/mobile';
|
|
8
8
|
interface RegistrationConflict {
|
|
@@ -41,7 +41,7 @@ export declare function useMobileRegistration(options?: UseMobileRegistrationOpt
|
|
|
41
41
|
error_type?: undefined;
|
|
42
42
|
} | {
|
|
43
43
|
success: boolean;
|
|
44
|
-
error_type:
|
|
44
|
+
error_type: string | undefined;
|
|
45
45
|
otp_code_dev?: undefined;
|
|
46
46
|
otp_method?: undefined;
|
|
47
47
|
otp_sent_to?: undefined;
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* Hook d'authentification Native SSO v1.0
|
|
3
3
|
* Architecture Frontend-First avec appels directs à l'IAM
|
|
4
4
|
*
|
|
5
|
-
* @version 2.
|
|
5
|
+
* @version 2.6.0
|
|
6
6
|
*/
|
|
7
|
+
import { type NativeStorageAdapter } from '../services/api';
|
|
7
8
|
import type { NativeAuthStatus, NativeExchangeResponse, AccountType } from '../types/native';
|
|
8
9
|
export interface UseNativeAuthOptions {
|
|
9
10
|
/** URL du Backend SaaS */
|
|
@@ -19,6 +20,8 @@ export interface UseNativeAuthOptions {
|
|
|
19
20
|
* Permet le multi-tenant dynamique : 'iam', 'iam_vendor', 'iam_client', etc.
|
|
20
21
|
*/
|
|
21
22
|
configPrefix?: string;
|
|
23
|
+
/** Stockage injecté pour les apps natives / Capacitor */
|
|
24
|
+
storage?: NativeStorageAdapter;
|
|
22
25
|
}
|
|
23
26
|
export declare function useNativeAuth(options: UseNativeAuthOptions): {
|
|
24
27
|
credentialsLoaded: boolean;
|
|
@@ -126,7 +129,7 @@ export declare function useNativeAuth(options: UseNativeAuthOptions): {
|
|
|
126
129
|
success: boolean;
|
|
127
130
|
user: {
|
|
128
131
|
iam_reference: string;
|
|
129
|
-
alias_reference:
|
|
132
|
+
alias_reference: string;
|
|
130
133
|
id?: number;
|
|
131
134
|
reference: string;
|
|
132
135
|
name: string;
|
|
@@ -181,7 +184,7 @@ export declare function useNativeAuth(options: UseNativeAuthOptions): {
|
|
|
181
184
|
success: boolean;
|
|
182
185
|
user: {
|
|
183
186
|
iam_reference: string;
|
|
184
|
-
alias_reference:
|
|
187
|
+
alias_reference: string;
|
|
185
188
|
id?: number;
|
|
186
189
|
reference: string;
|
|
187
190
|
name: string;
|
|
@@ -223,7 +226,7 @@ export declare function useNativeAuth(options: UseNativeAuthOptions): {
|
|
|
223
226
|
success: boolean;
|
|
224
227
|
user: {
|
|
225
228
|
iam_reference: string;
|
|
226
|
-
alias_reference:
|
|
229
|
+
alias_reference: string;
|
|
227
230
|
id?: number;
|
|
228
231
|
reference: string;
|
|
229
232
|
name: string;
|
|
@@ -255,7 +258,7 @@ export declare function useNativeAuth(options: UseNativeAuthOptions): {
|
|
|
255
258
|
success: boolean;
|
|
256
259
|
user: {
|
|
257
260
|
iam_reference: string;
|
|
258
|
-
alias_reference:
|
|
261
|
+
alias_reference: string;
|
|
259
262
|
id?: number;
|
|
260
263
|
reference: string;
|
|
261
264
|
name: string;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - Si 401 → révoque l'IAM (POST /iam/disconnect) + nettoie le frontend
|
|
11
11
|
* - Ne déconnecte PAS si offline ou serveur inaccessible
|
|
12
12
|
*
|
|
13
|
-
* @version 2.
|
|
13
|
+
* @version 2.6.0
|
|
14
14
|
*/
|
|
15
15
|
import type { UserInfos } from '../types/native';
|
|
16
16
|
export interface UseTokenHealthCheckOptions {
|