@ollaid/native-sso 2.8.2 → 2.8.4
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/dist/index.cjs +15 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +15 -12
- package/dist/index.js.map +1 -1
- package/dist/services/api.d.ts +2 -0
- package/dist/types/native.d.ts +1 -0
- package/docs/10_login-redirect.md +103 -0
- package/docs/11_session-refresh-resilience.md +130 -0
- package/docs/12_login_mode.md +55 -0
- package/docs/13_must_have_working.md +60 -0
- package/docs/14_backend_env_key.md +51 -0
- package/docs/1_quick-start.md +87 -0
- package/docs/2_backend-contract.md +200 -0
- package/docs/3_storage-security.md +54 -0
- package/docs/4_webhooks.md +48 -0
- package/docs/5_iam-account.md +190 -0
- package/docs/6_advanced-services.md +115 -0
- package/docs/7_migration-notes.md +16 -0
- package/docs/8_update_infos.md +139 -0
- package/docs/9_password_magic_link.md +84 -0
- package/docs/README.md +66 -0
- package/package.json +6 -3
- package/scripts/copy-docs.mjs +36 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Backend Contract
|
|
2
|
+
|
|
3
|
+
Version: `2.8.4`
|
|
4
|
+
|
|
5
|
+
## Endpoints SaaS requis
|
|
6
|
+
|
|
7
|
+
- `GET /api/native/config`
|
|
8
|
+
- `POST /api/native/exchange`
|
|
9
|
+
- `POST /api/native/check-token`
|
|
10
|
+
- `POST /api/native/refresh`
|
|
11
|
+
- `POST /api/native/logout`
|
|
12
|
+
- `POST /api/native/password-link` pour le flux de redirection mot de passe
|
|
13
|
+
|
|
14
|
+
## Exemple rapide
|
|
15
|
+
|
|
16
|
+
### 1) `GET /api/native/config`
|
|
17
|
+
|
|
18
|
+
Réponse:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"success": true,
|
|
23
|
+
"app_key": "oiam_ak_xxx",
|
|
24
|
+
"encrypted_credentials": "base64(IV::ciphertext_base64)...",
|
|
25
|
+
"iam_api_url": "https://identityam.ollaid.com/api",
|
|
26
|
+
"credentials_ttl": 300,
|
|
27
|
+
"debug": false,
|
|
28
|
+
"bypass": false
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Format attendu pour `encrypted_credentials`:
|
|
33
|
+
|
|
34
|
+
- chiffrement `AES-256-CBC`
|
|
35
|
+
- IV aléatoire de 16 octets
|
|
36
|
+
- clé dérivée avec `hash('sha256', secret_key, true)`
|
|
37
|
+
- sérialisation finale: `base64(IV::ciphertext_base64)`
|
|
38
|
+
- contenu chiffré: un JSON avec au minimum `app_key` et `secret_key`
|
|
39
|
+
|
|
40
|
+
### 2) `POST /api/native/exchange`
|
|
41
|
+
|
|
42
|
+
Body:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"callback_token": "cbk_xxx"
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Réponse:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"success": true,
|
|
55
|
+
"token": "1|sanctum_token",
|
|
56
|
+
"expires_at": "2026-05-15T17:00:00+00:00",
|
|
57
|
+
"refresh_token": "ref_xxx",
|
|
58
|
+
"refresh_expires_at": "2026-06-15T17:00:00+00:00",
|
|
59
|
+
"app_access_token_ref": "aat_ref_xxx",
|
|
60
|
+
"user": {
|
|
61
|
+
"reference": "USR-XXXX",
|
|
62
|
+
"name": "John Doe",
|
|
63
|
+
"email": "john@example.com",
|
|
64
|
+
"alias_reference": "ALI-XXXX"
|
|
65
|
+
},
|
|
66
|
+
"user_infos": {
|
|
67
|
+
"name": "John Doe",
|
|
68
|
+
"email": "john@example.com",
|
|
69
|
+
"ccphone": "+221",
|
|
70
|
+
"phone": "771234567",
|
|
71
|
+
"address": "Rue 10, Plateau",
|
|
72
|
+
"town": "Dakar",
|
|
73
|
+
"country": "SN"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2 bis) Flux `needs_access` sur une nouvelle application
|
|
79
|
+
|
|
80
|
+
Quand l'utilisateur est bien authentifié côté IAM mais qu'il n'a encore aucun accès sur l'application SaaS ciblée, le backend doit renvoyer un état `needs_access`.
|
|
81
|
+
|
|
82
|
+
Réponse attendue:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"success": true,
|
|
87
|
+
"needs_access": true,
|
|
88
|
+
"process_token": "pst_xxx",
|
|
89
|
+
"application": {
|
|
90
|
+
"id": 12,
|
|
91
|
+
"name": "Mon SaaS",
|
|
92
|
+
"logo": "https://..."
|
|
93
|
+
},
|
|
94
|
+
"user": {
|
|
95
|
+
"id": 42,
|
|
96
|
+
"name": "John Doe",
|
|
97
|
+
"email": "john@example.com"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Comportement du package:
|
|
103
|
+
|
|
104
|
+
- il affiche l'écran de confirmation "Confirmer la création de mon compte"
|
|
105
|
+
- il garde le `process_token` pour finaliser l'attribution d'accès
|
|
106
|
+
- il ne termine pas la connexion tant que l'utilisateur n'a pas confirmé
|
|
107
|
+
|
|
108
|
+
Cas de configuration backend:
|
|
109
|
+
|
|
110
|
+
- `BYPASS=true` sur le SaaS -> le backend auto-crée l'accès et finalise la connexion comme si le modal avait été validé
|
|
111
|
+
- `BYPASS` absent, `false` ou vide -> le backend renvoie `needs_access` dès que l'accès n'existe pas encore
|
|
112
|
+
|
|
113
|
+
Le flux natif ne dépend plus du mode legacy d'autorisation pour le comportement standard. Le contrat natif doit être centré sur `needs_access` par défaut.
|
|
114
|
+
|
|
115
|
+
### 3) `POST /api/native/check-token`
|
|
116
|
+
|
|
117
|
+
Réponse `200` si le token est valide:
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"success": true,
|
|
122
|
+
"user": {
|
|
123
|
+
"name": "John Doe",
|
|
124
|
+
"email": "john@example.com"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 4) `POST /api/native/refresh`
|
|
130
|
+
|
|
131
|
+
Le package tente ce refresh si `refresh_token` existe et que `check-token` renvoie `401`.
|
|
132
|
+
|
|
133
|
+
### 5) `POST /api/native/logout`
|
|
134
|
+
|
|
135
|
+
Réponse:
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{ "success": true }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 6) `POST /api/native/password-link`
|
|
142
|
+
|
|
143
|
+
Réponse recommandée:
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"success": true,
|
|
148
|
+
"redirect_url": "https://identityam.ollaid.com/auth/auto-connect?magic_token=xxx",
|
|
149
|
+
"magic_token": "xxx",
|
|
150
|
+
"expires_at": "2026-05-18T12:00:00+00:00"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Le backend SaaS doit relayer l'appel vers IAM sur `POST /api/backoffice/auth/password-link`, puis renvoyer au package une URL de redirection prête à ouvrir.
|
|
155
|
+
|
|
156
|
+
## Ce que le package envoie
|
|
157
|
+
|
|
158
|
+
- `X-Device-Id`
|
|
159
|
+
- `X-Session-UUID`
|
|
160
|
+
- `X-Device-Name`
|
|
161
|
+
- `X-Device-Model`
|
|
162
|
+
- `X-Device-Manufacturer`
|
|
163
|
+
- `X-Device-Operating-System`
|
|
164
|
+
- `X-Device-Os-Version`
|
|
165
|
+
- `X-Device-Platform`
|
|
166
|
+
- `X-Device-Browser`
|
|
167
|
+
- `X-Device-Language`
|
|
168
|
+
- `X-Device-WebView-Version`
|
|
169
|
+
- `X-Device-Is-Native`
|
|
170
|
+
- `X-Device-Label`
|
|
171
|
+
|
|
172
|
+
## Ce que le backend doit faire
|
|
173
|
+
|
|
174
|
+
- Répondre en JSON.
|
|
175
|
+
- Gérer `refresh_token` si disponible.
|
|
176
|
+
- Retourner `refresh_token` / `refresh_expires_at` si vous activez le refresh.
|
|
177
|
+
- Faire du `check-token` un signal de validité, avec tentative de refresh côté package après un `401`.
|
|
178
|
+
- Révoquer de façon ciblée via `app_access_token_ref`.
|
|
179
|
+
- Mettre à jour `last_active_at` si vous appliquez la politique d’activité.
|
|
180
|
+
- Exposer les sessions sous forme multi-device sans tuer les autres appareils.
|
|
181
|
+
- Renvoyer aussi les champs de profil utiles au package dans `user_infos` quand ils sont connus, notamment `name`, `email`, `ccphone`, `phone`, `address`, `town` et `country`.
|
|
182
|
+
|
|
183
|
+
## Dépannage
|
|
184
|
+
|
|
185
|
+
- `Identifiants application invalides` au moment du login natif signifie en pratique que `POST /api/iam/native/encrypt` n'a pas réussi à valider le couple `app_key` + `encrypted_credentials`.
|
|
186
|
+
- `Déchiffrement échoué` côté IAM veut dire que `encrypted_credentials` ne correspond pas à la `secret_key` attendue par l'application, ou que la valeur envoyée est mal formée.
|
|
187
|
+
- `Credentials expirés` veut dire que le blob de credentials reçu par le package est trop ancien par rapport au TTL configuré. Dans ce cas, le package doit refaire `GET /api/native/config`.
|
|
188
|
+
- Si l'utilisateur est authentifié mais n'a pas encore accès à l'application, le bon signal est `needs_access`. Le package doit afficher la demande de confirmation d'accès, pas un simple échec de login.
|
|
189
|
+
- Si ce flux n'apparaît plus, vérifiez que `BYPASS` n'est pas activé par erreur côté SaaS et que les endpoints IAM retournent bien `needs_access` après l'authentification.
|
|
190
|
+
- Si vous avez copié des clés depuis une application déjà en production et que le login échoue quand même, vérifiez d'abord que `GET /api/native/config` renvoie bien les clés attendues pour cette application.
|
|
191
|
+
- Vérifiez aussi que le SaaS ne sert pas un `encrypted_credentials` mis en cache avec une ancienne `secret_key`.
|
|
192
|
+
- Vérifiez enfin que le format chiffré reste `base64(IV::ciphertext_base64)` comme attendu par le package.
|
|
193
|
+
|
|
194
|
+
## APIs IAM Account
|
|
195
|
+
|
|
196
|
+
Si votre intégration utilise aussi les synchronisations utilisateur server-to-server, consultez [IAM Account](./5_iam-account.md).
|
|
197
|
+
|
|
198
|
+
## Session refresh et résilience
|
|
199
|
+
|
|
200
|
+
Le contrat de `refresh_token`, la rotation, la persistance des sessions et la gestion des erreurs réseau sont détaillés dans [Session Refresh & Resilience](./11_session-refresh-resilience.md).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Storage & Security
|
|
2
|
+
|
|
3
|
+
Version: `2.8.4`
|
|
4
|
+
|
|
5
|
+
## Ce que fait le package
|
|
6
|
+
|
|
7
|
+
- Les données de session sont stockées avec des clés préfixées `sso_`.
|
|
8
|
+
- Le contenu persistant est chiffré au repos par défaut.
|
|
9
|
+
- Le frontend hôte lit la session via `getSsoSessionSnapshot()`.
|
|
10
|
+
- Le package gère aussi des clés internes de rappel profil `sso_image_*` pour l'onboarding et le snooze.
|
|
11
|
+
|
|
12
|
+
### Exemple de lecture
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { getSsoSessionSnapshot } from '@ollaid/native-sso';
|
|
16
|
+
|
|
17
|
+
const session = getSsoSessionSnapshot();
|
|
18
|
+
|
|
19
|
+
console.log(session.authToken);
|
|
20
|
+
console.log(session.user);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Ce que le SaaS doit retenir
|
|
24
|
+
|
|
25
|
+
- Le SaaS ne lit pas le storage directement.
|
|
26
|
+
- Le SaaS demande la session au package quand il en a besoin.
|
|
27
|
+
- Les helpers `getAuthToken()`, `getAuthUser()` et `getAccountType()` restent compatibles, mais l’API recommandée est `getSsoSessionSnapshot()`.
|
|
28
|
+
- Si le backend fournit `refresh_token` / `refresh_expires_at`, le package les persiste et peut tenter un refresh avant déconnexion.
|
|
29
|
+
|
|
30
|
+
### Quand utiliser quoi
|
|
31
|
+
|
|
32
|
+
- `getSsoSessionSnapshot()` : lecture standard côté frontend SaaS.
|
|
33
|
+
- `getAuthToken()` : compatibilité rapide.
|
|
34
|
+
- `getAuthUser()` : compatibilité rapide.
|
|
35
|
+
- `getAccountType()` : compatibilité rapide.
|
|
36
|
+
|
|
37
|
+
## Recommandation
|
|
38
|
+
|
|
39
|
+
- **Web**: storage chiffré du package ou session serveur selon votre architecture.
|
|
40
|
+
- **Capacitor**: fournissez un storage natif sécurisé si vous pouvez.
|
|
41
|
+
- **Logout**: utilisez toujours `logout()`.
|
|
42
|
+
|
|
43
|
+
## Refresh token et persistance
|
|
44
|
+
|
|
45
|
+
- Si le backend fournit `refresh_token` / `refresh_expires_at`, le package les persiste et peut tenter un refresh avant déconnexion.
|
|
46
|
+
- Le backend SaaS doit conserver un `refresh_token_hash` côté base pour que la rotation fonctionne.
|
|
47
|
+
- Une erreur réseau sur `refresh()` ne doit pas vider la session. Voir [Session Refresh & Resilience](./11_session-refresh-resilience.md).
|
|
48
|
+
|
|
49
|
+
## Anti-patterns
|
|
50
|
+
|
|
51
|
+
- Ne pas lire `localStorage` directement depuis le frontend hôte.
|
|
52
|
+
- Ne pas utiliser `clearAuthToken()` comme flux principal.
|
|
53
|
+
- Ne pas effacer le storage manuellement pour simuler une déconnexion.
|
|
54
|
+
- Ne pas compter sur le chiffrement local comme protection absolue contre du JavaScript compromis.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Webhooks
|
|
2
|
+
|
|
3
|
+
Version: `2.8.4`
|
|
4
|
+
|
|
5
|
+
## But
|
|
6
|
+
|
|
7
|
+
Le backend IAM envoie des webhooks pour prévenir le SaaS d’une révocation, d’une suspension ou d’une mise à jour utilisateur.
|
|
8
|
+
|
|
9
|
+
## Points clés
|
|
10
|
+
|
|
11
|
+
- Vérifiez `X-IAM-Signature`.
|
|
12
|
+
- Dédupliquez `X-IAM-Webhook-Id`.
|
|
13
|
+
- Révoquez uniquement la session ciblée.
|
|
14
|
+
|
|
15
|
+
## Exemple de payload
|
|
16
|
+
|
|
17
|
+
Headers:
|
|
18
|
+
|
|
19
|
+
```http
|
|
20
|
+
X-IAM-Signature: sha256=...
|
|
21
|
+
X-IAM-Webhook-Id: wh_123
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Body:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"type": "session",
|
|
29
|
+
"event": "revoked",
|
|
30
|
+
"timestamp": "2026-05-15T17:00:00Z",
|
|
31
|
+
"data": {
|
|
32
|
+
"iam_reference": "USR-XXXX",
|
|
33
|
+
"app_access_token_ref": "aat_xxx"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Événements utiles
|
|
39
|
+
|
|
40
|
+
- `session.revoked`
|
|
41
|
+
- `access.revoked`
|
|
42
|
+
- `user.suspended`
|
|
43
|
+
- `user.updated`
|
|
44
|
+
|
|
45
|
+
## Règle pratique
|
|
46
|
+
|
|
47
|
+
- Ne faites pas de révocation globale par défaut.
|
|
48
|
+
- Utilisez `app_access_token_ref` pour cibler la session.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# IAM Account
|
|
2
|
+
|
|
3
|
+
Version: `2.8.4`
|
|
4
|
+
|
|
5
|
+
Les APIs IAM Account servent à synchroniser des données utilisateur entre un backend SaaS et le backend IAM.
|
|
6
|
+
|
|
7
|
+
## Règle
|
|
8
|
+
|
|
9
|
+
- Ces APIs sont **server-to-server uniquement**.
|
|
10
|
+
- N’appelez jamais ces méthodes depuis le frontend navigateur.
|
|
11
|
+
- Utilisez toujours `app_key` + `secret_key` côté backend.
|
|
12
|
+
|
|
13
|
+
## API exposée
|
|
14
|
+
|
|
15
|
+
Le package exporte `iamAccountService` avec les méthodes suivantes:
|
|
16
|
+
|
|
17
|
+
- `linkPhone()`
|
|
18
|
+
- `linkEmail()`
|
|
19
|
+
- `refreshUserInfo()`
|
|
20
|
+
- `refreshUserInfoBulk()`
|
|
21
|
+
- `updateAvatar()`
|
|
22
|
+
- `resetAvatar()`
|
|
23
|
+
|
|
24
|
+
## Références backend
|
|
25
|
+
|
|
26
|
+
- `POST /api/iam/link-phone`
|
|
27
|
+
- `POST /api/iam/link-email`
|
|
28
|
+
- `POST /api/iam/refresh-user-info`
|
|
29
|
+
- `POST /api/iam/update-avatar`
|
|
30
|
+
- `POST /api/iam/reset-avatar`
|
|
31
|
+
|
|
32
|
+
## `linkEmail()`
|
|
33
|
+
|
|
34
|
+
Liaison d’un email à un utilisateur IAM existant.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { iamAccountService } from '@ollaid/native-sso';
|
|
38
|
+
|
|
39
|
+
const result = await iamAccountService.linkEmail({
|
|
40
|
+
app_key: 'oiam_ak_xxx',
|
|
41
|
+
secret_key: 'sk_xxx',
|
|
42
|
+
iam_reference: 'USR-XXXX',
|
|
43
|
+
email: 'john@example.com',
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Réponse:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"success": true,
|
|
52
|
+
"message": "Adresse email liée avec succès",
|
|
53
|
+
"user_reference": "USR-XXXX",
|
|
54
|
+
"user_infos": {
|
|
55
|
+
"name": "John Doe",
|
|
56
|
+
"email": "john@example.com",
|
|
57
|
+
"ccphone": "+221",
|
|
58
|
+
"phone": "771234567",
|
|
59
|
+
"address": "",
|
|
60
|
+
"town": "",
|
|
61
|
+
"country": "",
|
|
62
|
+
"image_url": "https://...",
|
|
63
|
+
"auth_2fa": false
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## `linkPhone()`
|
|
69
|
+
|
|
70
|
+
Liaison d’un numéro de téléphone à un utilisateur IAM existant.
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
await iamAccountService.linkPhone({
|
|
74
|
+
app_key: 'oiam_ak_xxx',
|
|
75
|
+
secret_key: 'sk_xxx',
|
|
76
|
+
iam_reference: 'USR-XXXX',
|
|
77
|
+
ccphone: '+221',
|
|
78
|
+
phone: '771234567',
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## `refreshUserInfo()`
|
|
83
|
+
|
|
84
|
+
Récupère `user_infos` pour un alias donné.
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
await iamAccountService.refreshUserInfo({
|
|
88
|
+
secret_key: 'sk_xxx',
|
|
89
|
+
alias_reference: 'ALI-XXXX',
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Réponse single:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"success": true,
|
|
98
|
+
"user_reference": "USR-XXXX",
|
|
99
|
+
"alias_reference": "ALI-XXXX",
|
|
100
|
+
"login_type": "email",
|
|
101
|
+
"user_infos": {
|
|
102
|
+
"name": "John Doe",
|
|
103
|
+
"email": "john@example.com",
|
|
104
|
+
"ccphone": "+221",
|
|
105
|
+
"phone": "771234567",
|
|
106
|
+
"address": "",
|
|
107
|
+
"town": "",
|
|
108
|
+
"country": "",
|
|
109
|
+
"image_url": "https://...",
|
|
110
|
+
"auth_2fa": false
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## `refreshUserInfoBulk()`
|
|
116
|
+
|
|
117
|
+
Mode bulk pour synchroniser plusieurs `alias_reference`.
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
await iamAccountService.refreshUserInfoBulk({
|
|
121
|
+
secret_key: 'sk_xxx',
|
|
122
|
+
alias_references: ['ALI-1', 'ALI-2'],
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Réponse:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"success": true,
|
|
131
|
+
"total_requested": 2,
|
|
132
|
+
"total_found": 1,
|
|
133
|
+
"total_errors": 1,
|
|
134
|
+
"data": [
|
|
135
|
+
{
|
|
136
|
+
"user_reference": "USR-XXXX",
|
|
137
|
+
"alias_reference": "ALI-1",
|
|
138
|
+
"login_type": "email",
|
|
139
|
+
"user_infos": {
|
|
140
|
+
"name": "John Doe",
|
|
141
|
+
"email": "john@example.com",
|
|
142
|
+
"ccphone": "+221",
|
|
143
|
+
"phone": "771234567",
|
|
144
|
+
"address": "",
|
|
145
|
+
"town": "",
|
|
146
|
+
"country": "",
|
|
147
|
+
"image_url": "https://...",
|
|
148
|
+
"auth_2fa": false
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"errors": [
|
|
153
|
+
{
|
|
154
|
+
"alias_reference": "ALI-2",
|
|
155
|
+
"error": "Alias non trouvé"
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## `updateAvatar()`
|
|
162
|
+
|
|
163
|
+
Met à jour l’avatar d’un utilisateur sur un `AppAccess` donné.
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
await iamAccountService.updateAvatar({
|
|
167
|
+
app_key: 'oiam_ak_xxx',
|
|
168
|
+
secret_key: 'sk_xxx',
|
|
169
|
+
alias_reference: 'ALI-XXXX',
|
|
170
|
+
avatar_url: 'https://cdn.example.com/avatar.jpg',
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## `resetAvatar()`
|
|
175
|
+
|
|
176
|
+
Réinitialise l’avatar spécifique à l’application pour revenir sur la cascade standard.
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
await iamAccountService.resetAvatar({
|
|
180
|
+
app_key: 'oiam_ak_xxx',
|
|
181
|
+
secret_key: 'sk_xxx',
|
|
182
|
+
alias_reference: 'ALI-XXXX',
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Sécurité
|
|
187
|
+
|
|
188
|
+
- `secret_key` ne doit jamais être exposée au frontend.
|
|
189
|
+
- Ces appels doivent être exécutés uniquement par le backend SaaS.
|
|
190
|
+
- Ces méthodes ne remplacent pas le flux SSO principal.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Advanced Services
|
|
2
|
+
|
|
3
|
+
Version: `2.8.4`
|
|
4
|
+
|
|
5
|
+
Ces helpers sont utiles pour les parcours IAM avancés, mais ils ne remplacent pas le flux SSO principal.
|
|
6
|
+
|
|
7
|
+
## Règles
|
|
8
|
+
|
|
9
|
+
- Utilisez-les seulement après authentification.
|
|
10
|
+
- Ne les appelez pas depuis du code non authentifié.
|
|
11
|
+
- Ils s’appuient sur les credentials chargés par `nativeAuthService`.
|
|
12
|
+
|
|
13
|
+
## `mobilePasswordService`
|
|
14
|
+
|
|
15
|
+
Flux de récupération de mot de passe mobile.
|
|
16
|
+
|
|
17
|
+
### `initRecovery(email)`
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { mobilePasswordService } from '@ollaid/native-sso';
|
|
21
|
+
|
|
22
|
+
const init = await mobilePasswordService.initRecovery('john@example.com');
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Réponse possible:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"success": true,
|
|
30
|
+
"process_token": "proc_xxx",
|
|
31
|
+
"status": "pending_otp",
|
|
32
|
+
"expires_at": "2026-05-15T18:00:00Z",
|
|
33
|
+
"otp_code_dev": "123456",
|
|
34
|
+
"receive_mode": "email",
|
|
35
|
+
"masked_email": "j***@example.com"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### `selectMethod(processToken, receiveChoice)`
|
|
40
|
+
|
|
41
|
+
Choisit `email` ou `phone`.
|
|
42
|
+
|
|
43
|
+
### `reset(processToken, password)`
|
|
44
|
+
|
|
45
|
+
Termine la réinitialisation du mot de passe.
|
|
46
|
+
|
|
47
|
+
### `resendOtp(processToken)`
|
|
48
|
+
|
|
49
|
+
Renvoie l’OTP et expose parfois un délai de cooldown.
|
|
50
|
+
|
|
51
|
+
## `profileChangeService`
|
|
52
|
+
|
|
53
|
+
Flux OTP pour changer email ou téléphone.
|
|
54
|
+
|
|
55
|
+
### `requestEmailChange(newEmail)`
|
|
56
|
+
|
|
57
|
+
Demande un changement d’email avec OTP.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { profileChangeService } from '@ollaid/native-sso';
|
|
61
|
+
|
|
62
|
+
const request = await profileChangeService.requestEmailChange('new@example.com');
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Réponse possible:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"success": true,
|
|
70
|
+
"message": "Demande envoyée",
|
|
71
|
+
"request_id": 42,
|
|
72
|
+
"method": "phone",
|
|
73
|
+
"otp_dev": "654321"
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### `requestPhoneChange(ccphone, phone)`
|
|
78
|
+
|
|
79
|
+
Demande un changement de téléphone avec OTP.
|
|
80
|
+
|
|
81
|
+
### `verifyOldOTP(requestId, otpCode)` / `verifyNewOTP(requestId, otpCode)`
|
|
82
|
+
|
|
83
|
+
Valide l’ancienne ou la nouvelle valeur selon le workflow.
|
|
84
|
+
|
|
85
|
+
### `resendOTP(requestId)` / `switchMethod(requestId, method)`
|
|
86
|
+
|
|
87
|
+
Permet de renvoyer le code ou de basculer entre email et téléphone.
|
|
88
|
+
|
|
89
|
+
## `profileMediaService`
|
|
90
|
+
|
|
91
|
+
Upload de l’image de profil.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { profileMediaService } from '@ollaid/native-sso';
|
|
95
|
+
|
|
96
|
+
await profileMediaService.uploadProfileImage(fileBlob, 'avatar.jpg');
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Réponse possible:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"message": "Image mise à jour",
|
|
104
|
+
"user_infos": {
|
|
105
|
+
"name": "John Doe",
|
|
106
|
+
"image_url": "https://cdn.example.com/avatar.jpg"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Sécurité
|
|
112
|
+
|
|
113
|
+
- Ces helpers utilisent la session courante et le contexte device.
|
|
114
|
+
- Les changements de profil restent côté IAM.
|
|
115
|
+
- Si vous n’en avez pas besoin, vous pouvez les ignorer complètement.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Migration Notes
|
|
2
|
+
|
|
3
|
+
Version: `2.8.4`
|
|
4
|
+
|
|
5
|
+
## Version 2.8.2
|
|
6
|
+
|
|
7
|
+
- `@capacitor/device` est une peer dependency optionnelle.
|
|
8
|
+
- Le package chiffre les données persistées au repos.
|
|
9
|
+
- Le frontend SaaS récupère la session via `getSsoSessionSnapshot()`.
|
|
10
|
+
- `logout()` est le flux de sortie recommandé.
|
|
11
|
+
|
|
12
|
+
## Côté intégrateurs
|
|
13
|
+
|
|
14
|
+
- Gardez les anciens helpers uniquement pour compatibilité.
|
|
15
|
+
- Ne lisez plus le storage directement dans le frontend hôte.
|
|
16
|
+
- Si vous êtes sur Capacitor, fournissez un storage natif sécurisé si vous en avez un.
|