@getpara/user-management-client 3.4.0 → 3.5.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.
@@ -112,7 +112,7 @@ const throwParaApiError = (message, code, status, responseURL, data, cause) => {
112
112
  throw paraApiError;
113
113
  };
114
114
  const handleResponseError = (error) => {
115
- var _a, _b, _c;
115
+ var _a, _c, _d;
116
116
  if (error === null) throw new import_error.ParaApiError("Error is null");
117
117
  if (import_axios.default.isAxiosError(error)) {
118
118
  const data = (_a = error.response) == null ? void 0 : _a.data;
@@ -123,7 +123,12 @@ const handleResponseError = (error) => {
123
123
  const body = data;
124
124
  if (hasUsableString(body.message)) message = body.message;
125
125
  serverCode = body.code;
126
- serverData = body.data;
126
+ if (body.data && typeof body.data === "object") {
127
+ serverData = body.data;
128
+ } else {
129
+ const _b = body, { message: _message, code: _code } = _b, rest = __objRest(_b, ["message", "code"]);
130
+ serverData = Object.keys(rest).length > 0 ? rest : void 0;
131
+ }
127
132
  }
128
133
  if (error.code === "ERR_NETWORK") {
129
134
  message = "Connection error";
@@ -133,8 +138,8 @@ const handleResponseError = (error) => {
133
138
  throwParaApiError(
134
139
  message,
135
140
  serverCode != null ? serverCode : error.code,
136
- (_b = error.response) == null ? void 0 : _b.status,
137
- (_c = error.request) == null ? void 0 : _c.responseURL,
141
+ (_c = error.response) == null ? void 0 : _c.status,
142
+ (_d = error.request) == null ? void 0 : _d.responseURL,
138
143
  serverData,
139
144
  error
140
145
  );
@@ -191,6 +196,33 @@ class Client {
191
196
  const res = yield this.baseRequest.post("/users/verify-oauth");
192
197
  return res.data;
193
198
  });
199
+ // POST /internal/v1/auth/2fa/enroll
200
+ // Login-time 2FA enrollment (ENG-6906). Authenticated by the active session.
201
+ // Returns the otpauth URI to render as a QR plus the one-time backup codes.
202
+ this.enrollMfa = () => __async(this, null, function* () {
203
+ const res = yield this.baseRequest.post("/internal/v1/auth/2fa/enroll");
204
+ return res.data;
205
+ });
206
+ // POST /internal/v1/auth/2fa/verify
207
+ // Login-time 2FA verification (ENG-6906). On success the backend stamps the
208
+ // session so the keyshare/sign gate passes; callers should then re-poll the login
209
+ // status (verify-oauth) to advance to `stage:'done'`. A wrong code is a 401 with
210
+ // `code:'UNAUTHORIZED'` carrying the remaining attempt budget — we surface that as
211
+ // a typed `{ ok:false, attemptsRemaining }` rather than throwing, so the UI can
212
+ // re-prompt. Other failures (e.g. NOT_ENROLLED 400, network) still throw.
213
+ this.verifyMfa = (code) => __async(this, null, function* () {
214
+ try {
215
+ yield this.baseRequest.post("/internal/v1/auth/2fa/verify", { code });
216
+ return { ok: true };
217
+ } catch (error) {
218
+ const apiError = error;
219
+ if ((apiError == null ? void 0 : apiError.isParaApiError) && (apiError.code === "UNAUTHORIZED" || apiError.status === 401)) {
220
+ const data = apiError.data;
221
+ return { ok: false, attemptsRemaining: data == null ? void 0 : data.attemptsRemaining };
222
+ }
223
+ throw error;
224
+ }
225
+ });
194
226
  this.loginExternalWallet = (_0) => __async(this, [_0], function* ({
195
227
  externalWallet,
196
228
  shouldTrackUser,
@@ -43,7 +43,7 @@ const throwParaApiError = (message, code, status, responseURL, data, cause) => {
43
43
  throw paraApiError;
44
44
  };
45
45
  const handleResponseError = (error) => {
46
- var _a, _b, _c;
46
+ var _a, _c, _d;
47
47
  if (error === null) throw new ParaApiError("Error is null");
48
48
  if (axios.isAxiosError(error)) {
49
49
  const data = (_a = error.response) == null ? void 0 : _a.data;
@@ -54,7 +54,12 @@ const handleResponseError = (error) => {
54
54
  const body = data;
55
55
  if (hasUsableString(body.message)) message = body.message;
56
56
  serverCode = body.code;
57
- serverData = body.data;
57
+ if (body.data && typeof body.data === "object") {
58
+ serverData = body.data;
59
+ } else {
60
+ const _b = body, { message: _message, code: _code } = _b, rest = __objRest(_b, ["message", "code"]);
61
+ serverData = Object.keys(rest).length > 0 ? rest : void 0;
62
+ }
58
63
  }
59
64
  if (error.code === "ERR_NETWORK") {
60
65
  message = "Connection error";
@@ -64,8 +69,8 @@ const handleResponseError = (error) => {
64
69
  throwParaApiError(
65
70
  message,
66
71
  serverCode != null ? serverCode : error.code,
67
- (_b = error.response) == null ? void 0 : _b.status,
68
- (_c = error.request) == null ? void 0 : _c.responseURL,
72
+ (_c = error.response) == null ? void 0 : _c.status,
73
+ (_d = error.request) == null ? void 0 : _d.responseURL,
69
74
  serverData,
70
75
  error
71
76
  );
@@ -122,6 +127,33 @@ class Client {
122
127
  const res = yield this.baseRequest.post("/users/verify-oauth");
123
128
  return res.data;
124
129
  });
130
+ // POST /internal/v1/auth/2fa/enroll
131
+ // Login-time 2FA enrollment (ENG-6906). Authenticated by the active session.
132
+ // Returns the otpauth URI to render as a QR plus the one-time backup codes.
133
+ this.enrollMfa = () => __async(this, null, function* () {
134
+ const res = yield this.baseRequest.post("/internal/v1/auth/2fa/enroll");
135
+ return res.data;
136
+ });
137
+ // POST /internal/v1/auth/2fa/verify
138
+ // Login-time 2FA verification (ENG-6906). On success the backend stamps the
139
+ // session so the keyshare/sign gate passes; callers should then re-poll the login
140
+ // status (verify-oauth) to advance to `stage:'done'`. A wrong code is a 401 with
141
+ // `code:'UNAUTHORIZED'` carrying the remaining attempt budget — we surface that as
142
+ // a typed `{ ok:false, attemptsRemaining }` rather than throwing, so the UI can
143
+ // re-prompt. Other failures (e.g. NOT_ENROLLED 400, network) still throw.
144
+ this.verifyMfa = (code) => __async(this, null, function* () {
145
+ try {
146
+ yield this.baseRequest.post("/internal/v1/auth/2fa/verify", { code });
147
+ return { ok: true };
148
+ } catch (error) {
149
+ const apiError = error;
150
+ if ((apiError == null ? void 0 : apiError.isParaApiError) && (apiError.code === "UNAUTHORIZED" || apiError.status === 401)) {
151
+ const data = apiError.data;
152
+ return { ok: false, attemptsRemaining: data == null ? void 0 : data.attemptsRemaining };
153
+ }
154
+ throw error;
155
+ }
156
+ });
125
157
  this.loginExternalWallet = (_0) => __async(this, [_0], function* ({
126
158
  externalWallet,
127
159
  shouldTrackUser,
@@ -163,6 +163,24 @@ interface EncryptedWalletPrivateKey {
163
163
  biometricPublicKey?: string;
164
164
  passwordId?: string;
165
165
  }
166
+ /**
167
+ * Login-time 2FA (MFA) enroll/verify response shapes (ENG-6906). The challenge
168
+ * payload itself (`MfaChallenge`) lives in @getpara/shared and flows through the
169
+ * login auth-state poll; these are the bodies of the two dedicated session-authed
170
+ * endpoints under /internal/v1/auth/2fa.
171
+ */
172
+ export type EnrollMfaResponse = {
173
+ /** otpauth:// URI for the authenticator app. */
174
+ uri: string;
175
+ /** One-time backup codes, shown to the user exactly once at enrollment. */
176
+ backupCodes: string[];
177
+ };
178
+ export type VerifyMfaResult = {
179
+ ok: true;
180
+ } | {
181
+ ok: false;
182
+ attemptsRemaining?: number;
183
+ };
166
184
  export type SDKType = 'WEB' | 'SERVER' | 'BRIDGE' | 'REACT_NATIVE';
167
185
  export type VerifyTelegramRes = {
168
186
  isValid: true;
@@ -192,6 +210,8 @@ declare class Client {
192
210
  sessionLookupId?: string;
193
211
  }) => Promise<VerifyTelegramResponse>;
194
212
  verifyOAuth: () => Promise<VerifyThirdPartyAuth | null>;
213
+ enrollMfa: () => Promise<EnrollMfaResponse>;
214
+ verifyMfa: (code: string) => Promise<VerifyMfaResult>;
195
215
  loginExternalWallet: ({ externalWallet, shouldTrackUser, chainId, uri, }: {
196
216
  externalWallet: ExternalWalletInfo;
197
217
  shouldTrackUser?: boolean;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@getpara/user-management-client",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "dependencies": {
5
- "@getpara/shared": "^1.21.0",
5
+ "@getpara/shared": "^1.23.0",
6
6
  "@opentelemetry/api": "^1.9.1",
7
7
  "axios": "^1.8.4",
8
8
  "axios-retry": "^4.5.0",
@@ -22,7 +22,7 @@
22
22
  "dist",
23
23
  "package.json"
24
24
  ],
25
- "gitHead": "795829c50bb71817a84bdbf5e6561ca4df3a827d",
25
+ "gitHead": "2e70485f8f206ff50f58b339ebf0922fd259858f",
26
26
  "main": "dist/cjs/index.js",
27
27
  "module": "dist/esm/index.js",
28
28
  "scripts": {