Skip to content

Commit 008ac42

Browse files
authoredMar 5, 2024··
feat(clerk-js): Experimental CRUD methods for passkeys (#2926)
1 parent c86f73b commit 008ac42

File tree

7 files changed

+53
-26
lines changed

7 files changed

+53
-26
lines changed
 

‎.changeset/wet-carpets-double.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@clerk/clerk-js': minor
3+
'@clerk/types': minor
4+
---
5+
6+
Experimental support for reading, updating, and deleting a user's registered passkeys.
7+
- Get the user's passkeys
8+
`clerk.user.__experimental__passkeys`
9+
- Update the name of a passkey
10+
`clerk.user.__experimental__passkeys?.[0].update({name:'work laptop passkey'})`
11+
- Delete a passkey
12+
`clerk.user.__experimental__passkeys?.[0].delete()`

‎packages/clerk-js/src/core/resources/Passkey.ts

+23-22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import type { PasskeyJSON, PasskeyResource, PasskeyVerificationResource } from '@clerk/types';
1+
import type {
2+
DeletedObjectJSON,
3+
DeletedObjectResource,
4+
PasskeyJSON,
5+
PasskeyResource,
6+
PasskeyVerificationResource,
7+
UpdatePasskeyParams,
8+
} from '@clerk/types';
29

310
import { unixEpochToDate } from '../../utils/date';
411
import type { PublicKeyCredentialWithAuthenticatorAttestationResponse } from '../../utils/passkeys';
@@ -7,7 +14,7 @@ import {
714
serializePublicKeyCredential,
815
webAuthnCreateCredential,
916
} from '../../utils/passkeys';
10-
import { BaseResource, ClerkRuntimeError, PasskeyVerification } from './internal';
17+
import { BaseResource, ClerkRuntimeError, DeletedObject, PasskeyVerification } from './internal';
1118

1219
export class Passkey extends BaseResource implements PasskeyResource {
1320
id!: string;
@@ -43,13 +50,6 @@ export class Passkey extends BaseResource implements PasskeyResource {
4350
}).then(res => new Passkey(res?.response as PasskeyJSON));
4451
}
4552

46-
/**
47-
* TODO-PASSKEYS: Implement this later
48-
*
49-
* GET /v1/me/passkeys
50-
*/
51-
static async get() {}
52-
5353
/**
5454
* Developers should not be able to create a new Passkeys from an already instanced object
5555
*/
@@ -92,25 +92,26 @@ export class Passkey extends BaseResource implements PasskeyResource {
9292
}
9393

9494
/**
95-
* TODO-PASSKEYS: Implement this later
96-
*
9795
* PATCH /v1/me/passkeys/{passkeyIdentificationID}
9896
*/
99-
update = (): Promise<PasskeyResource> => this._basePatch();
97+
update = (params: UpdatePasskeyParams): Promise<PasskeyResource> =>
98+
this._basePatch({
99+
body: params,
100+
});
100101

101102
/**
102-
* TODO-PASSKEYS: Implement this later
103-
*
104103
* DELETE /v1/me/passkeys/{passkeyIdentificationID}
105104
*/
106-
destroy = (): Promise<void> => this._baseDelete();
107-
108-
/**
109-
* TODO-PASSKEYS: Implement this later
110-
*
111-
* GET /v1/me/passkeys/{passkeyIdentificationID}
112-
*/
113-
reload = () => this._baseGet();
105+
delete = async (): Promise<DeletedObjectResource> => {
106+
const json = (
107+
await BaseResource._fetch<DeletedObjectJSON>({
108+
path: `${this.path()}/${this.id}`,
109+
method: 'DELETE',
110+
})
111+
)?.response as unknown as DeletedObjectJSON;
112+
113+
return new DeletedObject(json);
114+
};
114115

115116
protected fromJSON(data: PasskeyJSON | null): this {
116117
if (!data) {

‎packages/clerk-js/src/core/resources/User.ts

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export class User extends BaseResource implements UserResource {
6161
phoneNumbers: PhoneNumberResource[] = [];
6262
web3Wallets: Web3WalletResource[] = [];
6363
externalAccounts: ExternalAccountResource[] = [];
64+
__experimental_passkeys: PasskeyResource[] = [];
6465

6566
samlAccounts: SamlAccountResource[] = [];
6667

@@ -337,6 +338,8 @@ export class User extends BaseResource implements UserResource {
337338
ea => new ExternalAccount(ea, this.path() + '/external_accounts'),
338339
);
339340

341+
this.__experimental_passkeys = (data.passkeys || []).map(passkey => new Passkey(passkey));
342+
340343
this.organizationMemberships = (data.organization_memberships || []).map(om => new OrganizationMembership(om));
341344

342345
this.samlAccounts = (data.saml_accounts || []).map(sa => new SamlAccount(sa, this.path() + '/saml_accounts'));

‎packages/clerk-js/src/utils/passkeys.ts

-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ class Base64Converter {
6060
}
6161

6262
static decode(base64url: string): ArrayBuffer {
63-
// TODO-PASSKEYS: check if this can be replaced with Buffer.from(base64url, 'base64');
6463
const base64 = base64url.replace(/-/g, '+').replace(/_/g, '/');
6564

6665
const binaryString = atob(base64);

‎packages/types/src/json.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ export interface UserJSON extends ClerkResourceJSON {
195195
phone_numbers: PhoneNumberJSON[];
196196
web3_wallets: Web3WalletJSON[];
197197
external_accounts: ExternalAccountJSON[];
198-
198+
passkeys: PasskeyJSON[];
199199
saml_accounts: SamlAccountJSON[];
200200

201201
organization_memberships: OrganizationMembershipJSON[];

‎packages/types/src/passkey.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
import type { DeletedObjectResource } from './deletedObject';
2+
import type { PasskeyJSON } from './json';
13
import type { ClerkResource } from './resource';
4+
import type { SnakeToCamel } from './utils';
25
import type { PasskeyVerificationResource } from './verification';
36

4-
export interface PublicKeyOptions extends PublicKeyCredentialCreationOptions {}
7+
type UpdatePasskeyJSON = Pick<PasskeyJSON, 'name'>;
8+
9+
export type UpdatePasskeyParams = Partial<SnakeToCamel<UpdatePasskeyJSON>>;
510

611
export interface PasskeyResource extends ClerkResource {
712
id: string;
@@ -11,4 +16,7 @@ export interface PasskeyResource extends ClerkResource {
1116
lastUsedAt: Date | null;
1217
updatedAt: Date;
1318
createdAt: Date;
19+
20+
update: (params: UpdatePasskeyParams) => Promise<PasskeyResource>;
21+
delete: () => Promise<DeletedObjectResource>;
1422
}

‎packages/types/src/user.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,11 @@ export interface UserResource extends ClerkResource {
6868
phoneNumbers: PhoneNumberResource[];
6969
web3Wallets: Web3WalletResource[];
7070
externalAccounts: ExternalAccountResource[];
71-
71+
/**
72+
* @experimental
73+
* This property is experimental, avoid using this in production applications
74+
*/
75+
__experimental_passkeys: PasskeyResource[];
7276
samlAccounts: SamlAccountResource[];
7377

7478
organizationMemberships: OrganizationMembershipResource[];

0 commit comments

Comments
 (0)
Please sign in to comment.