@object-ui/auth 11.5.0 → 13.2.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.
- package/CHANGELOG.md +54 -0
- package/dist/AuthContext.d.ts +14 -2
- package/dist/AuthContext.d.ts.map +1 -1
- package/dist/AuthProvider.d.ts.map +1 -1
- package/dist/AuthProvider.js +78 -6
- package/dist/ForgotPasswordForm.d.ts +26 -0
- package/dist/ForgotPasswordForm.d.ts.map +1 -1
- package/dist/ForgotPasswordForm.js +104 -3
- package/dist/LoginForm.d.ts +16 -0
- package/dist/LoginForm.d.ts.map +1 -1
- package/dist/LoginForm.js +68 -3
- package/dist/createAuthClient.d.ts.map +1 -1
- package/dist/createAuthClient.js +52 -0
- package/dist/types.d.ts +31 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/useAuth.d.ts.map +1 -1
- package/dist/useAuth.js +4 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# @object-ui/auth
|
|
2
2
|
|
|
3
|
+
## 13.2.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 53c40c2: feat: identity import — the stock ImportWizard now drives sys_user bulk import (framework#2782)
|
|
8
|
+
|
|
9
|
+
The Users list gets an Import entry for platform admins (gated on
|
|
10
|
+
`features.admin` from `/api/v1/auth/config` plus workspace-admin), wired to
|
|
11
|
+
the dedicated `POST /api/v1/auth/admin/import-users` pipeline instead of the
|
|
12
|
+
generic data import (which would bypass better-auth hashing and produce
|
|
13
|
+
accounts that can never sign in).
|
|
14
|
+
|
|
15
|
+
- **plugin-grid**: two generic, backend-agnostic ImportWizard slots —
|
|
16
|
+
`extraOptionsContent` (host-injected options on the preview step) and
|
|
17
|
+
`renderResultExtra` (host-rendered content on the result step).
|
|
18
|
+
- **app-shell**: identity import dataSource adapter — splits files into the
|
|
19
|
+
endpoint's ≤500-row batches (idempotent upsert makes re-runs safe), injects
|
|
20
|
+
the selected password policy, renumbers per-batch results onto the whole
|
|
21
|
+
file, and enriches rows with their sign-in identity. Password policy panel
|
|
22
|
+
(`none` default / `invite` / `temporary`) and a one-shot temporary-password
|
|
23
|
+
reveal with CSV download (client memory only — nothing is persisted).
|
|
24
|
+
Async-job/undo surfaces are hidden for identity import by design.
|
|
25
|
+
- **auth**: `AuthPublicConfig.features.admin` typing.
|
|
26
|
+
- **i18n**: en/zh strings for the identity import panels.
|
|
27
|
+
- @object-ui/types@13.2.0
|
|
28
|
+
|
|
29
|
+
## 13.1.0
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- @object-ui/types@13.1.0
|
|
34
|
+
|
|
35
|
+
## 13.0.0
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- Updated dependencies [619097e]
|
|
40
|
+
- @object-ui/types@13.0.0
|
|
41
|
+
|
|
42
|
+
## 12.1.0
|
|
43
|
+
|
|
44
|
+
### Patch Changes
|
|
45
|
+
|
|
46
|
+
- Updated dependencies [c31874d]
|
|
47
|
+
- @object-ui/types@12.1.0
|
|
48
|
+
|
|
49
|
+
## 12.0.0
|
|
50
|
+
|
|
51
|
+
### Patch Changes
|
|
52
|
+
|
|
53
|
+
- Updated dependencies [226fde9]
|
|
54
|
+
- Updated dependencies [e4de456]
|
|
55
|
+
- @object-ui/types@12.0.0
|
|
56
|
+
|
|
3
57
|
## 11.5.0
|
|
4
58
|
|
|
5
59
|
### Patch Changes
|
package/dist/AuthContext.d.ts
CHANGED
|
@@ -47,6 +47,14 @@ export interface AuthContextValue {
|
|
|
47
47
|
sendVerificationEmail: (email: string, callbackURL?: string) => Promise<void>;
|
|
48
48
|
/** Reset password with token */
|
|
49
49
|
resetPassword: (token: string, newPassword: string) => Promise<void>;
|
|
50
|
+
/** framework#2780 — request a sign-in OTP SMS for the phone number. */
|
|
51
|
+
sendPhoneOtp: (phoneNumber: string) => Promise<void>;
|
|
52
|
+
/** framework#2780 — sign in by verifying a phone OTP. */
|
|
53
|
+
signInWithPhoneOtp: (phoneNumber: string, code: string) => Promise<void>;
|
|
54
|
+
/** framework#2780 — request a password-reset OTP SMS for the phone number. */
|
|
55
|
+
requestPhonePasswordReset: (phoneNumber: string) => Promise<void>;
|
|
56
|
+
/** framework#2780 — reset the password with a phone OTP. */
|
|
57
|
+
resetPasswordWithPhoneOtp: (phoneNumber: string, otp: string, newPassword: string) => Promise<void>;
|
|
50
58
|
/**
|
|
51
59
|
* Change the local (email/password) password. Requires the current
|
|
52
60
|
* password. Use this when `hasLocalPassword()` returns true.
|
|
@@ -104,8 +112,12 @@ export interface AuthContextValue {
|
|
|
104
112
|
slug: string;
|
|
105
113
|
logo?: string;
|
|
106
114
|
}) => Promise<AuthOrganization>;
|
|
107
|
-
/**
|
|
108
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Refresh the organizations list. Returns the freshly fetched list so
|
|
117
|
+
* callers that need it right away (e.g. the first-run wizard's rename
|
|
118
|
+
* step) don't read a stale `organizations` closure.
|
|
119
|
+
*/
|
|
120
|
+
refreshOrganizations: () => Promise<AuthOrganization[] | undefined>;
|
|
109
121
|
/** Update organization details (owner/admin) */
|
|
110
122
|
updateOrganization: (orgId: string, data: Partial<Pick<AuthOrganization, 'name' | 'slug' | 'logo' | 'metadata'>>) => Promise<AuthOrganization>;
|
|
111
123
|
/** Delete an organization (owner) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../src/AuthContext.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../src/AuthContext.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../src/AuthProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AAEzE,OAAO,KAAK,EAAwB,kBAAkB,EAAE,kBAAkB,EAAyG,MAAM,SAAS,CAAC;AAKnM,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,MAAM,EAAE,cAAc,EACtB,iBAAiB,EACjB,OAAc,EACd,WAAW,EACX,QAAQ,GACT,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../src/AuthProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AAEzE,OAAO,KAAK,EAAwB,kBAAkB,EAAE,kBAAkB,EAAyG,MAAM,SAAS,CAAC;AAKnM,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,MAAM,EAAE,cAAc,EACtB,iBAAiB,EACjB,OAAc,EACd,WAAW,EACX,QAAQ,GACT,EAAE,iBAAiB,qBAynBnB"}
|
package/dist/AuthProvider.js
CHANGED
|
@@ -230,6 +230,57 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
|
|
|
230
230
|
throw authError;
|
|
231
231
|
}
|
|
232
232
|
}, [client]);
|
|
233
|
+
// --- Phone-number OTP (framework#2780) --------------------------------
|
|
234
|
+
const sendPhoneOtp = useCallback(async (phoneNumber) => {
|
|
235
|
+
setError(null);
|
|
236
|
+
try {
|
|
237
|
+
await client.sendPhoneOtp(phoneNumber);
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
const authError = err instanceof Error ? err : new Error(String(err));
|
|
241
|
+
setError(authError);
|
|
242
|
+
throw authError;
|
|
243
|
+
}
|
|
244
|
+
}, [client]);
|
|
245
|
+
const signInWithPhoneOtp = useCallback(async (phoneNumber, code) => {
|
|
246
|
+
setIsLoading(true);
|
|
247
|
+
setError(null);
|
|
248
|
+
try {
|
|
249
|
+
const result = await client.signInWithPhoneOtp(phoneNumber, code);
|
|
250
|
+
setUser(result.user);
|
|
251
|
+
setSession(result.session);
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
const authError = err instanceof Error ? err : new Error(String(err));
|
|
255
|
+
setError(authError);
|
|
256
|
+
throw authError;
|
|
257
|
+
}
|
|
258
|
+
finally {
|
|
259
|
+
setIsLoading(false);
|
|
260
|
+
}
|
|
261
|
+
}, [client]);
|
|
262
|
+
const requestPhonePasswordReset = useCallback(async (phoneNumber) => {
|
|
263
|
+
setError(null);
|
|
264
|
+
try {
|
|
265
|
+
await client.requestPhonePasswordReset(phoneNumber);
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
const authError = err instanceof Error ? err : new Error(String(err));
|
|
269
|
+
setError(authError);
|
|
270
|
+
throw authError;
|
|
271
|
+
}
|
|
272
|
+
}, [client]);
|
|
273
|
+
const resetPasswordWithPhoneOtp = useCallback(async (phoneNumber, otp, newPassword) => {
|
|
274
|
+
setError(null);
|
|
275
|
+
try {
|
|
276
|
+
await client.resetPasswordWithPhoneOtp(phoneNumber, otp, newPassword);
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
const authError = err instanceof Error ? err : new Error(String(err));
|
|
280
|
+
setError(authError);
|
|
281
|
+
throw authError;
|
|
282
|
+
}
|
|
283
|
+
}, [client]);
|
|
233
284
|
// ADR-0069 — the API fetch interceptor emits an auth-policy gate; raise the
|
|
234
285
|
// remediation overlay. Don't override an already-shown gate.
|
|
235
286
|
useEffect(() => {
|
|
@@ -282,21 +333,37 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
|
|
|
282
333
|
try {
|
|
283
334
|
const orgs = await client.listOrganizations();
|
|
284
335
|
if (isCancelled?.())
|
|
285
|
-
return;
|
|
336
|
+
return orgs;
|
|
286
337
|
setOrganizations(orgs);
|
|
287
338
|
// If no active org is set but orgs exist, try to get active from server
|
|
288
339
|
if (orgs.length > 0 && !activeOrganization) {
|
|
340
|
+
let active = null;
|
|
289
341
|
try {
|
|
290
|
-
|
|
291
|
-
if (active && !isCancelled?.()) {
|
|
292
|
-
setActiveOrganization(active);
|
|
293
|
-
ActiveOrganizationStorage.set(active.id);
|
|
294
|
-
}
|
|
342
|
+
active = await client.getActiveOrganization();
|
|
295
343
|
}
|
|
296
344
|
catch {
|
|
297
345
|
// No active org set — that's fine
|
|
346
|
+
active = null;
|
|
347
|
+
}
|
|
348
|
+
// Single-membership repair (ADR-0081): a session created before the
|
|
349
|
+
// server-side active-org stamp existed carries no active org even
|
|
350
|
+
// though the user belongs to exactly one — activate it so org-scoped
|
|
351
|
+
// UI ({current_org_id} nav links, org endpoints) works without a
|
|
352
|
+
// re-login. With multiple orgs the choice stays with the user.
|
|
353
|
+
if (!active && orgs.length === 1) {
|
|
354
|
+
try {
|
|
355
|
+
active = await client.setActiveOrganization(orgs[0].id);
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
active = null;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (active && !isCancelled?.()) {
|
|
362
|
+
setActiveOrganization(active);
|
|
363
|
+
ActiveOrganizationStorage.set(active.id);
|
|
298
364
|
}
|
|
299
365
|
}
|
|
366
|
+
return orgs;
|
|
300
367
|
}
|
|
301
368
|
catch (err) {
|
|
302
369
|
// A route change / unmount racing the in-flight request is not a real
|
|
@@ -441,6 +508,10 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
|
|
|
441
508
|
forgotPassword,
|
|
442
509
|
sendVerificationEmail,
|
|
443
510
|
resetPassword,
|
|
511
|
+
sendPhoneOtp,
|
|
512
|
+
signInWithPhoneOtp,
|
|
513
|
+
requestPhonePasswordReset,
|
|
514
|
+
resetPasswordWithPhoneOtp,
|
|
444
515
|
changePassword,
|
|
445
516
|
remediationRequired,
|
|
446
517
|
setRemediationRequired,
|
|
@@ -473,6 +544,7 @@ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChang
|
|
|
473
544
|
}), [
|
|
474
545
|
user, session, isAuthenticated, isAuthEnabled, isLoading, error, isPreviewMode, previewMode,
|
|
475
546
|
signIn, signUp, signOut, updateUser, forgotPassword, sendVerificationEmail, resetPassword, changePassword, setInitialPassword, hasLocalPassword, getAuthConfig, signInWithProvider,
|
|
547
|
+
sendPhoneOtp, signInWithPhoneOtp, requestPhonePasswordReset, resetPasswordWithPhoneOtp,
|
|
476
548
|
remediationRequired, enrollTotp, verifyTotp,
|
|
477
549
|
organizations, activeOrganization, activeMember, isOrganizationsLoading, switchOrganization, createOrganization, refreshOrganizations,
|
|
478
550
|
updateOrganization, deleteOrganization, leaveOrganization,
|
|
@@ -18,6 +18,32 @@ export interface ForgotPasswordFormLabels {
|
|
|
18
18
|
backToSignInText?: string;
|
|
19
19
|
rememberPasswordText?: string;
|
|
20
20
|
signInText?: string;
|
|
21
|
+
/** Phone reset (framework#2780) — phone field label (defaults to "Phone number"). */
|
|
22
|
+
phoneLabel?: string;
|
|
23
|
+
/** Phone reset — phone field placeholder (defaults to "+1 555 000 0000"). */
|
|
24
|
+
phonePlaceholder?: string;
|
|
25
|
+
/** Phone reset — code field label (defaults to "Verification code"). */
|
|
26
|
+
otpCodeLabel?: string;
|
|
27
|
+
/** Phone reset — code field placeholder (defaults to "6-digit code"). */
|
|
28
|
+
otpCodePlaceholder?: string;
|
|
29
|
+
/** Phone reset — "send code" button (defaults to "Get code"). */
|
|
30
|
+
sendOtpButton?: string;
|
|
31
|
+
/** Phone reset — resend countdown, `{seconds}` hole (defaults to "Resend in {seconds}s"). */
|
|
32
|
+
resendOtpCountdownText?: string;
|
|
33
|
+
/** Phone reset — new password field label (defaults to "New password"). */
|
|
34
|
+
newPasswordLabel?: string;
|
|
35
|
+
/** Phone reset — new password placeholder (defaults to "Enter a new password"). */
|
|
36
|
+
newPasswordPlaceholder?: string;
|
|
37
|
+
/** Phone reset — submit button (defaults to "Reset Password"). */
|
|
38
|
+
resetButton?: string;
|
|
39
|
+
/** Link that switches to the phone (SMS code) branch (defaults to "Reset via SMS code"). */
|
|
40
|
+
usePhoneResetText?: string;
|
|
41
|
+
/** Link that switches back to the email branch (defaults to "Reset via email instead"). */
|
|
42
|
+
useEmailResetText?: string;
|
|
43
|
+
/** Phone reset — success screen title (defaults to "Password reset"). */
|
|
44
|
+
phoneSuccessTitle?: string;
|
|
45
|
+
/** Phone reset — success screen description. */
|
|
46
|
+
phoneSuccessDescription?: string;
|
|
21
47
|
}
|
|
22
48
|
export interface ForgotPasswordFormProps {
|
|
23
49
|
/** Callback on successful submission */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgotPasswordForm.d.ts","sourceRoot":"","sources":["../src/ForgotPasswordForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"ForgotPasswordForm.d.ts","sourceRoot":"","sources":["../src/ForgotPasswordForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAYtD,qDAAqD;AACrD,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mFAAmF;IACnF,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,2FAA2F;IAC3F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gDAAgD;IAChD,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,wBAAwB;IACxB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC5D,uCAAuC;IACvC,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAqBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,SAAS,EACT,OAAO,EACP,QAAmB,EACnB,KAA6B,EAC7B,WAAyF,EACzF,IAAI,EACJ,QAAgB,EAChB,aAAa,EAAE,QAAsB,EACrC,MAAW,GACZ,EAAE,uBAAuB,qBAyUzB"}
|
|
@@ -6,7 +6,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
* This source code is licensed under the MIT license found in the
|
|
7
7
|
* LICENSE file in the root directory of this source tree.
|
|
8
8
|
*/
|
|
9
|
-
import { useState } from 'react';
|
|
9
|
+
import { useEffect, useState } from 'react';
|
|
10
10
|
import { useAuth } from './useAuth';
|
|
11
11
|
import { AUTH_FIELD_LABEL_CLASS, AUTH_INPUT_CLASS, AUTH_LINK_CLASS, AUTH_PRIMARY_BUTTON_CLASS, AuthErrorBanner, AuthFormHeader, AuthMailIcon, AuthSpinner, } from './authStyles';
|
|
12
12
|
const DefaultLink = ({ href, className, children }) => (_jsx("a", { href: href, className: className, children: children }));
|
|
@@ -25,10 +25,46 @@ const DefaultKeyIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none",
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
export function ForgotPasswordForm({ onSuccess, onError, loginUrl = '/login', title = 'Reset your password', description = "Enter your email address and we'll send you a link to reset your password", icon, hideIcon = false, linkComponent: LinkComp = DefaultLink, labels = {}, }) {
|
|
28
|
-
const { forgotPassword, isLoading } = useAuth();
|
|
28
|
+
const { forgotPassword, isLoading, getAuthConfig, requestPhonePasswordReset, resetPasswordWithPhoneOtp, } = useAuth();
|
|
29
29
|
const [email, setEmail] = useState('');
|
|
30
30
|
const [error, setError] = useState(null);
|
|
31
31
|
const [submitted, setSubmitted] = useState(false);
|
|
32
|
+
// Phone (SMS OTP) reset branch (framework#2780). Only offered when the
|
|
33
|
+
// server reports `features.phoneNumberOtp` — the phoneNumber plugin plus a
|
|
34
|
+
// deliverable SMS service — so the link never leads to codes that can't
|
|
35
|
+
// arrive.
|
|
36
|
+
const [phoneOtpEnabled, setPhoneOtpEnabled] = useState(false);
|
|
37
|
+
const [mode, setMode] = useState('email');
|
|
38
|
+
const [phone, setPhone] = useState('');
|
|
39
|
+
const [otpCode, setOtpCode] = useState('');
|
|
40
|
+
const [newPassword, setNewPassword] = useState('');
|
|
41
|
+
const [otpSending, setOtpSending] = useState(false);
|
|
42
|
+
const [otpSent, setOtpSent] = useState(false);
|
|
43
|
+
const [otpCooldown, setOtpCooldown] = useState(0);
|
|
44
|
+
const [phoneResetDone, setPhoneResetDone] = useState(false);
|
|
45
|
+
const [resetting, setResetting] = useState(false);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
let cancelled = false;
|
|
48
|
+
Promise.resolve()
|
|
49
|
+
.then(() => getAuthConfig())
|
|
50
|
+
.then((config) => {
|
|
51
|
+
if (!cancelled)
|
|
52
|
+
setPhoneOtpEnabled(config?.features?.phoneNumberOtp === true);
|
|
53
|
+
})
|
|
54
|
+
.catch(() => {
|
|
55
|
+
// Phone reset is an enhancement — a failed config fetch just hides it.
|
|
56
|
+
});
|
|
57
|
+
return () => {
|
|
58
|
+
cancelled = true;
|
|
59
|
+
};
|
|
60
|
+
}, [getAuthConfig]);
|
|
61
|
+
// Tick the resend cooldown down once per second while it's armed.
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (otpCooldown <= 0)
|
|
64
|
+
return;
|
|
65
|
+
const timer = setTimeout(() => setOtpCooldown((s) => (s > 1 ? s - 1 : 0)), 1000);
|
|
66
|
+
return () => clearTimeout(timer);
|
|
67
|
+
}, [otpCooldown]);
|
|
32
68
|
const l = {
|
|
33
69
|
emailLabel: labels.emailLabel ?? 'Email',
|
|
34
70
|
emailPlaceholder: labels.emailPlaceholder ?? 'name@example.com',
|
|
@@ -40,6 +76,20 @@ export function ForgotPasswordForm({ onSuccess, onError, loginUrl = '/login', ti
|
|
|
40
76
|
backToSignInText: labels.backToSignInText ?? 'Back to sign in',
|
|
41
77
|
rememberPasswordText: labels.rememberPasswordText ?? 'Remember your password?',
|
|
42
78
|
signInText: labels.signInText ?? 'Sign in',
|
|
79
|
+
phoneLabel: labels.phoneLabel ?? 'Phone number',
|
|
80
|
+
phonePlaceholder: labels.phonePlaceholder ?? '+1 555 000 0000',
|
|
81
|
+
otpCodeLabel: labels.otpCodeLabel ?? 'Verification code',
|
|
82
|
+
otpCodePlaceholder: labels.otpCodePlaceholder ?? '6-digit code',
|
|
83
|
+
sendOtpButton: labels.sendOtpButton ?? 'Get code',
|
|
84
|
+
resendOtpCountdownText: labels.resendOtpCountdownText ?? 'Resend in {seconds}s',
|
|
85
|
+
newPasswordLabel: labels.newPasswordLabel ?? 'New password',
|
|
86
|
+
newPasswordPlaceholder: labels.newPasswordPlaceholder ?? 'Enter a new password',
|
|
87
|
+
resetButton: labels.resetButton ?? 'Reset Password',
|
|
88
|
+
usePhoneResetText: labels.usePhoneResetText ?? 'Reset via SMS code',
|
|
89
|
+
useEmailResetText: labels.useEmailResetText ?? 'Reset via email instead',
|
|
90
|
+
phoneSuccessTitle: labels.phoneSuccessTitle ?? 'Password reset',
|
|
91
|
+
phoneSuccessDescription: labels.phoneSuccessDescription ??
|
|
92
|
+
'Your password has been reset. You can now sign in with your new password.',
|
|
43
93
|
};
|
|
44
94
|
const handleSubmit = async (e) => {
|
|
45
95
|
e.preventDefault();
|
|
@@ -55,11 +105,62 @@ export function ForgotPasswordForm({ onSuccess, onError, loginUrl = '/login', ti
|
|
|
55
105
|
onError?.(authError);
|
|
56
106
|
}
|
|
57
107
|
};
|
|
108
|
+
/**
|
|
109
|
+
* Request a reset OTP for the entered number (framework#2780). The server
|
|
110
|
+
* always answers success (no account-existence oracle); a 429 from the
|
|
111
|
+
* per-number cooldown surfaces its honest "retry in Ns" message.
|
|
112
|
+
*/
|
|
113
|
+
const handleSendOtp = async () => {
|
|
114
|
+
if (!phone.trim() || otpSending || otpCooldown > 0)
|
|
115
|
+
return;
|
|
116
|
+
setError(null);
|
|
117
|
+
setOtpSending(true);
|
|
118
|
+
try {
|
|
119
|
+
await requestPhonePasswordReset(phone.trim());
|
|
120
|
+
setOtpSent(true);
|
|
121
|
+
setOtpCooldown(60);
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
const authError = err instanceof Error ? err : new Error(String(err));
|
|
125
|
+
setError(authError.message);
|
|
126
|
+
onError?.(authError);
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
setOtpSending(false);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
const handlePhoneReset = async (e) => {
|
|
133
|
+
e.preventDefault();
|
|
134
|
+
setError(null);
|
|
135
|
+
setResetting(true);
|
|
136
|
+
try {
|
|
137
|
+
await resetPasswordWithPhoneOtp(phone.trim(), otpCode.trim(), newPassword);
|
|
138
|
+
setPhoneResetDone(true);
|
|
139
|
+
onSuccess?.();
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
const authError = err instanceof Error ? err : new Error(String(err));
|
|
143
|
+
setError(authError.message);
|
|
144
|
+
onError?.(authError);
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
setResetting(false);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const switchMode = (next) => {
|
|
151
|
+
setMode(next);
|
|
152
|
+
setError(null);
|
|
153
|
+
};
|
|
154
|
+
if (phoneResetDone) {
|
|
155
|
+
return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-7 sm:w-[400px]", children: [_jsx(AuthFormHeader, { icon: _jsx("span", { className: "flex h-12 w-12 items-center justify-center rounded-2xl bg-emerald-500/10 text-emerald-600 ring-1 ring-emerald-500/15 dark:text-emerald-400", children: _jsx(AuthMailIcon, {}) }), title: l.phoneSuccessTitle, description: l.phoneSuccessDescription }), loginUrl && (_jsx("p", { className: "text-center text-sm text-muted-foreground", children: _jsxs(LinkComp, { href: loginUrl, className: AUTH_LINK_CLASS, children: ["\u2190 ", l.backToSignInText] }) }))] }));
|
|
156
|
+
}
|
|
58
157
|
if (submitted) {
|
|
59
158
|
const successMsg = l.successDescription.includes('{{email}}')
|
|
60
159
|
? l.successDescription.replace('{{email}}', email)
|
|
61
160
|
: `${l.successDescription} ${email}`;
|
|
62
161
|
return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-7 sm:w-[400px]", children: [_jsx(AuthFormHeader, { icon: _jsx("span", { className: "flex h-12 w-12 items-center justify-center rounded-2xl bg-emerald-500/10 text-emerald-600 ring-1 ring-emerald-500/15 dark:text-emerald-400", children: _jsx(AuthMailIcon, {}) }), title: l.successTitle, description: successMsg }), loginUrl && (_jsx("p", { className: "text-center text-sm text-muted-foreground", children: _jsxs(LinkComp, { href: loginUrl, className: AUTH_LINK_CLASS, children: ["\u2190 ", l.backToSignInText] }) }))] }));
|
|
63
162
|
}
|
|
64
|
-
return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-7 sm:w-[400px]", children: [_jsx(AuthFormHeader, { icon: hideIcon ? undefined : (icon ?? _jsx(DefaultKeyIcon, {})), title: title, description: description }), _jsxs("form", { onSubmit:
|
|
163
|
+
return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-7 sm:w-[400px]", children: [_jsx(AuthFormHeader, { icon: hideIcon ? undefined : (icon ?? _jsx(DefaultKeyIcon, {})), title: title, description: description }), mode === 'phone' ? (_jsxs("form", { onSubmit: handlePhoneReset, className: "space-y-4", children: [error && _jsx(AuthErrorBanner, { message: error }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "forgot-phone", className: AUTH_FIELD_LABEL_CLASS, children: l.phoneLabel }), _jsx("input", { id: "forgot-phone", type: "tel", placeholder: l.phonePlaceholder, value: phone, onChange: (e) => setPhone(e.target.value), required: true, autoComplete: "tel", disabled: resetting, className: AUTH_INPUT_CLASS })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "forgot-otp", className: AUTH_FIELD_LABEL_CLASS, children: l.otpCodeLabel }), _jsxs("div", { className: "flex gap-2", children: [_jsx("input", { id: "forgot-otp", type: "text", inputMode: "numeric", placeholder: l.otpCodePlaceholder, value: otpCode, onChange: (e) => setOtpCode(e.target.value), required: true, autoComplete: "one-time-code", disabled: resetting, className: AUTH_INPUT_CLASS }), _jsxs("button", { type: "button", onClick: handleSendOtp, disabled: otpSending || otpCooldown > 0 || !phone.trim() || resetting, className: "shrink-0 rounded-md border border-input bg-background px-3 py-2 text-sm font-medium transition-colors hover:bg-accent disabled:opacity-50", children: [otpSending && _jsx(AuthSpinner, {}), otpCooldown > 0
|
|
164
|
+
? l.resendOtpCountdownText.replace('{seconds}', String(otpCooldown))
|
|
165
|
+
: l.sendOtpButton] })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "forgot-new-password", className: AUTH_FIELD_LABEL_CLASS, children: l.newPasswordLabel }), _jsx("input", { id: "forgot-new-password", type: "password", placeholder: l.newPasswordPlaceholder, value: newPassword, onChange: (e) => setNewPassword(e.target.value), required: true, autoComplete: "new-password", disabled: resetting, className: AUTH_INPUT_CLASS })] }), _jsxs("button", { type: "submit", disabled: resetting || !otpSent, className: AUTH_PRIMARY_BUTTON_CLASS, children: [resetting && _jsx(AuthSpinner, {}), resetting ? l.submittingButton : l.resetButton] }), _jsx("button", { type: "button", onClick: () => switchMode('email'), className: "w-full text-center text-xs text-muted-foreground underline-offset-4 transition-colors hover:text-primary hover:underline", children: l.useEmailResetText })] })) : (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && _jsx(AuthErrorBanner, { message: error }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "forgot-email", className: AUTH_FIELD_LABEL_CLASS, children: l.emailLabel }), _jsx("input", { id: "forgot-email", type: "email", placeholder: l.emailPlaceholder, value: email, onChange: (e) => setEmail(e.target.value), required: true, autoComplete: "email", disabled: isLoading, className: AUTH_INPUT_CLASS })] }), _jsxs("button", { type: "submit", disabled: isLoading, className: AUTH_PRIMARY_BUTTON_CLASS, children: [isLoading && _jsx(AuthSpinner, {}), isLoading ? l.submittingButton : l.submitButton] }), phoneOtpEnabled && (_jsx("button", { type: "button", onClick: () => switchMode('phone'), className: "w-full text-center text-xs text-muted-foreground underline-offset-4 transition-colors hover:text-primary hover:underline", children: l.usePhoneResetText }))] })), loginUrl && (_jsxs("p", { className: "px-8 text-center text-sm text-muted-foreground", children: [l.rememberPasswordText, ' ', _jsx(LinkComp, { href: loginUrl, className: AUTH_LINK_CLASS, children: l.signInText })] }))] }));
|
|
65
166
|
}
|
package/dist/LoginForm.d.ts
CHANGED
|
@@ -30,6 +30,22 @@ export interface LoginFormLabels {
|
|
|
30
30
|
usePasswordText?: string;
|
|
31
31
|
/** Link to collapse the revealed break-glass form back to SSO-only (defaults to "Back to single sign-on"). */
|
|
32
32
|
backToSsoText?: string;
|
|
33
|
+
/** Phone-OTP mode (framework#2780) — phone field label (defaults to "Phone number"). */
|
|
34
|
+
phoneLabel?: string;
|
|
35
|
+
/** Phone-OTP mode — phone field placeholder (defaults to "+1 555 000 0000"). */
|
|
36
|
+
phonePlaceholder?: string;
|
|
37
|
+
/** Phone-OTP mode — code field label (defaults to "Verification code"). */
|
|
38
|
+
otpCodeLabel?: string;
|
|
39
|
+
/** Phone-OTP mode — code field placeholder (defaults to "6-digit code"). */
|
|
40
|
+
otpCodePlaceholder?: string;
|
|
41
|
+
/** Phone-OTP mode — "send code" button (defaults to "Get code"). */
|
|
42
|
+
sendOtpButton?: string;
|
|
43
|
+
/** Phone-OTP mode — resend countdown, `{seconds}` hole (defaults to "Resend in {seconds}s"). */
|
|
44
|
+
resendOtpCountdownText?: string;
|
|
45
|
+
/** Link that switches to phone-OTP sign-in (defaults to "Sign in with verification code"). */
|
|
46
|
+
usePhoneOtpText?: string;
|
|
47
|
+
/** Link that switches back to password sign-in (defaults to "Sign in with password instead"). */
|
|
48
|
+
usePasswordSignInText?: string;
|
|
33
49
|
/** Description shown above the form in SSO-only mode (defaults to "Sign in with your organization's single sign-on"). */
|
|
34
50
|
ssoOnlyDescription?: string;
|
|
35
51
|
}
|
package/dist/LoginForm.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoginForm.d.ts","sourceRoot":"","sources":["../src/LoginForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAYtD,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8GAA8G;IAC9G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yHAAyH;IACzH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC5D,uCAAuC;IACvC,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAsBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,OAAO,EACP,WAAyB,EACzB,iBAAsC,EACtC,KAAiC,EACjC,WAAyD,EACzD,IAAI,EACJ,QAAgB,EAChB,aAAa,EAAE,QAAsB,EACrC,MAAW,EACX,aAAa,GACd,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"LoginForm.d.ts","sourceRoot":"","sources":["../src/LoginForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAYtD,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8GAA8G;IAC9G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gGAAgG;IAChG,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,8FAA8F;IAC9F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iGAAiG;IACjG,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,yHAAyH;IACzH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;IAC5D,uCAAuC;IACvC,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAsBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,OAAO,EACP,WAAyB,EACzB,iBAAsC,EACtC,KAAiC,EACjC,WAAyD,EACzD,IAAI,EACJ,QAAgB,EAChB,aAAa,EAAE,QAAsB,EACrC,MAAW,EACX,aAAa,GACd,EAAE,cAAc,qBAsXhB"}
|
package/dist/LoginForm.js
CHANGED
|
@@ -27,10 +27,23 @@ const DefaultLockIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none"
|
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
29
|
export function LoginForm({ onSuccess, onError, registerUrl = '/register', forgotPasswordUrl = '/forgot-password', title = 'Sign in to your account', description = 'Enter your email and password to continue', icon, hideIcon = false, linkComponent: LinkComp = DefaultLink, labels = {}, errorMessages, }) {
|
|
30
|
-
const { signIn, isLoading, getAuthConfig } = useAuth();
|
|
30
|
+
const { signIn, isLoading, getAuthConfig, sendPhoneOtp, signInWithPhoneOtp } = useAuth();
|
|
31
31
|
const [email, setEmail] = useState('');
|
|
32
32
|
const [password, setPassword] = useState('');
|
|
33
33
|
const [error, setError] = useState(null);
|
|
34
|
+
// Phone-OTP sign-in (framework#2780). Only offered when the server reports
|
|
35
|
+
// `features.phoneNumberOtp` — i.e. the phoneNumber plugin is on AND a
|
|
36
|
+
// deliverable SMS service is wired — so the mode never renders as a dead
|
|
37
|
+
// entry point whose code can never arrive.
|
|
38
|
+
const [phoneOtpEnabled, setPhoneOtpEnabled] = useState(false);
|
|
39
|
+
const [mode, setMode] = useState('password');
|
|
40
|
+
const [phone, setPhone] = useState('');
|
|
41
|
+
const [otpCode, setOtpCode] = useState('');
|
|
42
|
+
const [otpSending, setOtpSending] = useState(false);
|
|
43
|
+
const [otpSent, setOtpSent] = useState(false);
|
|
44
|
+
// Seconds until another code may be requested — mirrors the server's
|
|
45
|
+
// per-number cooldown so the button doesn't invite guaranteed 429s.
|
|
46
|
+
const [otpCooldown, setOtpCooldown] = useState(0);
|
|
34
47
|
const [hasSocialProviders, setHasSocialProviders] = useState(false);
|
|
35
48
|
// Enterprise SSO is opt-in server-side (`@better-auth/sso`). Mirror the
|
|
36
49
|
// social-provider pattern below: ask the server whether SSO is wired and
|
|
@@ -55,6 +68,7 @@ export function LoginForm({ onSuccess, onError, registerUrl = '/register', forgo
|
|
|
55
68
|
if (cancelled)
|
|
56
69
|
return;
|
|
57
70
|
setSsoEnabled(config?.features?.sso === true);
|
|
71
|
+
setPhoneOtpEnabled(config?.features?.phoneNumberOtp === true);
|
|
58
72
|
setSsoEnforced(config?.features?.ssoEnforced === true ||
|
|
59
73
|
config?.emailPassword?.enabled === false);
|
|
60
74
|
})
|
|
@@ -84,12 +98,32 @@ export function LoginForm({ onSuccess, onError, registerUrl = '/register', forgo
|
|
|
84
98
|
usePasswordText: labels.usePasswordText ?? 'Use a password instead',
|
|
85
99
|
backToSsoText: labels.backToSsoText ?? 'Back to single sign-on',
|
|
86
100
|
ssoOnlyDescription: labels.ssoOnlyDescription ?? "Sign in with your organization's single sign-on",
|
|
101
|
+
phoneLabel: labels.phoneLabel ?? 'Phone number',
|
|
102
|
+
phonePlaceholder: labels.phonePlaceholder ?? '+1 555 000 0000',
|
|
103
|
+
otpCodeLabel: labels.otpCodeLabel ?? 'Verification code',
|
|
104
|
+
otpCodePlaceholder: labels.otpCodePlaceholder ?? '6-digit code',
|
|
105
|
+
sendOtpButton: labels.sendOtpButton ?? 'Get code',
|
|
106
|
+
resendOtpCountdownText: labels.resendOtpCountdownText ?? 'Resend in {seconds}s',
|
|
107
|
+
usePhoneOtpText: labels.usePhoneOtpText ?? 'Sign in with verification code',
|
|
108
|
+
usePasswordSignInText: labels.usePasswordSignInText ?? 'Sign in with password instead',
|
|
87
109
|
};
|
|
110
|
+
// Tick the resend cooldown down once per second while it's armed.
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (otpCooldown <= 0)
|
|
113
|
+
return;
|
|
114
|
+
const timer = setTimeout(() => setOtpCooldown((s) => (s > 1 ? s - 1 : 0)), 1000);
|
|
115
|
+
return () => clearTimeout(timer);
|
|
116
|
+
}, [otpCooldown]);
|
|
88
117
|
const handleSubmit = async (e) => {
|
|
89
118
|
e.preventDefault();
|
|
90
119
|
setError(null);
|
|
91
120
|
try {
|
|
92
|
-
|
|
121
|
+
if (mode === 'phone-otp') {
|
|
122
|
+
await signInWithPhoneOtp(phone.trim(), otpCode.trim());
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
await signIn(email, password);
|
|
126
|
+
}
|
|
93
127
|
onSuccess?.();
|
|
94
128
|
}
|
|
95
129
|
catch (err) {
|
|
@@ -99,6 +133,35 @@ export function LoginForm({ onSuccess, onError, registerUrl = '/register', forgo
|
|
|
99
133
|
onError?.(authError);
|
|
100
134
|
}
|
|
101
135
|
};
|
|
136
|
+
/**
|
|
137
|
+
* Request a sign-in OTP for the entered number. A 429 (per-number cooldown
|
|
138
|
+
* / hourly cap, framework#2780) surfaces the server's honest "retry in Ns"
|
|
139
|
+
* message; any other failure surfaces as-is.
|
|
140
|
+
*/
|
|
141
|
+
const handleSendOtp = async () => {
|
|
142
|
+
if (!phone.trim() || otpSending || otpCooldown > 0)
|
|
143
|
+
return;
|
|
144
|
+
setError(null);
|
|
145
|
+
setOtpSending(true);
|
|
146
|
+
try {
|
|
147
|
+
await sendPhoneOtp(phone.trim());
|
|
148
|
+
setOtpSent(true);
|
|
149
|
+
setOtpCooldown(60);
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
const authError = err instanceof Error ? err : new Error(String(err));
|
|
153
|
+
const code = authError.code;
|
|
154
|
+
setError((code && errorMessages?.[code]) || authError.message);
|
|
155
|
+
onError?.(authError);
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
setOtpSending(false);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
const switchMode = (next) => {
|
|
162
|
+
setMode(next);
|
|
163
|
+
setError(null);
|
|
164
|
+
};
|
|
102
165
|
/**
|
|
103
166
|
* Federated SSO sign-in: routes the entered email to its configured IdP
|
|
104
167
|
* (better-auth `@better-auth/sso`, by email domain) and redirects the
|
|
@@ -126,5 +189,7 @@ export function LoginForm({ onSuccess, onError, registerUrl = '/register', forgo
|
|
|
126
189
|
setError(err instanceof Error ? err.message : String(err));
|
|
127
190
|
}
|
|
128
191
|
};
|
|
129
|
-
return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-7 sm:w-[400px]", children: [_jsx(AuthFormHeader, { icon: hideIcon ? undefined : (icon ?? _jsx(DefaultLockIcon, {})), title: title, description: ssoEnforced && !showPasswordFallback ? l.ssoOnlyDescription : description }), _jsxs("div", { className: "space-y-5", children: [_jsx(SocialSignInButtons, { mode: "sign-in", onProvidersResolved: (hasProviders) => setHasSocialProviders(hasProviders) }), passwordFormVisible ? (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [hasSocialProviders && _jsx(AuthDivider, { label: l.orText }), error && _jsx(AuthErrorBanner, { message: error }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "login-
|
|
192
|
+
return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-7 sm:w-[400px]", children: [_jsx(AuthFormHeader, { icon: hideIcon ? undefined : (icon ?? _jsx(DefaultLockIcon, {})), title: title, description: ssoEnforced && !showPasswordFallback ? l.ssoOnlyDescription : description }), _jsxs("div", { className: "space-y-5", children: [_jsx(SocialSignInButtons, { mode: "sign-in", onProvidersResolved: (hasProviders) => setHasSocialProviders(hasProviders) }), passwordFormVisible ? (mode === 'phone-otp' ? (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [hasSocialProviders && _jsx(AuthDivider, { label: l.orText }), error && _jsx(AuthErrorBanner, { message: error }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "login-phone", className: AUTH_FIELD_LABEL_CLASS, children: l.phoneLabel }), _jsx("input", { id: "login-phone", type: "tel", placeholder: l.phonePlaceholder, value: phone, onChange: (e) => setPhone(e.target.value), required: true, autoComplete: "tel", disabled: isLoading, className: AUTH_INPUT_CLASS })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "login-otp", className: AUTH_FIELD_LABEL_CLASS, children: l.otpCodeLabel }), _jsxs("div", { className: "flex gap-2", children: [_jsx("input", { id: "login-otp", type: "text", inputMode: "numeric", placeholder: l.otpCodePlaceholder, value: otpCode, onChange: (e) => setOtpCode(e.target.value), required: true, autoComplete: "one-time-code", disabled: isLoading, className: AUTH_INPUT_CLASS }), _jsxs("button", { type: "button", onClick: handleSendOtp, disabled: otpSending || otpCooldown > 0 || !phone.trim() || isLoading, className: "shrink-0 rounded-md border border-input bg-background px-3 py-2 text-sm font-medium transition-colors hover:bg-accent disabled:opacity-50", children: [otpSending && _jsx(AuthSpinner, {}), otpCooldown > 0
|
|
193
|
+
? l.resendOtpCountdownText.replace('{seconds}', String(otpCooldown))
|
|
194
|
+
: l.sendOtpButton] })] })] }), _jsxs("button", { type: "submit", disabled: isLoading || !otpSent, className: AUTH_PRIMARY_BUTTON_CLASS, children: [isLoading && _jsx(AuthSpinner, {}), isLoading ? l.submittingButton : l.submitButton] }), _jsx("button", { type: "button", onClick: () => switchMode('password'), className: "w-full text-center text-xs text-muted-foreground underline-offset-4 transition-colors hover:text-primary hover:underline", children: l.usePasswordSignInText })] })) : (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [hasSocialProviders && _jsx(AuthDivider, { label: l.orText }), error && _jsx(AuthErrorBanner, { message: error }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "login-email", className: AUTH_FIELD_LABEL_CLASS, children: l.emailLabel }), _jsx("input", { id: "login-email", type: "email", placeholder: l.emailPlaceholder, value: email, onChange: (e) => setEmail(e.target.value), required: true, autoComplete: "email", disabled: isLoading, className: AUTH_INPUT_CLASS })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("label", { htmlFor: "login-password", className: AUTH_FIELD_LABEL_CLASS, children: l.passwordLabel }), forgotPasswordUrl && (_jsx(LinkComp, { href: forgotPasswordUrl, className: "text-xs text-muted-foreground underline-offset-4 transition-colors hover:text-primary hover:underline", children: l.forgotPasswordText }))] }), _jsx("input", { id: "login-password", type: "password", placeholder: l.passwordPlaceholder, value: password, onChange: (e) => setPassword(e.target.value), required: true, autoComplete: "current-password", disabled: isLoading, className: AUTH_INPUT_CLASS })] }), _jsxs("button", { type: "submit", disabled: isLoading, className: AUTH_PRIMARY_BUTTON_CLASS, children: [isLoading && _jsx(AuthSpinner, {}), isLoading ? l.submittingButton : l.submitButton] }), ssoEnabled && (_jsx("button", { type: "button", onClick: handleSso, disabled: isLoading, className: "flex w-full items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent disabled:opacity-50", children: l.ssoButton })), phoneOtpEnabled && (_jsx("button", { type: "button", onClick: () => switchMode('phone-otp'), className: "w-full text-center text-xs text-muted-foreground underline-offset-4 transition-colors hover:text-primary hover:underline", children: l.usePhoneOtpText })), ssoEnforced && showPasswordFallback && (_jsx("button", { type: "button", onClick: () => setShowPasswordFallback(false), className: "w-full text-center text-xs text-muted-foreground underline-offset-4 transition-colors hover:text-primary hover:underline", children: l.backToSsoText }))] }))) : (_jsxs("div", { className: "space-y-4", children: [error && _jsx(AuthErrorBanner, { message: error }), _jsx("button", { type: "button", onClick: () => setShowPasswordFallback(true), className: "w-full text-center text-xs text-muted-foreground underline-offset-4 transition-colors hover:text-primary hover:underline", children: l.usePasswordText })] }))] }), registerUrl && !ssoEnforced && (_jsxs("p", { className: "px-8 text-center text-sm text-muted-foreground", children: [l.noAccountText, ' ', _jsx(LinkComp, { href: registerUrl, className: AUTH_LINK_CLASS, children: l.signUpText })] }))] }));
|
|
130
195
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createAuthClient.d.ts","sourceRoot":"","sources":["../src/createAuthClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,UAAU,EAAE,gBAAgB,EAE7B,MAAM,SAAS,CAAC;AAIjB;;;GAGG;AACH,eAAO,MAAM,YAAY;kBACD,MAAM,GAAG,IAAI;WAE5B,MAAM,GAAG,IAAI;eAST,MAAM,GAAG,IAAI;aASf,IAAI;CAQd,CAAC;AAmHF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"createAuthClient.d.ts","sourceRoot":"","sources":["../src/createAuthClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,UAAU,EAAE,gBAAgB,EAE7B,MAAM,SAAS,CAAC;AAIjB;;;GAGG;AACH,eAAO,MAAM,YAAY;kBACD,MAAM,GAAG,IAAI;WAE5B,MAAM,GAAG,IAAI;eAST,MAAM,GAAG,IAAI;aASf,IAAI;CAQd,CAAC;AAmHF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CA2iBrE"}
|
package/dist/createAuthClient.js
CHANGED
|
@@ -173,6 +173,29 @@ export function createAuthClient(config) {
|
|
|
173
173
|
// than the runtime JSON the server actually sends (e.g. `session` on signIn).
|
|
174
174
|
// We deliberately cast through `unknown` to bridge from better-auth types
|
|
175
175
|
// to the ObjectUI AuthClient contract.
|
|
176
|
+
/**
|
|
177
|
+
* POST one of the phoneNumber plugin's endpoints (framework#2780) and
|
|
178
|
+
* return the parsed JSON. Throws an Error carrying the better-auth `code`
|
|
179
|
+
* and HTTP `status` so the forms can special-case the per-number cooldown
|
|
180
|
+
* (429 TOO_MANY_REQUESTS) with an honest "retry in Ns" message.
|
|
181
|
+
*/
|
|
182
|
+
async function postPhoneNumberEndpoint(path, body) {
|
|
183
|
+
const response = await bearerFetch(`${origin}${basePath}${path}`, {
|
|
184
|
+
method: 'POST',
|
|
185
|
+
headers: { 'Content-Type': 'application/json' },
|
|
186
|
+
credentials: 'include',
|
|
187
|
+
body: JSON.stringify(body),
|
|
188
|
+
});
|
|
189
|
+
const payload = (await response.json().catch(() => ({})));
|
|
190
|
+
if (!response.ok) {
|
|
191
|
+
const err = new Error(payload?.message ?? `Auth request failed with status ${response.status}`);
|
|
192
|
+
if (payload?.code)
|
|
193
|
+
err.code = payload.code;
|
|
194
|
+
err.status = response.status;
|
|
195
|
+
throw err;
|
|
196
|
+
}
|
|
197
|
+
return payload ?? {};
|
|
198
|
+
}
|
|
176
199
|
return {
|
|
177
200
|
async signIn(credentials) {
|
|
178
201
|
const { data, error } = await betterAuth.signIn.email({
|
|
@@ -313,6 +336,35 @@ export function createAuthClient(config) {
|
|
|
313
336
|
throw new Error(error.message ?? `Auth request failed with status ${error.status}`);
|
|
314
337
|
}
|
|
315
338
|
},
|
|
339
|
+
// --- Phone-number OTP (framework#2780) -------------------------------
|
|
340
|
+
// The better-auth phoneNumber plugin's endpoints, called directly (the
|
|
341
|
+
// phoneNumberClient plugin adds nothing we need beyond these four POSTs,
|
|
342
|
+
// and direct fetch keeps the error `code`/status handy for the cooldown
|
|
343
|
+
// 429 UX). Server availability is gated by `features.phoneNumberOtp`.
|
|
344
|
+
async sendPhoneOtp(phoneNumber) {
|
|
345
|
+
await postPhoneNumberEndpoint('/phone-number/send-otp', { phoneNumber });
|
|
346
|
+
},
|
|
347
|
+
async signInWithPhoneOtp(phoneNumber, code) {
|
|
348
|
+
const payload = await postPhoneNumberEndpoint('/phone-number/verify', { phoneNumber, code });
|
|
349
|
+
// Response: `{ status, token: string|null, user: object|null }` —
|
|
350
|
+
// token/user are null when the number belongs to no account (the
|
|
351
|
+
// endpoint also serves the change-phone verification flow).
|
|
352
|
+
const token = typeof payload.token === 'string' ? payload.token : undefined;
|
|
353
|
+
const user = (payload.user ?? null);
|
|
354
|
+
if (!token || !user) {
|
|
355
|
+
throw new Error('No account is registered for this phone number.');
|
|
356
|
+
}
|
|
357
|
+
TokenStorage.set(token);
|
|
358
|
+
return { user, session: { token } };
|
|
359
|
+
},
|
|
360
|
+
async requestPhonePasswordReset(phoneNumber) {
|
|
361
|
+
// Always answers `{status:true}` (no account-existence oracle) — the
|
|
362
|
+
// OTP only arrives when the number belongs to an account.
|
|
363
|
+
await postPhoneNumberEndpoint('/phone-number/request-password-reset', { phoneNumber });
|
|
364
|
+
},
|
|
365
|
+
async resetPasswordWithPhoneOtp(phoneNumber, otp, newPassword) {
|
|
366
|
+
await postPhoneNumberEndpoint('/phone-number/reset-password', { phoneNumber, otp, newPassword });
|
|
367
|
+
},
|
|
316
368
|
async changePassword(currentPassword, newPassword, options) {
|
|
317
369
|
const fn = betterAuth.changePassword;
|
|
318
370
|
if (typeof fn !== 'function') {
|
package/dist/types.d.ts
CHANGED
|
@@ -121,6 +121,26 @@ export interface AuthPublicConfig {
|
|
|
121
121
|
* invite-accept) still work — only fresh creation is forbidden.
|
|
122
122
|
*/
|
|
123
123
|
multiOrgEnabled?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Phone-number sign-in enabled server-side (better-auth phoneNumber
|
|
126
|
+
* plugin — phone + password, framework#2766).
|
|
127
|
+
*/
|
|
128
|
+
phoneNumber?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Phone-number OTP sign-in / self-service reset available — requires the
|
|
131
|
+
* phoneNumber plugin plus a deliverable SMS service (framework#2780).
|
|
132
|
+
* Gates the "sign in with verification code" mode and the phone branch
|
|
133
|
+
* of the forgot-password form; falsy hides them so we never render an
|
|
134
|
+
* entry point whose code can never arrive.
|
|
135
|
+
*/
|
|
136
|
+
phoneNumberOtp?: boolean;
|
|
137
|
+
/**
|
|
138
|
+
* better-auth admin plugin mounted server-side (`auth.plugins.admin`;
|
|
139
|
+
* SCIM forces it on). Gates the admin user-management surfaces — the
|
|
140
|
+
* sys_user create/set-password actions and the identity import wizard
|
|
141
|
+
* entry (framework#2766 / #2782).
|
|
142
|
+
*/
|
|
143
|
+
admin?: boolean;
|
|
124
144
|
};
|
|
125
145
|
}
|
|
126
146
|
/** Options when initiating a third-party sign-in */
|
|
@@ -158,6 +178,17 @@ export interface AuthClient {
|
|
|
158
178
|
sendVerificationEmail: (email: string, callbackURL?: string) => Promise<void>;
|
|
159
179
|
/** Reset password with token */
|
|
160
180
|
resetPassword: (token: string, newPassword: string) => Promise<void>;
|
|
181
|
+
/** framework#2780 — request a sign-in/verification OTP SMS for the phone number. */
|
|
182
|
+
sendPhoneOtp: (phoneNumber: string) => Promise<void>;
|
|
183
|
+
/** framework#2780 — verify a phone OTP; signs in the number's user. */
|
|
184
|
+
signInWithPhoneOtp: (phoneNumber: string, code: string) => Promise<{
|
|
185
|
+
user: AuthUser;
|
|
186
|
+
session: AuthSession;
|
|
187
|
+
}>;
|
|
188
|
+
/** framework#2780 — request a password-reset OTP SMS for the phone number. */
|
|
189
|
+
requestPhonePasswordReset: (phoneNumber: string) => Promise<void>;
|
|
190
|
+
/** framework#2780 — reset the password using a phone OTP. */
|
|
191
|
+
resetPasswordWithPhoneOtp: (phoneNumber: string, otp: string, newPassword: string) => Promise<void>;
|
|
161
192
|
/** Change password (requires current password). For users who already have a local password. */
|
|
162
193
|
changePassword: (currentPassword: string, newPassword: string, options?: {
|
|
163
194
|
revokeOtherSessions?: boolean;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/useAuth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../src/useAuth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE/D;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,IAAI,gBAAgB,
|
|
1
|
+
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../src/useAuth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE/D;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,IAAI,gBAAgB,CA0D1C"}
|
package/dist/useAuth.js
CHANGED
|
@@ -40,6 +40,10 @@ export function useAuth() {
|
|
|
40
40
|
forgotPassword: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
|
|
41
41
|
sendVerificationEmail: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
|
|
42
42
|
resetPassword: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
|
|
43
|
+
sendPhoneOtp: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
|
|
44
|
+
signInWithPhoneOtp: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
|
|
45
|
+
requestPhonePasswordReset: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
|
|
46
|
+
resetPasswordWithPhoneOtp: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
|
|
43
47
|
changePassword: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
|
|
44
48
|
remediationRequired: null,
|
|
45
49
|
setRemediationRequired: () => { },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "13.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Authentication system for Object UI with AuthProvider, useAuth hook, AuthGuard, and form components.",
|
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
"react": "^18.0.0 || ^19.0.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"better-auth": "^1.6.
|
|
34
|
-
"@object-ui/types": "
|
|
33
|
+
"better-auth": "^1.6.23",
|
|
34
|
+
"@object-ui/types": "13.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/react": "19.2.17",
|
|
38
38
|
"react": "19.2.7",
|
|
39
39
|
"typescript": "^6.0.3",
|
|
40
|
-
"vitest": "^4.1.
|
|
40
|
+
"vitest": "^4.1.10"
|
|
41
41
|
},
|
|
42
42
|
"keywords": [
|
|
43
43
|
"objectui",
|