@aurabase/auth 0.5.4 → 0.6.1

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.js CHANGED
@@ -11,6 +11,9 @@ var AuthAdminService = class extends BaseService {
11
11
  return "/v1/auth/admin";
12
12
  }
13
13
  // -- Users ----------------------------------------------------------------
14
+ /**
15
+ * Liste les utilisateurs du projet, avec recherche (`search`) et pagination (`limit`, `offset`).
16
+ */
14
17
  async listUsers(params) {
15
18
  const query = new URLSearchParams();
16
19
  if (params?.limit !== void 0) query.set("limit", String(params.limit));
@@ -19,34 +22,52 @@ var AuthAdminService = class extends BaseService {
19
22
  const qs = query.toString();
20
23
  return this.request("GET", `${this.prefix}/users${qs ? "?" + qs : ""}`);
21
24
  }
25
+ /** Lit un utilisateur par son identifiant. */
22
26
  async getUser(userId) {
23
27
  return this.request("GET", `${this.prefix}/users/${userId}`);
24
28
  }
29
+ /**
30
+ * Crée un utilisateur sans passer par l'inscription publique (e-mail, mot de passe, métadonnées, rôle).
31
+ */
25
32
  async createUser(data) {
26
33
  return this.request("POST", `${this.prefix}/users`, data);
27
34
  }
35
+ /** Met à jour un utilisateur : seuls les champs fournis changent. */
28
36
  async updateUser(userId, data) {
29
37
  return this.request("PUT", `${this.prefix}/users/${userId}`, data);
30
38
  }
39
+ /** Supprime un utilisateur. */
31
40
  async deleteUser(userId) {
32
41
  return this.request("DELETE", `${this.prefix}/users/${userId}`);
33
42
  }
43
+ /** Bannit un utilisateur : il ne peut plus se connecter. */
34
44
  async banUser(userId) {
35
45
  return this.request("POST", `${this.prefix}/users/${userId}/ban`, {});
36
46
  }
47
+ /** Lève le bannissement d'un utilisateur. */
37
48
  async unbanUser(userId) {
38
49
  return this.request("POST", `${this.prefix}/users/${userId}/unban`, {});
39
50
  }
51
+ /**
52
+ * Génère un lien à usage unique pour un utilisateur (`'magic'`, `'recovery'` ou `'invite'`) et renvoie `{ link, token }`.
53
+ */
40
54
  async generateLink(userId, type) {
41
55
  return this.request("POST", `${this.prefix}/users/${userId}/generate-link`, { type });
42
56
  }
57
+ /**
58
+ * Statistiques des utilisateurs : total, vérifiés, bannis, avec MFA et nouveaux sur 7 jours.
59
+ */
43
60
  async getUserStats() {
44
61
  return this.request("GET", `${this.prefix}/users/stats`);
45
62
  }
63
+ /** Liste les identités liées à un utilisateur (fournisseurs OAuth, e-mail). */
46
64
  async listUserIdentities(userId) {
47
65
  return this.request("GET", `${this.prefix}/users/${userId}/identities`);
48
66
  }
49
67
  // -- Sessions ---------------------------------------------------------------
68
+ /**
69
+ * Liste les sessions actives de tous les utilisateurs, filtrables par `userId`, avec pagination.
70
+ */
50
71
  async listSessions(params) {
51
72
  const query = new URLSearchParams();
52
73
  if (params?.userId !== void 0) query.set("user_id", params.userId);
@@ -55,10 +76,14 @@ var AuthAdminService = class extends BaseService {
55
76
  const qs = query.toString();
56
77
  return this.request("GET", `${this.prefix}/sessions${qs ? "?" + qs : ""}`);
57
78
  }
79
+ /** Révoque une session par son identifiant. */
58
80
  async revokeSession(sessionId) {
59
81
  return this.request("DELETE", `${this.prefix}/sessions/${sessionId}`);
60
82
  }
61
83
  // -- Audit log ------------------------------------------------------------
84
+ /**
85
+ * Lit le journal d'audit (action, adresse IP, agent utilisateur, date), filtrable par `userId`, avec pagination.
86
+ */
62
87
  async getAuditLog(params) {
63
88
  const query = new URLSearchParams();
64
89
  if (params?.userId !== void 0) query.set("user_id", params.userId);
@@ -68,6 +93,9 @@ var AuthAdminService = class extends BaseService {
68
93
  return this.request("GET", `${this.prefix}/audit-log${qs ? "?" + qs : ""}`);
69
94
  }
70
95
  // -- Settings -------------------------------------------------------------
96
+ /**
97
+ * Lit les réglages d'authentification du projet. Les secrets (mot de passe SMTP, clés) ne sont jamais renvoyés.
98
+ */
71
99
  async getSettings() {
72
100
  return this.request("GET", `${this.prefix}/settings`);
73
101
  }
@@ -90,18 +118,23 @@ var AuthAdminService = class extends BaseService {
90
118
  return this.request("PUT", `${this.prefix}/settings`, data);
91
119
  }
92
120
  // -- Email templates ------------------------------------------------------
121
+ /** Liste les modèles d'e-mail d'authentification du projet. */
93
122
  async listEmailTemplates() {
94
123
  return this.request("GET", `${this.prefix}/email-templates`);
95
124
  }
125
+ /** Lit le modèle d'e-mail d'un type donné (par exemple confirmation, récupération). */
96
126
  async getEmailTemplate(type) {
97
127
  return this.request("GET", `${this.prefix}/email-templates/${type}`);
98
128
  }
129
+ /** Remplace le contenu du modèle d'e-mail d'un type donné. */
99
130
  async updateEmailTemplate(type, data) {
100
131
  return this.request("PUT", `${this.prefix}/email-templates/${type}`, data);
101
132
  }
133
+ /** Supprime le modèle personnalisé d'un type d'e-mail. */
102
134
  async deleteEmailTemplate(type) {
103
135
  return this.request("DELETE", `${this.prefix}/email-templates/${type}`);
104
136
  }
137
+ /** Envoie un e-mail de test avec le modèle d'un type à l'adresse `to_email`. */
105
138
  async testEmailTemplate(type, body) {
106
139
  return this.request("POST", `${this.prefix}/email-templates/${type}/test`, body);
107
140
  }
@@ -630,6 +663,10 @@ var AuthService = class extends BaseService {
630
663
  return `aura-${clientScope(this.client.baseUrl)}-oauth-implicit-initiated`;
631
664
  }
632
665
  // -- Auth state change ------------------------------------------------------
666
+ /**
667
+ * Écoute les changements d'état de la session (`SIGNED_IN`, `SIGNED_OUT`, `TOKEN_REFRESHED`, `USER_UPDATED`,
668
+ * `MFA_CHALLENGE`…). Renvoie de quoi se désabonner : `unsubscribe()` ou `data.subscription.unsubscribe()`.
669
+ */
633
670
  onAuthStateChange(callback) {
634
671
  const unsub = () => {
635
672
  this._stateListeners.delete(callback);
@@ -679,8 +716,24 @@ var AuthService = class extends BaseService {
679
716
  }
680
717
  }
681
718
  // -- Sign up / sign in / sign out -------------------------------------------
719
+ /**
720
+ * Crée un compte avec e-mail et mot de passe. Si le projet n'exige pas de confirmation et que le MFA n'est pas actif,
721
+ * la session est enregistrée et `SIGNED_IN` est émis ; sinon la réponse est un défi MFA (voir `isMfaChallenge`).
722
+ */
682
723
  async signUp(req) {
683
- const res = await this.request("POST", `${this.prefix}/register`, req);
724
+ const payload = {
725
+ email: req.email,
726
+ password: req.password
727
+ };
728
+ if (req.captcha_token) payload.captcha_token = req.captcha_token;
729
+ if (req.name) {
730
+ payload.name = req.name;
731
+ } else if (req.options?.data && typeof req.options.data.name === "string") {
732
+ payload.name = req.options.data.name;
733
+ }
734
+ if (req.options?.data) payload.data = req.options.data;
735
+ if (req.options?.emailRedirectTo) payload.email_redirect_to = req.options.emailRedirectTo;
736
+ const res = await this.request("POST", `${this.prefix}/register`, payload);
684
737
  if (res.data && !isMfaChallenge(res.data)) {
685
738
  const tp = res.data;
686
739
  tp.accessToken = tp.access_token;
@@ -713,8 +766,18 @@ var AuthService = class extends BaseService {
713
766
  }
714
767
  return res;
715
768
  }
769
+ /**
770
+ * Connecte un utilisateur par e-mail et mot de passe. Enregistre la session et émet `SIGNED_IN` ;
771
+ * si le MFA est actif, renvoie un défi (`isMfaChallenge`) à compléter par `mfaVerify`.
772
+ */
716
773
  async signInWithPassword(req) {
717
- const res = await this.request("POST", `${this.prefix}/login`, req);
774
+ const payload = {
775
+ email: req.email,
776
+ password: req.password
777
+ };
778
+ if (req.captcha_token) payload.captcha_token = req.captcha_token;
779
+ if (req.mfa) payload.mfa = req.mfa;
780
+ const res = await this.request("POST", `${this.prefix}/login`, payload);
718
781
  if (res.data && !isMfaChallenge(res.data)) {
719
782
  const tp = res.data;
720
783
  tp.accessToken = tp.access_token;
@@ -747,37 +810,32 @@ var AuthService = class extends BaseService {
747
810
  }
748
811
  return res;
749
812
  }
750
- /**
751
- * Démarre un flux OAuth : renvoie toujours `{ url }` (et redirige en plus le navigateur
752
- * si un `window` existe).
753
- *
754
- * ### `options.queryParams` — contrat (N22)
755
- *
756
- * Les clés listées par {@link OAUTH_FORWARDABLE_QUERY_PARAMS} — `prompt`, `login_hint`,
757
- * `display`, `ui_locales`, `max_age`, `acr_values`, `claims_locales`, `access_type`,
758
- * `include_granted_scopes`, `hd` — sont **réellement transmises au provider**, jusque
759
- * dans l'URL d'autorisation.
760
- *
761
- * Toute autre clé est **refusée** : la méthode renvoie
762
- * `error.code === 'invalid_oauth_query_param'` et n'amorce aucune redirection. Rien
763
- * n'est jamais accepté puis jeté en silence. Sont notamment refusés :
764
- * - les paramètres du protocole (`state`, `nonce`, `client_id`, `response_type`,
765
- * `scope`, `code_challenge`…) — ils sont calculés par le serveur ;
766
- * - les paramètres construits par cette méthode (`redirect_uri`, `scopes`) — passez par
767
- * `redirectTo`, `scopes` ou `flowType` ;
768
- * - `project_id` : le projet est porté par l'URL du client, jamais par un paramètre ;
769
- * - les variantes de casse (`Prompt`, `State`) et les clés inconnues.
770
- *
771
- * L'autorité est le **backend** (`OAUTH_FORWARDABLE_PARAMS` de
772
- * `services/aura-auth/src/handlers/oauth.rs`), qui répond `400` sur les mêmes règles :
773
- * l'endpoint de démarrage est public et appelable sans SDK. Ce filtre-ci n'est que son
774
- * miroir, pour échouer avant la redirection ; un test de parité interdit qu'ils divergent.
775
- *
776
- * Les **valeurs**, elles, ne sont validées que par le backend (non vide, sans caractère
777
- * de contrôle, 512 caractères au plus, jamais deux fois la même clé) — un manquement
778
- * donne un `400` au démarrage du flux, pas une erreur de cette méthode.
779
- */
780
- async signInWithOAuth(provider, options) {
813
+ async signInWithOAuth(providerOrOptions, rawOptions) {
814
+ let provider;
815
+ let options;
816
+ if (typeof providerOrOptions === "object" && providerOrOptions !== null) {
817
+ provider = providerOrOptions.provider;
818
+ const nestedOptions = providerOrOptions.options;
819
+ options = {
820
+ ...providerOrOptions,
821
+ ...nestedOptions,
822
+ ...rawOptions
823
+ };
824
+ } else {
825
+ provider = providerOrOptions;
826
+ options = rawOptions;
827
+ }
828
+ if (typeof provider !== "string" || provider.trim() === "") {
829
+ return {
830
+ data: null,
831
+ error: new AuraError(0, {
832
+ error: {
833
+ code: "invalid_provider",
834
+ message: "signInWithOAuth: le fournisseur doit \xEAtre une cha\xEEne non vide, par exemple signInWithOAuth('google', { redirectTo }) ou signInWithOAuth({ provider: 'google', redirectTo })"
835
+ }
836
+ })
837
+ };
838
+ }
781
839
  const params = new URLSearchParams();
782
840
  if (options?.redirectTo) params.set("redirect_uri", options.redirectTo);
783
841
  if (options?.scopes) params.set("scopes", options.scopes);
@@ -839,9 +897,15 @@ var AuthService = class extends BaseService {
839
897
  }
840
898
  return { data: { url }, error: null };
841
899
  }
900
+ /**
901
+ * Envoie un lien de connexion par e-mail (« magic link »). La session s'obtient ensuite par `verifyOtp({ type: 'magiclink' })`.
902
+ */
842
903
  async signInWithMagicLink(req) {
843
904
  return this.request("POST", `${this.prefix}/magic-link`, req);
844
905
  }
906
+ /**
907
+ * Crée une session anonyme (utilisateur sans e-mail), enregistrée et signalée par `SIGNED_IN`.
908
+ */
845
909
  async signInAnonymously() {
846
910
  const res = await this.request("POST", `${this.prefix}/anonymous`);
847
911
  if (res.data) {
@@ -850,6 +914,9 @@ var AuthService = class extends BaseService {
850
914
  }
851
915
  return res;
852
916
  }
917
+ /**
918
+ * Déconnecte : révoque le jeton de rafraîchissement côté serveur s'il existe, vide la session locale et émet `SIGNED_OUT`.
919
+ */
853
920
  async signOut() {
854
921
  const refreshToken = this.client.authStore.refreshToken;
855
922
  if (!refreshToken) {
@@ -870,6 +937,10 @@ var AuthService = class extends BaseService {
870
937
  return res;
871
938
  }
872
939
  // -- Session management -----------------------------------------------------
940
+ /**
941
+ * Rafraîchit la session avec le jeton de rafraîchissement et émet `TOKEN_REFRESHED`.
942
+ * Les rafraîchissements concurrents sont fusionnés en un seul appel.
943
+ */
873
944
  async refreshSession() {
874
945
  const res = await refreshOnce(this.client);
875
946
  if (res.data) {
@@ -904,6 +975,10 @@ var AuthService = class extends BaseService {
904
975
  user
905
976
  });
906
977
  }
978
+ /**
979
+ * Installe une session à partir d'un jeton d'accès et d'un jeton de rafraîchissement existants (par exemple reçus d'un serveur).
980
+ * Un jeton d'accès expiré est rafraîchi ; une session invalide est refusée et l'état précédent est restauré.
981
+ */
907
982
  async setSession(accessToken, refreshToken) {
908
983
  const store = this.client.authStore;
909
984
  const prev = { token: store.token, refreshToken: store.refreshToken, user: store.user };
@@ -990,6 +1065,9 @@ var AuthService = class extends BaseService {
990
1065
  this.client.authStore.removeItem(verifierKey);
991
1066
  }
992
1067
  }
1068
+ /**
1069
+ * Liste les sessions de l'utilisateur connecté (appareil, adresse IP, dates) ; `is_current` repère la session courante.
1070
+ */
993
1071
  async listSessions() {
994
1072
  const store = this.client.authStore;
995
1073
  if (store.token && store.refreshToken && !store.isValid) {
@@ -1003,9 +1081,13 @@ var AuthService = class extends BaseService {
1003
1081
  headers: refreshToken ? { "x-refresh-token": refreshToken } : void 0
1004
1082
  });
1005
1083
  }
1084
+ /** Révoque une session de l'utilisateur connecté par son identifiant. */
1006
1085
  async revokeSession(sessionId) {
1007
1086
  return this.request("DELETE", `${this.prefix}/sessions/${sessionId}`);
1008
1087
  }
1088
+ /**
1089
+ * Déconnecte l'utilisateur partout : révoque toutes ses sessions, vide la session locale et émet `SIGNED_OUT`.
1090
+ */
1009
1091
  async revokeAllSessions() {
1010
1092
  const rt = this.client.authStore.refreshToken;
1011
1093
  if (!rt) {
@@ -1186,6 +1268,9 @@ var AuthService = class extends BaseService {
1186
1268
  error: new AuraError(0, { error: { code: r.code, message: `getClaims: ${r.code}` } })
1187
1269
  };
1188
1270
  }
1271
+ /**
1272
+ * Supprime le compte de l'utilisateur connecté après confirmation par son mot de passe, puis vide la session locale.
1273
+ */
1189
1274
  async deleteUser(password) {
1190
1275
  const res = await this.request("DELETE", `${this.prefix}/user`, { password });
1191
1276
  if (!res.error) {
@@ -1194,6 +1279,9 @@ var AuthService = class extends BaseService {
1194
1279
  }
1195
1280
  return res;
1196
1281
  }
1282
+ /**
1283
+ * Met à jour l'utilisateur connecté (métadonnées, mot de passe…) et émet `USER_UPDATED`. Un changement d'e-mail ne prend effet qu'après confirmation par `verifyOtp({ type: 'email_change' })`.
1284
+ */
1197
1285
  async updateUser(req) {
1198
1286
  const res = await this.request("PUT", `${this.prefix}/user`, req);
1199
1287
  if (res.data) {
@@ -1206,9 +1294,13 @@ var AuthService = class extends BaseService {
1206
1294
  return res;
1207
1295
  }
1208
1296
  // -- Password recovery ------------------------------------------------------
1297
+ /** Envoie un e-mail de réinitialisation du mot de passe. */
1209
1298
  async resetPasswordForEmail(req) {
1210
1299
  return this.request("POST", `${this.prefix}/forgot-password`, req);
1211
1300
  }
1301
+ /**
1302
+ * Change le mot de passe de l'utilisateur connecté. Le serveur révoque toutes ses sessions : le SDK vide la session locale et émet `SIGNED_OUT`.
1303
+ */
1212
1304
  async updatePassword(newPassword, currentPassword) {
1213
1305
  const res = await this.request("PUT", `${this.prefix}/user`, {
1214
1306
  password: newPassword,
@@ -1221,12 +1313,39 @@ var AuthService = class extends BaseService {
1221
1313
  return res;
1222
1314
  }
1223
1315
  // -- MFA --------------------------------------------------------------------
1316
+ /**
1317
+ * Façade unifiée pour les opérations MFA (TOTP).
1318
+ * Permet d'appeler indifféremment `aura.auth.mfa.enroll()` ou `aura.auth.mfaEnroll()`.
1319
+ */
1320
+ get mfa() {
1321
+ return {
1322
+ enroll: () => this.mfaEnroll(),
1323
+ verifySetup: (codeOrParams) => {
1324
+ const code = typeof codeOrParams === "string" ? codeOrParams : codeOrParams.code;
1325
+ return this.mfaVerifySetup(code);
1326
+ },
1327
+ verify: (req) => this.mfaVerify(req),
1328
+ unenroll: (passwordOrParams) => {
1329
+ const password = typeof passwordOrParams === "string" ? passwordOrParams : passwordOrParams.password;
1330
+ return this.mfaUnenroll(password);
1331
+ },
1332
+ regenerateRecoveryCodes: (codeOrParams) => {
1333
+ const code = typeof codeOrParams === "string" ? codeOrParams : codeOrParams.code;
1334
+ return this.regenerateRecoveryCodes(code);
1335
+ }
1336
+ };
1337
+ }
1338
+ /** MFA : démarre l'enrôlement TOTP et renvoie le `secret` et l'URL `otpauth_url` à afficher en QR code. */
1224
1339
  async mfaEnroll() {
1225
1340
  return this.request("POST", `${this.prefix}/mfa/setup`);
1226
1341
  }
1342
+ /** MFA : confirme l'enrôlement avec un premier code et renvoie les codes de récupération. */
1227
1343
  async mfaVerifySetup(code) {
1228
1344
  return this.request("POST", `${this.prefix}/mfa/setup/verify`, { code });
1229
1345
  }
1346
+ /**
1347
+ * MFA : termine une connexion qui a renvoyé un défi (`mfa_token` et code TOTP). Enregistre la session et émet `SIGNED_IN`.
1348
+ */
1230
1349
  async mfaVerify(req) {
1231
1350
  const res = await this.request("POST", `${this.prefix}/mfa/verify-login`, req);
1232
1351
  if (res.data) {
@@ -1235,6 +1354,7 @@ var AuthService = class extends BaseService {
1235
1354
  }
1236
1355
  return res;
1237
1356
  }
1357
+ /** MFA : désactive le MFA après confirmation par le mot de passe. */
1238
1358
  async mfaUnenroll(password) {
1239
1359
  return this.request("POST", `${this.prefix}/mfa/disable`, { password });
1240
1360
  }
@@ -1306,6 +1426,7 @@ var AuthService = class extends BaseService {
1306
1426
  return res;
1307
1427
  }
1308
1428
  // -- Email verification -----------------------------------------------------
1429
+ /** Renvoie l'e-mail de vérification, à `email` ou à l'adresse de l'utilisateur connecté. */
1309
1430
  async resendVerificationEmail(email) {
1310
1431
  const e = email ?? this.client.authStore.user?.email;
1311
1432
  if (!e) {
@@ -1317,24 +1438,34 @@ var AuthService = class extends BaseService {
1317
1438
  return this.request("POST", `${this.prefix}/resend-verification`, { email: e });
1318
1439
  }
1319
1440
  // -- Email OTP (Phase 2) --------------------------------------------------
1441
+ /**
1442
+ * Envoie un code à usage unique par e-mail ; à confirmer par `verifyOtp({ type: 'email' })`.
1443
+ */
1320
1444
  async signInWithEmailOtp(email) {
1321
1445
  return this.request("POST", `${this.prefix}/email-otp/send`, { email });
1322
1446
  }
1323
1447
  // -- SMS OTP (Phase 2) ----------------------------------------------------
1448
+ /** Envoie un code à usage unique par SMS ; à confirmer par `verifyOtp({ type: 'sms' })`. */
1324
1449
  async signInWithSmsOtp(phone) {
1325
1450
  return this.request("POST", `${this.prefix}/sms/send`, { phone });
1326
1451
  }
1327
1452
  // -- Identity linking (Phase 2) -------------------------------------------
1453
+ /** Liste les identités (fournisseurs) liées à l'utilisateur connecté. */
1328
1454
  async listIdentities() {
1329
1455
  return this.request("GET", `${this.prefix}/user/identities`);
1330
1456
  }
1457
+ /**
1458
+ * Démarre la liaison d'un fournisseur OAuth au compte connecté et renvoie l'URL d'autorisation à ouvrir.
1459
+ */
1331
1460
  async linkIdentity(provider) {
1332
1461
  return this.request("POST", `${this.prefix}/user/identities/link/${provider}`);
1333
1462
  }
1463
+ /** Détache une identité du compte connecté par son identifiant. */
1334
1464
  async unlinkIdentity(identityId) {
1335
1465
  return this.request("DELETE", `${this.prefix}/user/identities/${identityId}`);
1336
1466
  }
1337
1467
  // -- MFA recovery codes (Phase 2) -----------------------------------------
1468
+ /** MFA : régénère les codes de récupération après confirmation par un code TOTP. */
1338
1469
  async regenerateRecoveryCodes(code) {
1339
1470
  return this.request("POST", `${this.prefix}/mfa/recovery-codes/regenerate`, { code });
1340
1471
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurabase/auth",
3
- "version": "0.5.4",
3
+ "version": "0.6.1",
4
4
  "description": "Service d'authentification du SDK Aurabase (sessions, OAuth/PKCE, MFA, magic link, OTP, admin)",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -46,7 +46,7 @@
46
46
  "authentication"
47
47
  ],
48
48
  "dependencies": {
49
- "@aurabase/core": "0.5.4"
49
+ "@aurabase/core": "0.6.1"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/node": "20.14.15",