Skip to content

Commit 145308b

Browse files
committed
Merge branch 'feat/webauthn-credential-mng-methods' into feat/webauthn-mfa
2 parents 309a50f + a13b2f7 commit 145308b

File tree

10 files changed

+223
-18
lines changed

10 files changed

+223
-18
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
- Add `webauthn` as a secondary factor in MFA
1111

12+
## [0.50] - 2025-08-11
13+
14+
- Add WebAuthn credential management methods: `listCredentials`, `removeCredential`
15+
- Added `createAndRegisterCredentialWithUser` method that creates and registers a credential with a user
16+
- The `registerCredential` method has been renamed to `createCredential`. This was done to better represent the creation of a credential and not the actual registration of it with the backend API. The new `registerCredential` implementation now calls the backend API.
17+
1218
## [0.49.1] - 2025-03-27
1319

1420
- Fixed a type issue making the WebauthnPreBuitlUI not produce a type error when added to the prebuiltUIList

lib/build/recipe/webauthn/index.d.ts

Lines changed: 105 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/build/recipe/webauthn/types.d.ts

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/build/webauthn.js

Lines changed: 23 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/build/webauthnprebuiltui.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/ts/recipe/webauthn/components/features/recoverAccountWithToken/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export const RecoverAccountUsingToken: React.FC<RecoverAccountWithTokenProps> =
131131

132132
// Use the register options to register the credential and recover the account.
133133
// We should have received a valid registration options response.
134-
const registerCredentialResponse = await props.recipe.webJSRecipe.registerCredential({
134+
const registerCredentialResponse = await props.recipe.webJSRecipe.createCredential({
135135
registrationOptions: registerOptions,
136136
userContext: props.userContext,
137137
});

lib/ts/recipe/webauthn/index.ts

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ export default class Wrapper {
249249
return Webauthn.getInstanceOrThrow().webJSRecipe.recoverAccount(input);
250250
}
251251

252-
static registerCredential(input: {
252+
static createCredential(input: {
253253
registrationOptions: Omit<RegistrationOptions, "fetchResponse" | "status">;
254254
userContext: any;
255255
}): Promise<
@@ -269,7 +269,7 @@ export default class Wrapper {
269269
error: any;
270270
}
271271
> {
272-
return Webauthn.getInstanceOrThrow().webJSRecipe.registerCredential(input);
272+
return Webauthn.getInstanceOrThrow().webJSRecipe.createCredential(input);
273273
}
274274

275275
static authenticateCredential(input: {
@@ -446,6 +446,69 @@ export default class Wrapper {
446446
return Webauthn.getInstanceOrThrow().webJSRecipe.registerCredentialWithRecoverAccount(input);
447447
}
448448

449+
static listCredentials(input: { options?: RecipeFunctionOptions; userContext: any }): Promise<
450+
| {
451+
status: "OK";
452+
credentials: {
453+
webauthnCredentialId: string;
454+
relyingPartyId: string;
455+
recipeUserId: string;
456+
createdAt: number;
457+
}[];
458+
}
459+
| GeneralErrorResponse
460+
> {
461+
return Webauthn.getInstanceOrThrow().webJSRecipe.listCredentials(input);
462+
}
463+
464+
static removeCredential(input: {
465+
webauthnCredentialId: string;
466+
userContext: any;
467+
}): Promise<
468+
{ status: "OK" } | GeneralErrorResponse | { status: "CREDENTIAL_NOT_FOUND_ERROR"; fetchResponse: Response }
469+
> {
470+
return Webauthn.getInstanceOrThrow().webJSRecipe.removeCredential(input);
471+
}
472+
473+
static createAndRegisterCredentialForSessionUser(input: {
474+
recipeUserId: string;
475+
email: string;
476+
options?: RecipeFunctionOptions;
477+
userContext: any;
478+
}): Promise<
479+
| { status: "OK" }
480+
| GeneralErrorResponse
481+
| { status: "REGISTER_CREDENTIAL_NOT_ALLOWED"; reason?: string }
482+
| { status: "INVALID_EMAIL_ERROR"; err: string }
483+
| { status: "INVALID_CREDENTIALS_ERROR" }
484+
| { status: "OPTIONS_NOT_FOUND_ERROR" }
485+
| { status: "INVALID_OPTIONS_ERROR" }
486+
| { status: "INVALID_AUTHENTICATOR_ERROR"; reason?: string }
487+
| { status: "AUTHENTICATOR_ALREADY_REGISTERED" }
488+
| { status: "FAILED_TO_REGISTER_USER"; error: any }
489+
| { status: "WEBAUTHN_NOT_SUPPORTED"; error: any }
490+
> {
491+
return Webauthn.getInstanceOrThrow().webJSRecipe.createAndRegisterCredentialForSessionUser(input);
492+
}
493+
494+
static registerCredential(input: {
495+
recipeUserId: string;
496+
webauthnGeneratedOptionsId: string;
497+
credential: RegistrationResponseJSON;
498+
options?: RecipeFunctionOptions;
499+
userContext: any;
500+
}): Promise<
501+
| { status: "OK" }
502+
| GeneralErrorResponse
503+
| { status: "REGISTER_CREDENTIAL_NOT_ALLOWED"; reason?: string }
504+
| { status: "INVALID_CREDENTIALS_ERROR" }
505+
| { status: "OPTIONS_NOT_FOUND_ERROR" }
506+
| { status: "INVALID_OPTIONS_ERROR" }
507+
| { status: "INVALID_AUTHENTICATOR_ERROR"; reason?: string }
508+
> {
509+
return Webauthn.getInstanceOrThrow().webJSRecipe.registerCredential(input);
510+
}
511+
449512
static doesBrowserSupportWebAuthn(input: { userContext: any }): Promise<
450513
| {
451514
status: "OK";
@@ -471,11 +534,15 @@ const signIn = Wrapper.signIn;
471534
const getEmailExists = Wrapper.getEmailExists;
472535
const generateRecoverAccountToken = Wrapper.generateRecoverAccountToken;
473536
const recoverAccount = Wrapper.recoverAccount;
474-
const registerCredential = Wrapper.registerCredential;
537+
const createCredential = Wrapper.createCredential;
475538
const authenticateCredential = Wrapper.authenticateCredential;
476539
const registerCredentialWithSignUp = Wrapper.registerCredentialWithSignUp;
477540
const authenticateCredentialWithSignIn = Wrapper.authenticateCredentialWithSignIn;
478541
const registerCredentialWithRecoverAccount = Wrapper.registerCredentialWithRecoverAccount;
542+
const createAndRegisterCredentialForSessionUser = Wrapper.createAndRegisterCredentialForSessionUser;
543+
const listCredentials = Wrapper.listCredentials;
544+
const removeCredential = Wrapper.removeCredential;
545+
const registerCredential = Wrapper.registerCredential;
479546
const doesBrowserSupportWebAuthn = Wrapper.doesBrowserSupportWebAuthn;
480547
const WebauthnComponentsOverrideProvider = Wrapper.ComponentsOverrideProvider;
481548

@@ -488,11 +555,15 @@ export {
488555
getEmailExists,
489556
generateRecoverAccountToken,
490557
recoverAccount,
491-
registerCredential,
558+
createCredential,
492559
authenticateCredential,
493560
registerCredentialWithSignUp,
494561
authenticateCredentialWithSignIn,
495562
registerCredentialWithRecoverAccount,
563+
createAndRegisterCredentialForSessionUser,
496564
doesBrowserSupportWebAuthn,
497565
WebauthnComponentsOverrideProvider,
566+
listCredentials,
567+
removeCredential,
568+
registerCredential,
498569
};

lib/ts/recipe/webauthn/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ export type PreAndPostAPIHookAction =
6565
| "SIGN_IN"
6666
| "EMAIL_EXISTS"
6767
| "GENERATE_RECOVER_ACCOUNT_TOKEN"
68-
| "RECOVER_ACCOUNT";
68+
| "RECOVER_ACCOUNT"
69+
| "REGISTER_CREDENTIAL"
70+
| "REMOVE_CREDENTIAL"
71+
| "LIST_CREDENTIALS";
6972

7073
export type OnHandleEventContext =
7174
| {

0 commit comments

Comments
 (0)