@aurabase/auth 0.7.0 → 0.7.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/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,41 @@ 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 soit `generateLink(userId, type)` soit `generateLink({ userId, 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
+ if (typeof userIdOrParams === "object" && userIdOrParams !== null) {
61
+ resolvedUserId = userIdOrParams.userId ?? userIdOrParams.user_id;
62
+ resolvedType = userIdOrParams.type ?? type;
63
+ } else if (typeof userIdOrParams === "string") {
64
+ resolvedUserId = userIdOrParams;
65
+ resolvedType = type;
66
+ }
67
+ if (!resolvedUserId || typeof resolvedUserId !== "string" || resolvedUserId.trim() === "" || resolvedUserId.includes("[object")) {
68
+ return {
69
+ data: null,
70
+ error: new core.AuraError(400, {
71
+ error: {
72
+ code: "INVALID_ARGUMENT",
73
+ message: "userId must be a non-empty string (UUID). Usage: generateLink(userId, type) or generateLink({ userId, type })."
74
+ }
75
+ })
76
+ };
77
+ }
78
+ if (!resolvedType) {
79
+ return {
80
+ data: null,
81
+ error: new core.AuraError(400, {
82
+ error: {
83
+ code: "INVALID_ARGUMENT",
84
+ message: 'type is required for generateLink ("magic" | "recovery" | "invite").'
85
+ }
86
+ })
87
+ };
88
+ }
89
+ return this.request("POST", `${this.prefix}/users/${encodeURIComponent(resolvedUserId)}/generate-link`, { type: resolvedType });
58
90
  }
59
91
  /**
60
92
  * Impersonation (AUTH-037) : jeton COURT (10 minutes au plus) pour agir en tant que l'utilisateur,
@@ -536,6 +568,15 @@ var SessionManager = class {
536
568
  };
537
569
 
538
570
  // src/AuthService.ts
571
+ function extractSessionId(token) {
572
+ if (!token) return void 0;
573
+ try {
574
+ const payload = decodeJwt(token).payload;
575
+ return payload?.session_id ?? payload?.sid ?? void 0;
576
+ } catch {
577
+ return void 0;
578
+ }
579
+ }
539
580
  function isMfaChallenge(v) {
540
581
  return typeof v === "object" && v !== null && v.mfa_required === true;
541
582
  }
@@ -814,6 +855,7 @@ var AuthService = class extends core.BaseService {
814
855
  queueMicrotask(() => {
815
856
  if (this._stateListeners.has(callback)) {
816
857
  const session = store.token && store.user ? {
858
+ id: extractSessionId(store.token),
817
859
  access_token: store.token,
818
860
  refresh_token: store.refreshToken ?? "",
819
861
  token_type: "Bearer",
@@ -828,6 +870,7 @@ var AuthService = class extends core.BaseService {
828
870
  _emitEvent(event, user, accessToken, extra) {
829
871
  if (event === "SIGNED_OUT") this._signedOutSeq = this._clearSeq;
830
872
  const session = accessToken && user ? {
873
+ id: extractSessionId(accessToken),
831
874
  access_token: accessToken,
832
875
  refresh_token: this.client.authStore.refreshToken ?? "",
833
876
  token_type: "Bearer",
@@ -859,6 +902,7 @@ var AuthService = class extends core.BaseService {
859
902
  }
860
903
  if (req.options?.data) payload.data = req.options.data;
861
904
  if (req.options?.emailRedirectTo) payload.email_redirect_to = req.options.emailRedirectTo;
905
+ if (req.options?.preventEmailEnumeration) payload.prevent_email_enumeration = true;
862
906
  const res = await this.request("POST", `${this.prefix}/register`, payload);
863
907
  if (res.data && !isMfaChallenge(res.data) && !res.data.access_token) {
864
908
  res.data.session = null;
@@ -867,6 +911,7 @@ var AuthService = class extends core.BaseService {
867
911
  if (res.data && !isMfaChallenge(res.data)) {
868
912
  const tp = res.data;
869
913
  tp.session = {
914
+ id: extractSessionId(tp.access_token),
870
915
  access_token: tp.access_token,
871
916
  refresh_token: tp.refresh_token,
872
917
  token_type: tp.token_type,
@@ -902,6 +947,7 @@ var AuthService = class extends core.BaseService {
902
947
  if (res.data && !isMfaChallenge(res.data)) {
903
948
  const tp = res.data;
904
949
  tp.session = {
950
+ id: extractSessionId(tp.access_token),
905
951
  access_token: tp.access_token,
906
952
  refresh_token: tp.refresh_token,
907
953
  token_type: tp.token_type,
@@ -1069,6 +1115,7 @@ var AuthService = class extends core.BaseService {
1069
1115
  const token = this.client.authStore.token;
1070
1116
  const user = this.client.authStore.user;
1071
1117
  const session = token && user ? {
1118
+ id: extractSessionId(token),
1072
1119
  access_token: token,
1073
1120
  refresh_token: this.client.authStore.refreshToken ?? "",
1074
1121
  token_type: "Bearer",
@@ -1572,10 +1619,31 @@ var AuthService = class extends core.BaseService {
1572
1619
  * MFA : termine une connexion qui a renvoyé un défi (`mfa_token` et code TOTP). Enregistre la session et émet `SIGNED_IN`.
1573
1620
  */
1574
1621
  async mfaVerify(req) {
1575
- const res = await this.request("POST", `${this.prefix}/mfa/verify-login`, req);
1622
+ const raw = req;
1623
+ const mfa_token = raw.mfa_token ?? raw.mfaToken ?? raw.challenge_id ?? raw.challengeId;
1624
+ const code = raw.code;
1625
+ const recovery_code = raw.recovery_code ?? raw.recoveryCode;
1626
+ const sms_code = raw.sms_code ?? raw.smsCode;
1627
+ const body = {};
1628
+ if (mfa_token) body.mfa_token = mfa_token;
1629
+ if (code !== void 0) body.code = code;
1630
+ if (recovery_code !== void 0) body.recovery_code = recovery_code;
1631
+ if (sms_code !== void 0) body.sms_code = sms_code;
1632
+ const res = await this.request("POST", `${this.prefix}/mfa/verify-login`, body);
1576
1633
  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);
1634
+ const tp = res.data;
1635
+ tp.session = {
1636
+ id: extractSessionId(tp.access_token),
1637
+ access_token: tp.access_token,
1638
+ refresh_token: tp.refresh_token,
1639
+ token_type: tp.token_type,
1640
+ expires_in: tp.expires_in,
1641
+ user: tp.user,
1642
+ provider_token: tp.provider_token,
1643
+ provider_refresh_token: tp.provider_refresh_token
1644
+ };
1645
+ this.client.authStore.save(tp.access_token, tp.refresh_token, tp.user);
1646
+ this._emitEvent("SIGNED_IN", tp.user, tp.access_token);
1579
1647
  }
1580
1648
  return res;
1581
1649
  }
package/dist/index.d.cts CHANGED
@@ -72,8 +72,13 @@ 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 soit `generateLink(userId, type)` soit `generateLink({ userId, type })`.
75
76
  */
76
- generateLink(userId: string, type: GenerateLinkType): Promise<AuraResponse<GenerateLinkResult>>;
77
+ generateLink(userIdOrParams: string | {
78
+ userId?: string;
79
+ user_id?: string;
80
+ type: GenerateLinkType;
81
+ }, type?: GenerateLinkType): Promise<AuraResponse<GenerateLinkResult>>;
77
82
  /**
78
83
  * Impersonation (AUTH-037) : jeton COURT (10 minutes au plus) pour agir en tant que l'utilisateur,
79
84
  * avec le claim `act: { sub }`. Pas de refresh token, journalisé (`admin_impersonation`).
package/dist/index.d.ts CHANGED
@@ -72,8 +72,13 @@ 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 soit `generateLink(userId, type)` soit `generateLink({ userId, type })`.
75
76
  */
76
- generateLink(userId: string, type: GenerateLinkType): Promise<AuraResponse<GenerateLinkResult>>;
77
+ generateLink(userIdOrParams: string | {
78
+ userId?: string;
79
+ user_id?: string;
80
+ type: GenerateLinkType;
81
+ }, type?: GenerateLinkType): Promise<AuraResponse<GenerateLinkResult>>;
77
82
  /**
78
83
  * Impersonation (AUTH-037) : jeton COURT (10 minutes au plus) pour agir en tant que l'utilisateur,
79
84
  * avec le claim `act: { sub }`. Pas de refresh token, journalisé (`admin_impersonation`).
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,41 @@ 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 soit `generateLink(userId, type)` soit `generateLink({ userId, 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
+ if (typeof userIdOrParams === "object" && userIdOrParams !== null) {
59
+ resolvedUserId = userIdOrParams.userId ?? userIdOrParams.user_id;
60
+ resolvedType = userIdOrParams.type ?? type;
61
+ } else if (typeof userIdOrParams === "string") {
62
+ resolvedUserId = userIdOrParams;
63
+ resolvedType = type;
64
+ }
65
+ if (!resolvedUserId || typeof resolvedUserId !== "string" || resolvedUserId.trim() === "" || resolvedUserId.includes("[object")) {
66
+ return {
67
+ data: null,
68
+ error: new AuraError(400, {
69
+ error: {
70
+ code: "INVALID_ARGUMENT",
71
+ message: "userId must be a non-empty string (UUID). Usage: generateLink(userId, type) or generateLink({ userId, type })."
72
+ }
73
+ })
74
+ };
75
+ }
76
+ if (!resolvedType) {
77
+ return {
78
+ data: null,
79
+ error: new AuraError(400, {
80
+ error: {
81
+ code: "INVALID_ARGUMENT",
82
+ message: 'type is required for generateLink ("magic" | "recovery" | "invite").'
83
+ }
84
+ })
85
+ };
86
+ }
87
+ return this.request("POST", `${this.prefix}/users/${encodeURIComponent(resolvedUserId)}/generate-link`, { type: resolvedType });
56
88
  }
57
89
  /**
58
90
  * Impersonation (AUTH-037) : jeton COURT (10 minutes au plus) pour agir en tant que l'utilisateur,
@@ -534,6 +566,15 @@ var SessionManager = class {
534
566
  };
535
567
 
536
568
  // src/AuthService.ts
569
+ function extractSessionId(token) {
570
+ if (!token) return void 0;
571
+ try {
572
+ const payload = decodeJwt(token).payload;
573
+ return payload?.session_id ?? payload?.sid ?? void 0;
574
+ } catch {
575
+ return void 0;
576
+ }
577
+ }
537
578
  function isMfaChallenge(v) {
538
579
  return typeof v === "object" && v !== null && v.mfa_required === true;
539
580
  }
@@ -812,6 +853,7 @@ var AuthService = class extends BaseService {
812
853
  queueMicrotask(() => {
813
854
  if (this._stateListeners.has(callback)) {
814
855
  const session = store.token && store.user ? {
856
+ id: extractSessionId(store.token),
815
857
  access_token: store.token,
816
858
  refresh_token: store.refreshToken ?? "",
817
859
  token_type: "Bearer",
@@ -826,6 +868,7 @@ var AuthService = class extends BaseService {
826
868
  _emitEvent(event, user, accessToken, extra) {
827
869
  if (event === "SIGNED_OUT") this._signedOutSeq = this._clearSeq;
828
870
  const session = accessToken && user ? {
871
+ id: extractSessionId(accessToken),
829
872
  access_token: accessToken,
830
873
  refresh_token: this.client.authStore.refreshToken ?? "",
831
874
  token_type: "Bearer",
@@ -857,6 +900,7 @@ var AuthService = class extends BaseService {
857
900
  }
858
901
  if (req.options?.data) payload.data = req.options.data;
859
902
  if (req.options?.emailRedirectTo) payload.email_redirect_to = req.options.emailRedirectTo;
903
+ if (req.options?.preventEmailEnumeration) payload.prevent_email_enumeration = true;
860
904
  const res = await this.request("POST", `${this.prefix}/register`, payload);
861
905
  if (res.data && !isMfaChallenge(res.data) && !res.data.access_token) {
862
906
  res.data.session = null;
@@ -865,6 +909,7 @@ var AuthService = class extends BaseService {
865
909
  if (res.data && !isMfaChallenge(res.data)) {
866
910
  const tp = res.data;
867
911
  tp.session = {
912
+ id: extractSessionId(tp.access_token),
868
913
  access_token: tp.access_token,
869
914
  refresh_token: tp.refresh_token,
870
915
  token_type: tp.token_type,
@@ -900,6 +945,7 @@ var AuthService = class extends BaseService {
900
945
  if (res.data && !isMfaChallenge(res.data)) {
901
946
  const tp = res.data;
902
947
  tp.session = {
948
+ id: extractSessionId(tp.access_token),
903
949
  access_token: tp.access_token,
904
950
  refresh_token: tp.refresh_token,
905
951
  token_type: tp.token_type,
@@ -1067,6 +1113,7 @@ var AuthService = class extends BaseService {
1067
1113
  const token = this.client.authStore.token;
1068
1114
  const user = this.client.authStore.user;
1069
1115
  const session = token && user ? {
1116
+ id: extractSessionId(token),
1070
1117
  access_token: token,
1071
1118
  refresh_token: this.client.authStore.refreshToken ?? "",
1072
1119
  token_type: "Bearer",
@@ -1570,10 +1617,31 @@ var AuthService = class extends BaseService {
1570
1617
  * MFA : termine une connexion qui a renvoyé un défi (`mfa_token` et code TOTP). Enregistre la session et émet `SIGNED_IN`.
1571
1618
  */
1572
1619
  async mfaVerify(req) {
1573
- const res = await this.request("POST", `${this.prefix}/mfa/verify-login`, req);
1620
+ const raw = req;
1621
+ const mfa_token = raw.mfa_token ?? raw.mfaToken ?? raw.challenge_id ?? raw.challengeId;
1622
+ const code = raw.code;
1623
+ const recovery_code = raw.recovery_code ?? raw.recoveryCode;
1624
+ const sms_code = raw.sms_code ?? raw.smsCode;
1625
+ const body = {};
1626
+ if (mfa_token) body.mfa_token = mfa_token;
1627
+ if (code !== void 0) body.code = code;
1628
+ if (recovery_code !== void 0) body.recovery_code = recovery_code;
1629
+ if (sms_code !== void 0) body.sms_code = sms_code;
1630
+ const res = await this.request("POST", `${this.prefix}/mfa/verify-login`, body);
1574
1631
  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);
1632
+ const tp = res.data;
1633
+ tp.session = {
1634
+ id: extractSessionId(tp.access_token),
1635
+ access_token: tp.access_token,
1636
+ refresh_token: tp.refresh_token,
1637
+ token_type: tp.token_type,
1638
+ expires_in: tp.expires_in,
1639
+ user: tp.user,
1640
+ provider_token: tp.provider_token,
1641
+ provider_refresh_token: tp.provider_refresh_token
1642
+ };
1643
+ this.client.authStore.save(tp.access_token, tp.refresh_token, tp.user);
1644
+ this._emitEvent("SIGNED_IN", tp.user, tp.access_token);
1577
1645
  }
1578
1646
  return res;
1579
1647
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurabase/auth",
3
- "version": "0.7.0",
3
+ "version": "0.7.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.7.0"
49
+ "@aurabase/core": "0.7.1"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/node": "20.14.15",