From ad2902b0bb7acf9f545fe1a9c84a09a15784c7f9 Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Wed, 25 Sep 2024 22:21:21 -0400 Subject: [PATCH] feat: add WebAuthn credential management functionality --- .gitignore | 1 + nebula/bun.lockb | Bin 0 -> 42269 bytes nebula/src/main.ts | 257 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 256 insertions(+), 2 deletions(-) create mode 100755 nebula/bun.lockb diff --git a/.gitignore b/.gitignore index b5510bd19..d0e485aad 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,7 @@ deploy/**/data x/.DS_Store .aider* buildenv* +nebula/node_modules !devbox.lock !motr/build diff --git a/nebula/bun.lockb b/nebula/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..0cb6f3666df62cc40e745d52d595cd79ade45818 GIT binary patch literal 42269 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 { + const publicKeyCredentialCreationOptions = { + challenge: new Uint8Array(32), + rp: { + name: this.config.motr.origin, + id: new URL(this.config.motr.origin).hostname, + }, + user: { + id: new TextEncoder().encode(options.subject), + name: options.subject, + displayName: options.label, + }, + pubKeyCredParams: [ + { alg: -7, type: "public-key" }, + { alg: -257, type: "public-key" }, + ], + authenticatorSelection: { + authenticatorAttachment: "platform", + userVerification: "required", + }, + timeout: 60000, + attestation: "direct", + }; + + try { + const credential = await navigator.credentials.create({ + publicKey: publicKeyCredentialCreationOptions, + }); + + const publicKeyJwk = await crypto.subtle.exportKey( + "jwk", + credential.response.getPublicKey(), + ); + + return { + id: credential.id, + publicKey: publicKeyJwk, + type: credential.type, + transports: credential.response.getTransports(), + }; + } catch (error) { + console.error("Error creating credential:", error); + throw error; + } + } + + async getPublicKeyCredential(options) { + const publicKeyCredentialRequestOptions = { + challenge: new Uint8Array(32), + rpId: new URL(this.config.motr.origin).hostname, + allowCredentials: options.allowCredentials || [], + userVerification: "required", + timeout: 60000, + }; + + try { + const assertion = await navigator.credentials.get({ + publicKey: publicKeyCredentialRequestOptions, + }); + + return { + id: assertion.id, + type: assertion.type, + rawId: new Uint8Array(assertion.rawId), + response: { + authenticatorData: new Uint8Array( + assertion.response.authenticatorData, + ), + clientDataJSON: new Uint8Array(assertion.response.clientDataJSON), + signature: new Uint8Array(assertion.response.signature), + userHandle: new Uint8Array(assertion.response.userHandle), + }, + }; + } catch (error) { + console.error("Error getting credential:", error); + throw error; + } + } +}