Skip to content

Commit 23ef8e7

Browse files
coolbuebniftyvictorporcellus
authored
feat: WebAuthn credential management methods [v0.50.0] (#908)
* feat: add WebAuthn credential management methods * feat: renamed `registerCredential` to `createCredential` and added `registerCredentialWithUser` method for user-specific credential registration * fix: added missing exports * fix: temporarily set web-js version new version branch * chore: update changelog --------- Co-authored-by: Victor Bojica <[email protected]> Co-authored-by: Mihaly Lengyel <[email protected]>
1 parent 32b10db commit 23ef8e7

File tree

10 files changed

+226
-18
lines changed

10 files changed

+226
-18
lines changed

CHANGELOG.md

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

88
## [unreleased]
99

10+
## [0.50] - 2025-08-11
11+
12+
- Add WebAuthn credential management methods: `listCredentials`, `removeCredential`
13+
- Added `createAndRegisterCredentialWithUser` method that creates and registers a credential with a user
14+
15+
### Breaking changes
16+
17+
- 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.
18+
1019
## [0.49.1] - 2025-03-27
1120

1221
- 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
@@ -247,7 +247,7 @@ export default class Wrapper {
247247
return Webauthn.getInstanceOrThrow().webJSRecipe.recoverAccount(input);
248248
}
249249

250-
static registerCredential(input: {
250+
static createCredential(input: {
251251
registrationOptions: Omit<RegistrationOptions, "fetchResponse" | "status">;
252252
userContext: any;
253253
}): Promise<
@@ -267,7 +267,7 @@ export default class Wrapper {
267267
error: any;
268268
}
269269
> {
270-
return Webauthn.getInstanceOrThrow().webJSRecipe.registerCredential(input);
270+
return Webauthn.getInstanceOrThrow().webJSRecipe.createCredential(input);
271271
}
272272

273273
static authenticateCredential(input: {
@@ -439,6 +439,69 @@ export default class Wrapper {
439439
return Webauthn.getInstanceOrThrow().webJSRecipe.registerCredentialWithRecoverAccount(input);
440440
}
441441

442+
static listCredentials(input: { options?: RecipeFunctionOptions; userContext: any }): Promise<
443+
| {
444+
status: "OK";
445+
credentials: {
446+
webauthnCredentialId: string;
447+
relyingPartyId: string;
448+
recipeUserId: string;
449+
createdAt: number;
450+
}[];
451+
}
452+
| GeneralErrorResponse
453+
> {
454+
return Webauthn.getInstanceOrThrow().webJSRecipe.listCredentials(input);
455+
}
456+
457+
static removeCredential(input: {
458+
webauthnCredentialId: string;
459+
userContext: any;
460+
}): Promise<
461+
{ status: "OK" } | GeneralErrorResponse | { status: "CREDENTIAL_NOT_FOUND_ERROR"; fetchResponse: Response }
462+
> {
463+
return Webauthn.getInstanceOrThrow().webJSRecipe.removeCredential(input);
464+
}
465+
466+
static createAndRegisterCredentialForSessionUser(input: {
467+
recipeUserId: string;
468+
email: string;
469+
options?: RecipeFunctionOptions;
470+
userContext: any;
471+
}): Promise<
472+
| { status: "OK" }
473+
| GeneralErrorResponse
474+
| { status: "REGISTER_CREDENTIAL_NOT_ALLOWED"; reason?: string }
475+
| { status: "INVALID_EMAIL_ERROR"; err: string }
476+
| { status: "INVALID_CREDENTIALS_ERROR" }
477+
| { status: "OPTIONS_NOT_FOUND_ERROR" }
478+
| { status: "INVALID_OPTIONS_ERROR" }
479+
| { status: "INVALID_AUTHENTICATOR_ERROR"; reason?: string }
480+
| { status: "AUTHENTICATOR_ALREADY_REGISTERED" }
481+
| { status: "FAILED_TO_REGISTER_USER"; error: any }
482+
| { status: "WEBAUTHN_NOT_SUPPORTED"; error: any }
483+
> {
484+
return Webauthn.getInstanceOrThrow().webJSRecipe.createAndRegisterCredentialForSessionUser(input);
485+
}
486+
487+
static registerCredential(input: {
488+
recipeUserId: string;
489+
webauthnGeneratedOptionsId: string;
490+
credential: RegistrationResponseJSON;
491+
options?: RecipeFunctionOptions;
492+
userContext: any;
493+
}): Promise<
494+
| { status: "OK" }
495+
| GeneralErrorResponse
496+
| { status: "REGISTER_CREDENTIAL_NOT_ALLOWED"; reason?: string }
497+
| { status: "INVALID_CREDENTIALS_ERROR" }
498+
| { status: "OPTIONS_NOT_FOUND_ERROR" }
499+
| { status: "INVALID_OPTIONS_ERROR" }
500+
| { status: "INVALID_AUTHENTICATOR_ERROR"; reason?: string }
501+
> {
502+
return Webauthn.getInstanceOrThrow().webJSRecipe.registerCredential(input);
503+
}
504+
442505
static doesBrowserSupportWebAuthn(input: { userContext: any }): Promise<
443506
| {
444507
status: "OK";
@@ -464,11 +527,15 @@ const signIn = Wrapper.signIn;
464527
const getEmailExists = Wrapper.getEmailExists;
465528
const generateRecoverAccountToken = Wrapper.generateRecoverAccountToken;
466529
const recoverAccount = Wrapper.recoverAccount;
467-
const registerCredential = Wrapper.registerCredential;
530+
const createCredential = Wrapper.createCredential;
468531
const authenticateCredential = Wrapper.authenticateCredential;
469532
const registerCredentialWithSignUp = Wrapper.registerCredentialWithSignUp;
470533
const authenticateCredentialWithSignIn = Wrapper.authenticateCredentialWithSignIn;
471534
const registerCredentialWithRecoverAccount = Wrapper.registerCredentialWithRecoverAccount;
535+
const createAndRegisterCredentialForSessionUser = Wrapper.createAndRegisterCredentialForSessionUser;
536+
const listCredentials = Wrapper.listCredentials;
537+
const removeCredential = Wrapper.removeCredential;
538+
const registerCredential = Wrapper.registerCredential;
472539
const doesBrowserSupportWebAuthn = Wrapper.doesBrowserSupportWebAuthn;
473540
const WebauthnComponentsOverrideProvider = Wrapper.ComponentsOverrideProvider;
474541

@@ -481,11 +548,15 @@ export {
481548
getEmailExists,
482549
generateRecoverAccountToken,
483550
recoverAccount,
484-
registerCredential,
551+
createCredential,
485552
authenticateCredential,
486553
registerCredentialWithSignUp,
487554
authenticateCredentialWithSignIn,
488555
registerCredentialWithRecoverAccount,
556+
createAndRegisterCredentialForSessionUser,
489557
doesBrowserSupportWebAuthn,
490558
WebauthnComponentsOverrideProvider,
559+
listCredentials,
560+
removeCredential,
561+
registerCredential,
491562
};

lib/ts/recipe/webauthn/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ export type PreAndPostAPIHookAction =
5757
| "SIGN_IN"
5858
| "EMAIL_EXISTS"
5959
| "GENERATE_RECOVER_ACCOUNT_TOKEN"
60-
| "RECOVER_ACCOUNT";
60+
| "RECOVER_ACCOUNT"
61+
| "REGISTER_CREDENTIAL"
62+
| "REMOVE_CREDENTIAL"
63+
| "LIST_CREDENTIALS";
6164

6265
export type OnHandleEventContext =
6366
| {

0 commit comments

Comments
 (0)