@aurabase/auth 0.7.0 → 0.7.2

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 CHANGED
@@ -39,8 +39,13 @@ await aura.auth.signOut()
39
39
  ### Session
40
40
 
41
41
  ```ts
42
- // getSession() n'est PAS un AuraResponse : il lit directement le store local (synchrone en pratique).
43
- const { accessToken, user } = await aura.auth.getSession()
42
+ // getSession() lit le store local (synchrone en pratique) :
43
+ const { data: { session } } = await aura.auth.getSession()
44
+ if (session) {
45
+ console.log('Session ID:', session.id)
46
+ console.log('Access token:', session.access_token)
47
+ console.log('User ID:', session.user.id)
48
+ }
44
49
 
45
50
  const refreshed = await aura.auth.refreshSession()
46
51
 
@@ -55,6 +60,32 @@ if (first) await aura.auth.revokeSession(first.id)
55
60
  await aura.auth.revokeAllSessions()
56
61
  ```
57
62
 
63
+ ### Configuration du stockage (SSR & Node.js)
64
+
65
+ ```ts
66
+ import { createClient, LocalAuthStore, BaseAuthStore } from '@aurabase/aurabase-js'
67
+
68
+ // Par défaut, le client choisit automatiquement :
69
+ // - Navigateur : `LocalAuthStore` avec clé scopée par projet (`aura-<slug>-auth`)
70
+ // - Node.js / SSR : `BaseAuthStore` en mémoire avec exportToCookie() / loadFromCookie()
71
+
72
+ // Pour personnaliser le stockage :
73
+ const aura = createClient('https://mon-projet.aurabase.cloud', 'aura_anon_xxx', {
74
+ auth: {
75
+ storage: new LocalAuthStore('custom-auth-key'),
76
+ autoRefreshToken: true,
77
+ persistSession: true,
78
+ },
79
+ })
80
+
81
+ // Sérialisation cookie (SSR) :
82
+ const setCookieHeader = aura.authStore.exportToCookie({
83
+ httpOnly: true,
84
+ secure: true,
85
+ sameSite: 'lax',
86
+ })
87
+ ```
88
+
58
89
  ### OAuth (implicite ou PKCE)
59
90
 
60
91
  `signInWithOAuth` ne redirige plus « en dur » : il renvoie toujours `{ url }` (et redirige en plus via `window.location.href` si un `window` existe).
package/dist/index.cjs CHANGED
@@ -52,9 +52,69 @@ var AuthAdminService = class extends core.BaseService {
52
52
  }
53
53
  /**
54
54
  * Génère un lien à usage unique pour un utilisateur (`'magic'`, `'recovery'` ou `'invite'`) et renvoie `{ link, token }`.
55
+ * Accepte `generateLink(userId, type)` ou `generateLink({ userId, type })` ou `generateLink({ email, type })`.
55
56
  */
56
- async generateLink(userId, type) {
57
- return this.request("POST", `${this.prefix}/users/${userId}/generate-link`, { type });
57
+ async generateLink(userIdOrParams, type) {
58
+ let resolvedUserId;
59
+ let resolvedType;
60
+ let resolvedRedirectTo;
61
+ if (typeof userIdOrParams === "object" && userIdOrParams !== null) {
62
+ resolvedUserId = userIdOrParams.userId ?? userIdOrParams.user_id;
63
+ resolvedType = userIdOrParams.type ?? type;
64
+ resolvedRedirectTo = userIdOrParams.redirectTo ?? userIdOrParams.redirect_to;
65
+ if (!resolvedUserId && userIdOrParams.email) {
66
+ const email = userIdOrParams.email.trim().toLowerCase();
67
+ const searchRes = await this.listUsers({ search: email, limit: 1 });
68
+ const usersList = Array.isArray(searchRes.data) ? searchRes.data : [];
69
+ if (usersList[0]?.id) {
70
+ resolvedUserId = usersList[0].id;
71
+ } else {
72
+ return {
73
+ data: null,
74
+ error: new core.AuraError(404, {
75
+ error: {
76
+ code: "USER_NOT_FOUND",
77
+ message: `No user found with email "${email}".`
78
+ }
79
+ })
80
+ };
81
+ }
82
+ }
83
+ } else if (typeof userIdOrParams === "string") {
84
+ resolvedUserId = userIdOrParams;
85
+ resolvedType = type;
86
+ }
87
+ if (!resolvedUserId || typeof resolvedUserId !== "string" || resolvedUserId.trim() === "" || resolvedUserId.includes("[object")) {
88
+ return {
89
+ data: null,
90
+ error: new core.AuraError(400, {
91
+ error: {
92
+ code: "INVALID_ARGUMENT",
93
+ message: "userId or email is required. Usage: generateLink({ email, type }) or generateLink(userId, type)."
94
+ }
95
+ })
96
+ };
97
+ }
98
+ if (!resolvedType) {
99
+ return {
100
+ data: null,
101
+ error: new core.AuraError(400, {
102
+ error: {
103
+ code: "INVALID_ARGUMENT",
104
+ message: 'type is required for generateLink ("magic" | "recovery" | "invite").'
105
+ }
106
+ })
107
+ };
108
+ }
109
+ const body = { type: resolvedType };
110
+ if (resolvedRedirectTo) {
111
+ body.redirect_to = resolvedRedirectTo;
112
+ }
113
+ return this.request(
114
+ "POST",
115
+ `${this.prefix}/users/${encodeURIComponent(resolvedUserId)}/generate-link`,
116
+ body
117
+ );
58
118
  }
59
119
  /**
60
120
  * Impersonation (AUTH-037) : jeton COURT (10 minutes au plus) pour agir en tant que l'utilisateur,
@@ -536,6 +596,15 @@ var SessionManager = class {
536
596
  };
537
597
 
538
598
  // src/AuthService.ts
599
+ function extractSessionId(token) {
600
+ if (!token) return void 0;
601
+ try {
602
+ const payload = decodeJwt(token).payload;
603
+ return payload?.session_id ?? payload?.sid ?? void 0;
604
+ } catch {
605
+ return void 0;
606
+ }
607
+ }
539
608
  function isMfaChallenge(v) {
540
609
  return typeof v === "object" && v !== null && v.mfa_required === true;
541
610
  }
@@ -814,6 +883,7 @@ var AuthService = class extends core.BaseService {
814
883
  queueMicrotask(() => {
815
884
  if (this._stateListeners.has(callback)) {
816
885
  const session = store.token && store.user ? {
886
+ id: extractSessionId(store.token),
817
887
  access_token: store.token,
818
888
  refresh_token: store.refreshToken ?? "",
819
889
  token_type: "Bearer",
@@ -828,6 +898,7 @@ var AuthService = class extends core.BaseService {
828
898
  _emitEvent(event, user, accessToken, extra) {
829
899
  if (event === "SIGNED_OUT") this._signedOutSeq = this._clearSeq;
830
900
  const session = accessToken && user ? {
901
+ id: extractSessionId(accessToken),
831
902
  access_token: accessToken,
832
903
  refresh_token: this.client.authStore.refreshToken ?? "",
833
904
  token_type: "Bearer",
@@ -859,6 +930,7 @@ var AuthService = class extends core.BaseService {
859
930
  }
860
931
  if (req.options?.data) payload.data = req.options.data;
861
932
  if (req.options?.emailRedirectTo) payload.email_redirect_to = req.options.emailRedirectTo;
933
+ if (req.options?.preventEmailEnumeration) payload.prevent_email_enumeration = true;
862
934
  const res = await this.request("POST", `${this.prefix}/register`, payload);
863
935
  if (res.data && !isMfaChallenge(res.data) && !res.data.access_token) {
864
936
  res.data.session = null;
@@ -867,6 +939,7 @@ var AuthService = class extends core.BaseService {
867
939
  if (res.data && !isMfaChallenge(res.data)) {
868
940
  const tp = res.data;
869
941
  tp.session = {
942
+ id: extractSessionId(tp.access_token),
870
943
  access_token: tp.access_token,
871
944
  refresh_token: tp.refresh_token,
872
945
  token_type: tp.token_type,
@@ -902,6 +975,7 @@ var AuthService = class extends core.BaseService {
902
975
  if (res.data && !isMfaChallenge(res.data)) {
903
976
  const tp = res.data;
904
977
  tp.session = {
978
+ id: extractSessionId(tp.access_token),
905
979
  access_token: tp.access_token,
906
980
  refresh_token: tp.refresh_token,
907
981
  token_type: tp.token_type,
@@ -1069,6 +1143,7 @@ var AuthService = class extends core.BaseService {
1069
1143
  const token = this.client.authStore.token;
1070
1144
  const user = this.client.authStore.user;
1071
1145
  const session = token && user ? {
1146
+ id: extractSessionId(token),
1072
1147
  access_token: token,
1073
1148
  refresh_token: this.client.authStore.refreshToken ?? "",
1074
1149
  token_type: "Bearer",
@@ -1460,14 +1535,28 @@ var AuthService = class extends core.BaseService {
1460
1535
  const code = typeof codeOrParams === "string" ? codeOrParams : codeOrParams.code;
1461
1536
  return this.regenerateRecoveryCodes(code);
1462
1537
  },
1463
- factors: (mfaToken) => this.request("POST", `${this.prefix}/mfa/factors`, { mfa_token: mfaToken }),
1538
+ factors: (mfaToken) => this.request("POST", `${this.prefix}/mfa/factors`, {
1539
+ mfa_token: mfaToken
1540
+ }),
1464
1541
  sms: {
1465
1542
  setup: (phone) => this.request("POST", `${this.prefix}/mfa/sms/setup`, { phone }),
1466
- verifySetup: (code) => this.request("POST", `${this.prefix}/mfa/sms/setup/verify`, { code }),
1467
- send: (mfaToken) => this.request("POST", `${this.prefix}/mfa/sms/send`, {
1468
- mfa_token: mfaToken
1469
- }),
1470
- remove: (password) => this.request("DELETE", `${this.prefix}/mfa/sms`, { password })
1543
+ verifySetup: (code) => this.request(
1544
+ "POST",
1545
+ `${this.prefix}/mfa/sms/setup/verify`,
1546
+ { code }
1547
+ ),
1548
+ send: (mfaToken) => this.request(
1549
+ "POST",
1550
+ `${this.prefix}/mfa/sms/send`,
1551
+ {
1552
+ mfa_token: mfaToken
1553
+ }
1554
+ ),
1555
+ remove: (password) => this.request(
1556
+ "DELETE",
1557
+ `${this.prefix}/mfa/sms`,
1558
+ { password }
1559
+ )
1471
1560
  },
1472
1561
  webauthn: {
1473
1562
  register: (params) => this.webauthnRegister(params),
@@ -1481,6 +1570,13 @@ var AuthService = class extends core.BaseService {
1481
1570
  }
1482
1571
  };
1483
1572
  }
1573
+ /**
1574
+ * API d'administration de l'authentification (alias vers `client.authAdmin`).
1575
+ * Exige une clé `service_role` (côté serveur uniquement).
1576
+ */
1577
+ get admin() {
1578
+ return this.client.authAdmin;
1579
+ }
1484
1580
  webauthnIndisponible() {
1485
1581
  return {
1486
1582
  data: null,
@@ -1505,7 +1601,7 @@ var AuthService = class extends core.BaseService {
1505
1601
  `${this.prefix}/mfa/webauthn/register/start`,
1506
1602
  { friendly_name: params?.friendlyName }
1507
1603
  );
1508
- if (!debut.data) return debut;
1604
+ if (!debut.data) return { data: null, error: debut.error };
1509
1605
  let cred;
1510
1606
  try {
1511
1607
  cred = await conteneur.create(creationOptionsFromJson(debut.data.options));
@@ -1513,10 +1609,14 @@ var AuthService = class extends core.BaseService {
1513
1609
  return this.webauthnAnnule(e);
1514
1610
  }
1515
1611
  if (!cred) return this.webauthnAnnule(new Error("no credential returned"));
1516
- return this.request("POST", `${this.prefix}/mfa/webauthn/register/finish`, {
1517
- credential: attestationToJson(cred),
1518
- friendly_name: params?.friendlyName
1519
- });
1612
+ return this.request(
1613
+ "POST",
1614
+ `${this.prefix}/mfa/webauthn/register/finish`,
1615
+ {
1616
+ credential: attestationToJson(cred),
1617
+ friendly_name: params?.friendlyName
1618
+ }
1619
+ );
1520
1620
  }
1521
1621
  /**
1522
1622
  * Relève un défi MFA (`mfaToken`, reçu d'un `signIn`) avec une passkey : options du serveur,
@@ -1530,7 +1630,7 @@ var AuthService = class extends core.BaseService {
1530
1630
  `${this.prefix}/mfa/webauthn/verify/start`,
1531
1631
  { mfa_token: params.mfaToken }
1532
1632
  );
1533
- if (!debut.data) return debut;
1633
+ if (!debut.data) return { data: null, error: debut.error };
1534
1634
  let cred;
1535
1635
  try {
1536
1636
  cred = await conteneur.get(requestOptionsFromJson(debut.data.options));
@@ -1572,10 +1672,31 @@ var AuthService = class extends core.BaseService {
1572
1672
  * MFA : termine une connexion qui a renvoyé un défi (`mfa_token` et code TOTP). Enregistre la session et émet `SIGNED_IN`.
1573
1673
  */
1574
1674
  async mfaVerify(req) {
1575
- const res = await this.request("POST", `${this.prefix}/mfa/verify-login`, req);
1675
+ const raw = req;
1676
+ const mfa_token = raw.mfa_token ?? raw.mfaToken ?? raw.challenge_id ?? raw.challengeId;
1677
+ const code = raw.code;
1678
+ const recovery_code = raw.recovery_code ?? raw.recoveryCode;
1679
+ const sms_code = raw.sms_code ?? raw.smsCode;
1680
+ const body = {};
1681
+ if (mfa_token) body.mfa_token = mfa_token;
1682
+ if (code !== void 0) body.code = code;
1683
+ if (recovery_code !== void 0) body.recovery_code = recovery_code;
1684
+ if (sms_code !== void 0) body.sms_code = sms_code;
1685
+ const res = await this.request("POST", `${this.prefix}/mfa/verify-login`, body);
1576
1686
  if (res.data) {
1577
- this.client.authStore.save(res.data.access_token, res.data.refresh_token, res.data.user);
1578
- this._emitEvent("SIGNED_IN", res.data.user, res.data.access_token);
1687
+ const tp = res.data;
1688
+ tp.session = {
1689
+ id: extractSessionId(tp.access_token),
1690
+ access_token: tp.access_token,
1691
+ refresh_token: tp.refresh_token,
1692
+ token_type: tp.token_type,
1693
+ expires_in: tp.expires_in,
1694
+ user: tp.user,
1695
+ provider_token: tp.provider_token,
1696
+ provider_refresh_token: tp.provider_refresh_token
1697
+ };
1698
+ this.client.authStore.save(tp.access_token, tp.refresh_token, tp.user);
1699
+ this._emitEvent("SIGNED_IN", tp.user, tp.access_token);
1579
1700
  }
1580
1701
  return res;
1581
1702
  }
package/dist/index.d.cts CHANGED
@@ -72,8 +72,16 @@ declare class AuthAdminService extends BaseService {
72
72
  unbanUser(userId: string): Promise<AuraResponse<null>>;
73
73
  /**
74
74
  * Génère un lien à usage unique pour un utilisateur (`'magic'`, `'recovery'` ou `'invite'`) et renvoie `{ link, token }`.
75
+ * Accepte `generateLink(userId, type)` ou `generateLink({ userId, type })` ou `generateLink({ email, type })`.
75
76
  */
76
- generateLink(userId: string, type: GenerateLinkType): Promise<AuraResponse<GenerateLinkResult>>;
77
+ generateLink(userIdOrParams: string | {
78
+ userId?: string;
79
+ user_id?: string;
80
+ email?: string;
81
+ type: GenerateLinkType;
82
+ redirectTo?: string;
83
+ redirect_to?: string;
84
+ }, type?: GenerateLinkType): Promise<AuraResponse<GenerateLinkResult>>;
77
85
  /**
78
86
  * Impersonation (AUTH-037) : jeton COURT (10 minutes au plus) pour agir en tant que l'utilisateur,
79
87
  * avec le claim `act: { sub }`. Pas de refresh token, journalisé (`admin_impersonation`).
@@ -568,6 +576,11 @@ declare class AuthService extends BaseService {
568
576
  }>>;
569
577
  };
570
578
  };
579
+ /**
580
+ * API d'administration de l'authentification (alias vers `client.authAdmin`).
581
+ * Exige une clé `service_role` (côté serveur uniquement).
582
+ */
583
+ get admin(): AuthAdminService;
571
584
  private webauthnIndisponible;
572
585
  /**
573
586
  * Enrôle une passkey WebAuthn pour l'utilisateur connecté (cérémonie complète : options du serveur,
package/dist/index.d.ts CHANGED
@@ -72,8 +72,16 @@ declare class AuthAdminService extends BaseService {
72
72
  unbanUser(userId: string): Promise<AuraResponse<null>>;
73
73
  /**
74
74
  * Génère un lien à usage unique pour un utilisateur (`'magic'`, `'recovery'` ou `'invite'`) et renvoie `{ link, token }`.
75
+ * Accepte `generateLink(userId, type)` ou `generateLink({ userId, type })` ou `generateLink({ email, type })`.
75
76
  */
76
- generateLink(userId: string, type: GenerateLinkType): Promise<AuraResponse<GenerateLinkResult>>;
77
+ generateLink(userIdOrParams: string | {
78
+ userId?: string;
79
+ user_id?: string;
80
+ email?: string;
81
+ type: GenerateLinkType;
82
+ redirectTo?: string;
83
+ redirect_to?: string;
84
+ }, type?: GenerateLinkType): Promise<AuraResponse<GenerateLinkResult>>;
77
85
  /**
78
86
  * Impersonation (AUTH-037) : jeton COURT (10 minutes au plus) pour agir en tant que l'utilisateur,
79
87
  * avec le claim `act: { sub }`. Pas de refresh token, journalisé (`admin_impersonation`).
@@ -568,6 +576,11 @@ declare class AuthService extends BaseService {
568
576
  }>>;
569
577
  };
570
578
  };
579
+ /**
580
+ * API d'administration de l'authentification (alias vers `client.authAdmin`).
581
+ * Exige une clé `service_role` (côté serveur uniquement).
582
+ */
583
+ get admin(): AuthAdminService;
571
584
  private webauthnIndisponible;
572
585
  /**
573
586
  * Enrôle une passkey WebAuthn pour l'utilisateur connecté (cérémonie complète : options du serveur,
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseService, isTokenExpired, clientScope, AuraError, refreshOnce, DEFAULT_REQUEST_TIMEOUT_MS, emitAuraEvent } from '@aurabase/core';
1
+ import { BaseService, AuraError, isTokenExpired, clientScope, refreshOnce, DEFAULT_REQUEST_TIMEOUT_MS, emitAuraEvent } from '@aurabase/core';
2
2
 
3
3
  // src/AuthAdminService.ts
4
4
  var AuthAdminService = class extends BaseService {
@@ -50,9 +50,69 @@ var AuthAdminService = class extends BaseService {
50
50
  }
51
51
  /**
52
52
  * Génère un lien à usage unique pour un utilisateur (`'magic'`, `'recovery'` ou `'invite'`) et renvoie `{ link, token }`.
53
+ * Accepte `generateLink(userId, type)` ou `generateLink({ userId, type })` ou `generateLink({ email, type })`.
53
54
  */
54
- async generateLink(userId, type) {
55
- return this.request("POST", `${this.prefix}/users/${userId}/generate-link`, { type });
55
+ async generateLink(userIdOrParams, type) {
56
+ let resolvedUserId;
57
+ let resolvedType;
58
+ let resolvedRedirectTo;
59
+ if (typeof userIdOrParams === "object" && userIdOrParams !== null) {
60
+ resolvedUserId = userIdOrParams.userId ?? userIdOrParams.user_id;
61
+ resolvedType = userIdOrParams.type ?? type;
62
+ resolvedRedirectTo = userIdOrParams.redirectTo ?? userIdOrParams.redirect_to;
63
+ if (!resolvedUserId && userIdOrParams.email) {
64
+ const email = userIdOrParams.email.trim().toLowerCase();
65
+ const searchRes = await this.listUsers({ search: email, limit: 1 });
66
+ const usersList = Array.isArray(searchRes.data) ? searchRes.data : [];
67
+ if (usersList[0]?.id) {
68
+ resolvedUserId = usersList[0].id;
69
+ } else {
70
+ return {
71
+ data: null,
72
+ error: new AuraError(404, {
73
+ error: {
74
+ code: "USER_NOT_FOUND",
75
+ message: `No user found with email "${email}".`
76
+ }
77
+ })
78
+ };
79
+ }
80
+ }
81
+ } else if (typeof userIdOrParams === "string") {
82
+ resolvedUserId = userIdOrParams;
83
+ resolvedType = type;
84
+ }
85
+ if (!resolvedUserId || typeof resolvedUserId !== "string" || resolvedUserId.trim() === "" || resolvedUserId.includes("[object")) {
86
+ return {
87
+ data: null,
88
+ error: new AuraError(400, {
89
+ error: {
90
+ code: "INVALID_ARGUMENT",
91
+ message: "userId or email is required. Usage: generateLink({ email, type }) or generateLink(userId, type)."
92
+ }
93
+ })
94
+ };
95
+ }
96
+ if (!resolvedType) {
97
+ return {
98
+ data: null,
99
+ error: new AuraError(400, {
100
+ error: {
101
+ code: "INVALID_ARGUMENT",
102
+ message: 'type is required for generateLink ("magic" | "recovery" | "invite").'
103
+ }
104
+ })
105
+ };
106
+ }
107
+ const body = { type: resolvedType };
108
+ if (resolvedRedirectTo) {
109
+ body.redirect_to = resolvedRedirectTo;
110
+ }
111
+ return this.request(
112
+ "POST",
113
+ `${this.prefix}/users/${encodeURIComponent(resolvedUserId)}/generate-link`,
114
+ body
115
+ );
56
116
  }
57
117
  /**
58
118
  * Impersonation (AUTH-037) : jeton COURT (10 minutes au plus) pour agir en tant que l'utilisateur,
@@ -534,6 +594,15 @@ var SessionManager = class {
534
594
  };
535
595
 
536
596
  // src/AuthService.ts
597
+ function extractSessionId(token) {
598
+ if (!token) return void 0;
599
+ try {
600
+ const payload = decodeJwt(token).payload;
601
+ return payload?.session_id ?? payload?.sid ?? void 0;
602
+ } catch {
603
+ return void 0;
604
+ }
605
+ }
537
606
  function isMfaChallenge(v) {
538
607
  return typeof v === "object" && v !== null && v.mfa_required === true;
539
608
  }
@@ -812,6 +881,7 @@ var AuthService = class extends BaseService {
812
881
  queueMicrotask(() => {
813
882
  if (this._stateListeners.has(callback)) {
814
883
  const session = store.token && store.user ? {
884
+ id: extractSessionId(store.token),
815
885
  access_token: store.token,
816
886
  refresh_token: store.refreshToken ?? "",
817
887
  token_type: "Bearer",
@@ -826,6 +896,7 @@ var AuthService = class extends BaseService {
826
896
  _emitEvent(event, user, accessToken, extra) {
827
897
  if (event === "SIGNED_OUT") this._signedOutSeq = this._clearSeq;
828
898
  const session = accessToken && user ? {
899
+ id: extractSessionId(accessToken),
829
900
  access_token: accessToken,
830
901
  refresh_token: this.client.authStore.refreshToken ?? "",
831
902
  token_type: "Bearer",
@@ -857,6 +928,7 @@ var AuthService = class extends BaseService {
857
928
  }
858
929
  if (req.options?.data) payload.data = req.options.data;
859
930
  if (req.options?.emailRedirectTo) payload.email_redirect_to = req.options.emailRedirectTo;
931
+ if (req.options?.preventEmailEnumeration) payload.prevent_email_enumeration = true;
860
932
  const res = await this.request("POST", `${this.prefix}/register`, payload);
861
933
  if (res.data && !isMfaChallenge(res.data) && !res.data.access_token) {
862
934
  res.data.session = null;
@@ -865,6 +937,7 @@ var AuthService = class extends BaseService {
865
937
  if (res.data && !isMfaChallenge(res.data)) {
866
938
  const tp = res.data;
867
939
  tp.session = {
940
+ id: extractSessionId(tp.access_token),
868
941
  access_token: tp.access_token,
869
942
  refresh_token: tp.refresh_token,
870
943
  token_type: tp.token_type,
@@ -900,6 +973,7 @@ var AuthService = class extends BaseService {
900
973
  if (res.data && !isMfaChallenge(res.data)) {
901
974
  const tp = res.data;
902
975
  tp.session = {
976
+ id: extractSessionId(tp.access_token),
903
977
  access_token: tp.access_token,
904
978
  refresh_token: tp.refresh_token,
905
979
  token_type: tp.token_type,
@@ -1067,6 +1141,7 @@ var AuthService = class extends BaseService {
1067
1141
  const token = this.client.authStore.token;
1068
1142
  const user = this.client.authStore.user;
1069
1143
  const session = token && user ? {
1144
+ id: extractSessionId(token),
1070
1145
  access_token: token,
1071
1146
  refresh_token: this.client.authStore.refreshToken ?? "",
1072
1147
  token_type: "Bearer",
@@ -1458,14 +1533,28 @@ var AuthService = class extends BaseService {
1458
1533
  const code = typeof codeOrParams === "string" ? codeOrParams : codeOrParams.code;
1459
1534
  return this.regenerateRecoveryCodes(code);
1460
1535
  },
1461
- factors: (mfaToken) => this.request("POST", `${this.prefix}/mfa/factors`, { mfa_token: mfaToken }),
1536
+ factors: (mfaToken) => this.request("POST", `${this.prefix}/mfa/factors`, {
1537
+ mfa_token: mfaToken
1538
+ }),
1462
1539
  sms: {
1463
1540
  setup: (phone) => this.request("POST", `${this.prefix}/mfa/sms/setup`, { phone }),
1464
- verifySetup: (code) => this.request("POST", `${this.prefix}/mfa/sms/setup/verify`, { code }),
1465
- send: (mfaToken) => this.request("POST", `${this.prefix}/mfa/sms/send`, {
1466
- mfa_token: mfaToken
1467
- }),
1468
- remove: (password) => this.request("DELETE", `${this.prefix}/mfa/sms`, { password })
1541
+ verifySetup: (code) => this.request(
1542
+ "POST",
1543
+ `${this.prefix}/mfa/sms/setup/verify`,
1544
+ { code }
1545
+ ),
1546
+ send: (mfaToken) => this.request(
1547
+ "POST",
1548
+ `${this.prefix}/mfa/sms/send`,
1549
+ {
1550
+ mfa_token: mfaToken
1551
+ }
1552
+ ),
1553
+ remove: (password) => this.request(
1554
+ "DELETE",
1555
+ `${this.prefix}/mfa/sms`,
1556
+ { password }
1557
+ )
1469
1558
  },
1470
1559
  webauthn: {
1471
1560
  register: (params) => this.webauthnRegister(params),
@@ -1479,6 +1568,13 @@ var AuthService = class extends BaseService {
1479
1568
  }
1480
1569
  };
1481
1570
  }
1571
+ /**
1572
+ * API d'administration de l'authentification (alias vers `client.authAdmin`).
1573
+ * Exige une clé `service_role` (côté serveur uniquement).
1574
+ */
1575
+ get admin() {
1576
+ return this.client.authAdmin;
1577
+ }
1482
1578
  webauthnIndisponible() {
1483
1579
  return {
1484
1580
  data: null,
@@ -1503,7 +1599,7 @@ var AuthService = class extends BaseService {
1503
1599
  `${this.prefix}/mfa/webauthn/register/start`,
1504
1600
  { friendly_name: params?.friendlyName }
1505
1601
  );
1506
- if (!debut.data) return debut;
1602
+ if (!debut.data) return { data: null, error: debut.error };
1507
1603
  let cred;
1508
1604
  try {
1509
1605
  cred = await conteneur.create(creationOptionsFromJson(debut.data.options));
@@ -1511,10 +1607,14 @@ var AuthService = class extends BaseService {
1511
1607
  return this.webauthnAnnule(e);
1512
1608
  }
1513
1609
  if (!cred) return this.webauthnAnnule(new Error("no credential returned"));
1514
- return this.request("POST", `${this.prefix}/mfa/webauthn/register/finish`, {
1515
- credential: attestationToJson(cred),
1516
- friendly_name: params?.friendlyName
1517
- });
1610
+ return this.request(
1611
+ "POST",
1612
+ `${this.prefix}/mfa/webauthn/register/finish`,
1613
+ {
1614
+ credential: attestationToJson(cred),
1615
+ friendly_name: params?.friendlyName
1616
+ }
1617
+ );
1518
1618
  }
1519
1619
  /**
1520
1620
  * Relève un défi MFA (`mfaToken`, reçu d'un `signIn`) avec une passkey : options du serveur,
@@ -1528,7 +1628,7 @@ var AuthService = class extends BaseService {
1528
1628
  `${this.prefix}/mfa/webauthn/verify/start`,
1529
1629
  { mfa_token: params.mfaToken }
1530
1630
  );
1531
- if (!debut.data) return debut;
1631
+ if (!debut.data) return { data: null, error: debut.error };
1532
1632
  let cred;
1533
1633
  try {
1534
1634
  cred = await conteneur.get(requestOptionsFromJson(debut.data.options));
@@ -1570,10 +1670,31 @@ var AuthService = class extends BaseService {
1570
1670
  * MFA : termine une connexion qui a renvoyé un défi (`mfa_token` et code TOTP). Enregistre la session et émet `SIGNED_IN`.
1571
1671
  */
1572
1672
  async mfaVerify(req) {
1573
- const res = await this.request("POST", `${this.prefix}/mfa/verify-login`, req);
1673
+ const raw = req;
1674
+ const mfa_token = raw.mfa_token ?? raw.mfaToken ?? raw.challenge_id ?? raw.challengeId;
1675
+ const code = raw.code;
1676
+ const recovery_code = raw.recovery_code ?? raw.recoveryCode;
1677
+ const sms_code = raw.sms_code ?? raw.smsCode;
1678
+ const body = {};
1679
+ if (mfa_token) body.mfa_token = mfa_token;
1680
+ if (code !== void 0) body.code = code;
1681
+ if (recovery_code !== void 0) body.recovery_code = recovery_code;
1682
+ if (sms_code !== void 0) body.sms_code = sms_code;
1683
+ const res = await this.request("POST", `${this.prefix}/mfa/verify-login`, body);
1574
1684
  if (res.data) {
1575
- this.client.authStore.save(res.data.access_token, res.data.refresh_token, res.data.user);
1576
- this._emitEvent("SIGNED_IN", res.data.user, res.data.access_token);
1685
+ const tp = res.data;
1686
+ tp.session = {
1687
+ id: extractSessionId(tp.access_token),
1688
+ access_token: tp.access_token,
1689
+ refresh_token: tp.refresh_token,
1690
+ token_type: tp.token_type,
1691
+ expires_in: tp.expires_in,
1692
+ user: tp.user,
1693
+ provider_token: tp.provider_token,
1694
+ provider_refresh_token: tp.provider_refresh_token
1695
+ };
1696
+ this.client.authStore.save(tp.access_token, tp.refresh_token, tp.user);
1697
+ this._emitEvent("SIGNED_IN", tp.user, tp.access_token);
1577
1698
  }
1578
1699
  return res;
1579
1700
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurabase/auth",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
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.7.0"
49
+ "@aurabase/core": "0.7.2"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/node": "20.14.15",