@better-auth/passkey 1.5.7-beta.1 → 1.6.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/dist/client.d.mts CHANGED
@@ -1,4 +1,5 @@
1
- import { a as WebAuthnChallengeValue, i as PasskeyOptions, n as PASSKEY_ERROR_CODES, r as Passkey, t as passkey } from "./index-BfRDyiNp.mjs";
1
+ import { a as PasskeyExtensionsResolver, c as PasskeyRegistrationUser, i as PasskeyAuthenticationOptions, l as WebAuthnChallengeValue, n as PASSKEY_ERROR_CODES, o as PasskeyOptions, r as Passkey, s as PasskeyRegistrationOptions, t as passkey } from "./index-DD5Lute1.mjs";
2
+ import { AuthenticationExtensionsClientInputs, AuthenticationExtensionsClientOutputs, AuthenticationResponseJSON, RegistrationResponseJSON } from "@simplewebauthn/server";
2
3
  import * as better_auth_client0 from "better-auth/client";
3
4
  import * as nanostores from "nanostores";
4
5
  import { atom } from "nanostores";
@@ -22,6 +23,8 @@ declare const getPasskeyActions: ($fetch: BetterFetch, {
22
23
  */
23
24
  passkey: (opts?: {
24
25
  autoFill?: boolean;
26
+ extensions?: AuthenticationExtensionsClientInputs;
27
+ returnWebAuthnResponse?: boolean;
25
28
  fetchOptions?: ClientFetchOption;
26
29
  } | undefined, options?: ClientFetchOption | undefined) => Promise<{
27
30
  data: null;
@@ -36,11 +39,32 @@ declare const getPasskeyActions: ($fetch: BetterFetch, {
36
39
  user: User;
37
40
  };
38
41
  error: null;
42
+ } | {
43
+ webauthn: {
44
+ response: AuthenticationResponseJSON;
45
+ clientExtensionResults: AuthenticationExtensionsClientOutputs;
46
+ };
47
+ data: null;
48
+ error: {
49
+ message?: string | undefined;
50
+ status: number;
51
+ statusText: string;
52
+ };
53
+ } | {
54
+ webauthn: {
55
+ response: AuthenticationResponseJSON;
56
+ clientExtensionResults: AuthenticationExtensionsClientOutputs;
57
+ };
58
+ data: {
59
+ session: Session;
60
+ user: User;
61
+ };
62
+ error: null;
39
63
  } | {
40
64
  data: null;
41
65
  error: {
42
66
  code: string;
43
- message: better_auth0.RawError<"AUTH_CANCELLED">;
67
+ message: string;
44
68
  status: number;
45
69
  statusText: string;
46
70
  };
@@ -62,12 +86,24 @@ declare const getPasskeyActions: ($fetch: BetterFetch, {
62
86
  * platform and cross-platform allowed, with platform preferred.
63
87
  */
64
88
  authenticatorAttachment?: "platform" | "cross-platform";
89
+ /**
90
+ * Optional context for passkey-first registration flows.
91
+ */
92
+ context?: string | null;
93
+ /**
94
+ * Optional WebAuthn extensions to include during registration.
95
+ */
96
+ extensions?: AuthenticationExtensionsClientInputs;
65
97
  /**
66
98
  * Try to silently create a passkey with the password manager that the user just signed
67
99
  * in with.
68
100
  * @default false
69
101
  */
70
102
  useAutoRegister?: boolean;
103
+ /**
104
+ * Return WebAuthn response and extension results.
105
+ */
106
+ returnWebAuthnResponse?: boolean;
71
107
  } | undefined, fetchOpts?: ClientFetchOption | undefined) => Promise<{
72
108
  data: null;
73
109
  error: {
@@ -79,26 +115,17 @@ declare const getPasskeyActions: ($fetch: BetterFetch, {
79
115
  data: Passkey;
80
116
  error: null;
81
117
  } | {
82
- data: null;
83
- error: {
84
- code: "ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED";
85
- message: better_auth0.RawError<"PREVIOUSLY_REGISTERED">;
86
- status: number;
87
- statusText: string;
88
- };
89
- } | {
90
- data: null;
91
- error: {
92
- code: "ERROR_CEREMONY_ABORTED";
93
- message: better_auth0.RawError<"REGISTRATION_CANCELLED">;
94
- status: number;
95
- statusText: string;
118
+ webauthn: {
119
+ response: RegistrationResponseJSON;
120
+ clientExtensionResults: AuthenticationExtensionsClientOutputs;
96
121
  };
122
+ data: Passkey;
123
+ error: null;
97
124
  } | {
98
125
  data: null;
99
126
  error: {
100
127
  code: string;
101
- message: string | better_auth0.RawError<"UNKNOWN_ERROR">;
128
+ message: string;
102
129
  status: number;
103
130
  statusText: string;
104
131
  };
@@ -113,6 +140,7 @@ declare const getPasskeyActions: ($fetch: BetterFetch, {
113
140
  };
114
141
  declare const passkeyClient: () => {
115
142
  id: "passkey";
143
+ version: string;
116
144
  $InferServerPlugin: ReturnType<typeof passkey>;
117
145
  getActions: ($fetch: BetterFetch, $store: ClientStore) => {
118
146
  signIn: {
@@ -121,6 +149,8 @@ declare const passkeyClient: () => {
121
149
  */
122
150
  passkey: (opts?: {
123
151
  autoFill?: boolean;
152
+ extensions?: AuthenticationExtensionsClientInputs;
153
+ returnWebAuthnResponse?: boolean;
124
154
  fetchOptions?: ClientFetchOption;
125
155
  } | undefined, options?: ClientFetchOption | undefined) => Promise<{
126
156
  data: null;
@@ -135,11 +165,32 @@ declare const passkeyClient: () => {
135
165
  user: User;
136
166
  };
137
167
  error: null;
168
+ } | {
169
+ webauthn: {
170
+ response: AuthenticationResponseJSON;
171
+ clientExtensionResults: AuthenticationExtensionsClientOutputs;
172
+ };
173
+ data: null;
174
+ error: {
175
+ message?: string | undefined;
176
+ status: number;
177
+ statusText: string;
178
+ };
179
+ } | {
180
+ webauthn: {
181
+ response: AuthenticationResponseJSON;
182
+ clientExtensionResults: AuthenticationExtensionsClientOutputs;
183
+ };
184
+ data: {
185
+ session: Session;
186
+ user: User;
187
+ };
188
+ error: null;
138
189
  } | {
139
190
  data: null;
140
191
  error: {
141
192
  code: string;
142
- message: better_auth0.RawError<"AUTH_CANCELLED">;
193
+ message: string;
143
194
  status: number;
144
195
  statusText: string;
145
196
  };
@@ -161,12 +212,24 @@ declare const passkeyClient: () => {
161
212
  * platform and cross-platform allowed, with platform preferred.
162
213
  */
163
214
  authenticatorAttachment?: "platform" | "cross-platform";
215
+ /**
216
+ * Optional context for passkey-first registration flows.
217
+ */
218
+ context?: string | null;
219
+ /**
220
+ * Optional WebAuthn extensions to include during registration.
221
+ */
222
+ extensions?: AuthenticationExtensionsClientInputs;
164
223
  /**
165
224
  * Try to silently create a passkey with the password manager that the user just signed
166
225
  * in with.
167
226
  * @default false
168
227
  */
169
228
  useAutoRegister?: boolean;
229
+ /**
230
+ * Return WebAuthn response and extension results.
231
+ */
232
+ returnWebAuthnResponse?: boolean;
170
233
  } | undefined, fetchOpts?: ClientFetchOption | undefined) => Promise<{
171
234
  data: null;
172
235
  error: {
@@ -178,26 +241,17 @@ declare const passkeyClient: () => {
178
241
  data: Passkey;
179
242
  error: null;
180
243
  } | {
181
- data: null;
182
- error: {
183
- code: "ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED";
184
- message: better_auth0.RawError<"PREVIOUSLY_REGISTERED">;
185
- status: number;
186
- statusText: string;
187
- };
188
- } | {
189
- data: null;
190
- error: {
191
- code: "ERROR_CEREMONY_ABORTED";
192
- message: better_auth0.RawError<"REGISTRATION_CANCELLED">;
193
- status: number;
194
- statusText: string;
244
+ webauthn: {
245
+ response: RegistrationResponseJSON;
246
+ clientExtensionResults: AuthenticationExtensionsClientOutputs;
195
247
  };
248
+ data: Passkey;
249
+ error: null;
196
250
  } | {
197
251
  data: null;
198
252
  error: {
199
253
  code: string;
200
- message: string | better_auth0.RawError<"UNKNOWN_ERROR">;
254
+ message: string;
201
255
  status: number;
202
256
  statusText: string;
203
257
  };
@@ -237,8 +291,10 @@ declare const passkeyClient: () => {
237
291
  REGISTRATION_CANCELLED: better_auth0.RawError<"REGISTRATION_CANCELLED">;
238
292
  AUTH_CANCELLED: better_auth0.RawError<"AUTH_CANCELLED">;
239
293
  UNKNOWN_ERROR: better_auth0.RawError<"UNKNOWN_ERROR">;
294
+ SESSION_REQUIRED: better_auth0.RawError<"SESSION_REQUIRED">;
295
+ RESOLVE_USER_REQUIRED: better_auth0.RawError<"RESOLVE_USER_REQUIRED">;
296
+ RESOLVED_USER_INVALID: better_auth0.RawError<"RESOLVED_USER_INVALID">;
240
297
  };
241
298
  };
242
299
  //#endregion
243
- export { PASSKEY_ERROR_CODES, Passkey, PasskeyOptions, WebAuthnChallengeValue, getPasskeyActions, passkeyClient };
244
- //# sourceMappingURL=client.d.mts.map
300
+ export { PASSKEY_ERROR_CODES, Passkey, PasskeyAuthenticationOptions, PasskeyExtensionsResolver, PasskeyOptions, PasskeyRegistrationOptions, PasskeyRegistrationUser, WebAuthnChallengeValue, getPasskeyActions, passkeyClient };
package/dist/client.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as PASSKEY_ERROR_CODES } from "./error-codes-BwAsYefH.mjs";
1
+ import { n as PASSKEY_ERROR_CODES, t as PACKAGE_VERSION } from "./version-DSSbBvqx.mjs";
2
2
  import { WebAuthnError, startAuthentication, startRegistration } from "@simplewebauthn/browser";
3
3
  import { useAuthQuery } from "better-auth/client";
4
4
  import { atom } from "nanostores";
@@ -11,11 +11,20 @@ const getPasskeyActions = ($fetch, { $listPasskeys, $store }) => {
11
11
  });
12
12
  if (!response.data) return response;
13
13
  try {
14
+ const mergedExtensions = response.data.extensions || opts?.extensions ? {
15
+ ...response.data.extensions || {},
16
+ ...opts?.extensions || {}
17
+ } : void 0;
18
+ const res = await startAuthentication({
19
+ optionsJSON: {
20
+ ...response.data,
21
+ extensions: mergedExtensions
22
+ },
23
+ useBrowserAutofill: opts?.autoFill
24
+ });
25
+ const { clientExtensionResults, ...responseBody } = res;
14
26
  const verified = await $fetch("/passkey/verify-authentication", {
15
- body: { response: await startAuthentication({
16
- optionsJSON: response.data,
17
- useBrowserAutofill: opts?.autoFill
18
- }) },
27
+ body: { response: responseBody },
19
28
  ...opts?.fetchOptions,
20
29
  ...options,
21
30
  method: "POST",
@@ -23,6 +32,13 @@ const getPasskeyActions = ($fetch, { $listPasskeys, $store }) => {
23
32
  });
24
33
  $listPasskeys.set(Math.random());
25
34
  $store.notify("$sessionSignal");
35
+ if (opts?.returnWebAuthnResponse) return {
36
+ ...verified,
37
+ webauthn: {
38
+ response: res,
39
+ clientExtensionResults
40
+ }
41
+ };
26
42
  return verified;
27
43
  } catch (err) {
28
44
  console.error(`[Better Auth] Error verifying passkey`, err);
@@ -30,7 +46,7 @@ const getPasskeyActions = ($fetch, { $listPasskeys, $store }) => {
30
46
  data: null,
31
47
  error: {
32
48
  code: "AUTH_CANCELLED",
33
- message: PASSKEY_ERROR_CODES.AUTH_CANCELLED,
49
+ message: PASSKEY_ERROR_CODES.AUTH_CANCELLED.message,
34
50
  status: 400,
35
51
  statusText: "BAD_REQUEST"
36
52
  }
@@ -42,21 +58,30 @@ const getPasskeyActions = ($fetch, { $listPasskeys, $store }) => {
42
58
  method: "GET",
43
59
  query: {
44
60
  ...opts?.authenticatorAttachment && { authenticatorAttachment: opts.authenticatorAttachment },
45
- ...opts?.name && { name: opts.name }
61
+ ...opts?.name && { name: opts.name },
62
+ ...opts?.context && { context: opts.context }
46
63
  },
47
64
  throw: false
48
65
  });
49
66
  if (!options.data) return options;
50
67
  try {
68
+ const mergedExtensions = options.data.extensions || opts?.extensions ? {
69
+ ...options.data.extensions || {},
70
+ ...opts?.extensions || {}
71
+ } : void 0;
51
72
  const res = await startRegistration({
52
- optionsJSON: options.data,
73
+ optionsJSON: {
74
+ ...options.data,
75
+ extensions: mergedExtensions
76
+ },
53
77
  useAutoRegister: opts?.useAutoRegister
54
78
  });
79
+ const { clientExtensionResults, ...responseBody } = res;
55
80
  const verified = await $fetch("/passkey/verify-registration", {
56
81
  ...opts?.fetchOptions,
57
82
  ...fetchOpts,
58
83
  body: {
59
- response: res,
84
+ response: responseBody,
60
85
  name: opts?.name
61
86
  },
62
87
  method: "POST",
@@ -64,6 +89,13 @@ const getPasskeyActions = ($fetch, { $listPasskeys, $store }) => {
64
89
  });
65
90
  if (!verified.data) return verified;
66
91
  $listPasskeys.set(Math.random());
92
+ if (opts?.returnWebAuthnResponse) return {
93
+ ...verified,
94
+ webauthn: {
95
+ response: res,
96
+ clientExtensionResults
97
+ }
98
+ };
67
99
  return verified;
68
100
  } catch (e) {
69
101
  if (e instanceof WebAuthnError) {
@@ -71,7 +103,7 @@ const getPasskeyActions = ($fetch, { $listPasskeys, $store }) => {
71
103
  data: null,
72
104
  error: {
73
105
  code: e.code,
74
- message: PASSKEY_ERROR_CODES.PREVIOUSLY_REGISTERED,
106
+ message: PASSKEY_ERROR_CODES.PREVIOUSLY_REGISTERED.message,
75
107
  status: 400,
76
108
  statusText: "BAD_REQUEST"
77
109
  }
@@ -80,7 +112,7 @@ const getPasskeyActions = ($fetch, { $listPasskeys, $store }) => {
80
112
  data: null,
81
113
  error: {
82
114
  code: e.code,
83
- message: PASSKEY_ERROR_CODES.REGISTRATION_CANCELLED,
115
+ message: PASSKEY_ERROR_CODES.REGISTRATION_CANCELLED.message,
84
116
  status: 400,
85
117
  statusText: "BAD_REQUEST"
86
118
  }
@@ -99,7 +131,7 @@ const getPasskeyActions = ($fetch, { $listPasskeys, $store }) => {
99
131
  data: null,
100
132
  error: {
101
133
  code: "UNKNOWN_ERROR",
102
- message: e instanceof Error ? e.message : PASSKEY_ERROR_CODES.UNKNOWN_ERROR,
134
+ message: e instanceof Error ? e.message : PASSKEY_ERROR_CODES.UNKNOWN_ERROR.message,
103
135
  status: 500,
104
136
  statusText: "INTERNAL_SERVER_ERROR"
105
137
  }
@@ -116,6 +148,7 @@ const passkeyClient = () => {
116
148
  const $listPasskeys = atom();
117
149
  return {
118
150
  id: "passkey",
151
+ version: PACKAGE_VERSION,
119
152
  $InferServerPlugin: {},
120
153
  getActions: ($fetch, $store) => getPasskeyActions($fetch, {
121
154
  $listPasskeys,
@@ -145,5 +178,3 @@ const passkeyClient = () => {
145
178
  };
146
179
  //#endregion
147
180
  export { PASSKEY_ERROR_CODES, getPasskeyActions, passkeyClient };
148
-
149
- //# sourceMappingURL=client.mjs.map