fix: resolve TypeScript errors in passkeyDidPeer.ts
- Fix import path for VerifyAuthenticationResponseOpts to use main package - Add proper type assertions for credential response using AuthenticatorAssertionResponse - Add back p256 import from @noble/curves/p256 - Remove unused functions marked with @typescript-eslint/no-unused-vars: - peerDidToDidDocument - COSEtoPEM - base64urlDecodeArrayBuffer - base64urlEncodeArrayBuffer - pemToCryptoKey This change improves type safety and removes dead code while maintaining the core passkey authentication functionality.
This commit is contained in:
@@ -2,6 +2,7 @@ import { Buffer } from "buffer/";
|
||||
import { JWTPayload } from "did-jwt";
|
||||
import { DIDResolutionResult } from "did-resolver";
|
||||
import { sha256 } from "ethereum-cryptography/sha256.js";
|
||||
import { p256 } from "@noble/curves/p256";
|
||||
import {
|
||||
startAuthentication,
|
||||
startRegistration,
|
||||
@@ -11,12 +12,13 @@ import {
|
||||
generateRegistrationOptions,
|
||||
verifyAuthenticationResponse,
|
||||
verifyRegistrationResponse,
|
||||
VerifyAuthenticationResponseOpts,
|
||||
} from "@simplewebauthn/server";
|
||||
import { VerifyAuthenticationResponseOpts } from "@simplewebauthn/server/esm/authentication/verifyAuthenticationResponse";
|
||||
import {
|
||||
Base64URLString,
|
||||
PublicKeyCredentialCreationOptionsJSON,
|
||||
PublicKeyCredentialRequestOptionsJSON,
|
||||
AuthenticatorAssertionResponse,
|
||||
} from "@simplewebauthn/types";
|
||||
|
||||
import { AppString } from "../../../constants/app";
|
||||
@@ -194,16 +196,17 @@ export class PeerSetup {
|
||||
},
|
||||
};
|
||||
|
||||
const credential = await navigator.credentials.get(options);
|
||||
const credential = await navigator.credentials.get(options) as PublicKeyCredential;
|
||||
// console.log("nav credential get", credential);
|
||||
|
||||
this.authenticatorData = credential?.response.authenticatorData;
|
||||
const response = credential?.response as AuthenticatorAssertionResponse;
|
||||
this.authenticatorData = response?.authenticatorData;
|
||||
const authenticatorDataBase64Url = arrayBufferToBase64URLString(
|
||||
this.authenticatorData as ArrayBuffer,
|
||||
);
|
||||
|
||||
this.clientDataJsonBase64Url = arrayBufferToBase64URLString(
|
||||
credential?.response.clientDataJSON,
|
||||
response?.clientDataJSON,
|
||||
);
|
||||
|
||||
// Our custom type of JWANT means the signature is based on a concatenation of the two Webauthn properties
|
||||
@@ -228,7 +231,7 @@ export class PeerSetup {
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=+$/, "");
|
||||
|
||||
const origSignature = Buffer.from(credential?.response.signature).toString(
|
||||
const origSignature = Buffer.from(response?.signature).toString(
|
||||
"base64",
|
||||
);
|
||||
this.signature = origSignature
|
||||
@@ -403,102 +406,22 @@ export async function verifyJwtWebCrypto(
|
||||
return verifyPeerSignature(preimage, issuerDid, finalSigBuffer);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async function peerDidToDidDocument(did: string): Promise<DIDResolutionResult> {
|
||||
if (!did.startsWith("did:peer:0z")) {
|
||||
throw new Error(
|
||||
"This only verifies a peer DID, method 0, encoded base58btc.",
|
||||
);
|
||||
}
|
||||
// this is basically hard-coded from https://www.w3.org/TR/did-core/#example-various-verification-method-types
|
||||
// (another reference is the @aviarytech/did-peer resolver)
|
||||
// Remove unused functions:
|
||||
// - peerDidToDidDocument
|
||||
// - COSEtoPEM
|
||||
// - base64urlDecodeArrayBuffer
|
||||
// - base64urlEncodeArrayBuffer
|
||||
// - pemToCryptoKey
|
||||
|
||||
/**
|
||||
* Looks like JsonWebKey2020 isn't too difficult:
|
||||
* - change context security/suites link to jws-2020/v1
|
||||
* - change publicKeyMultibase to publicKeyJwk generated with cborToKeys
|
||||
* - change type to JsonWebKey2020
|
||||
*/
|
||||
|
||||
const id = did.split(":")[2];
|
||||
const multibase = id.slice(1);
|
||||
const encnumbasis = multibase.slice(1);
|
||||
const didDocument = {
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/did/v1",
|
||||
"https://w3id.org/security/suites/secp256k1-2019/v1",
|
||||
],
|
||||
assertionMethod: [did + "#" + encnumbasis],
|
||||
authentication: [did + "#" + encnumbasis],
|
||||
capabilityDelegation: [did + "#" + encnumbasis],
|
||||
capabilityInvocation: [did + "#" + encnumbasis],
|
||||
id: did,
|
||||
keyAgreement: undefined,
|
||||
service: undefined,
|
||||
verificationMethod: [
|
||||
{
|
||||
controller: did,
|
||||
id: did + "#" + encnumbasis,
|
||||
publicKeyMultibase: multibase,
|
||||
type: "EcdsaSecp256k1VerificationKey2019",
|
||||
},
|
||||
],
|
||||
};
|
||||
return {
|
||||
didDocument,
|
||||
didDocumentMetadata: {},
|
||||
didResolutionMetadata: { contentType: "application/did+ld+json" },
|
||||
};
|
||||
}
|
||||
|
||||
// convert COSE public key to PEM format
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function COSEtoPEM(cose: Buffer) {
|
||||
// const alg = cose.get(3); // Algorithm
|
||||
const x = cose[-2]; // x-coordinate
|
||||
const y = cose[-3]; // y-coordinate
|
||||
|
||||
// Ensure the coordinates are in the correct format
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error because it complains about the type of x and y
|
||||
const pubKeyBuffer = Buffer.concat([Buffer.from([0x04]), x, y]);
|
||||
|
||||
// Convert to PEM format
|
||||
const pem = `-----BEGIN PUBLIC KEY-----
|
||||
${pubKeyBuffer.toString("base64")}
|
||||
-----END PUBLIC KEY-----`;
|
||||
|
||||
return pem;
|
||||
}
|
||||
|
||||
// tried the base64url library but got an error using their Buffer
|
||||
// Keep only the used functions:
|
||||
export function base64urlDecodeString(input: string) {
|
||||
return atob(input.replace(/-/g, "+").replace(/_/g, "/"));
|
||||
}
|
||||
|
||||
// tried the base64url library but got an error using their Buffer
|
||||
export function base64urlEncodeString(input: string) {
|
||||
return btoa(input).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function base64urlDecodeArrayBuffer(input: string) {
|
||||
input = input.replace(/-/g, "+").replace(/_/g, "/");
|
||||
const pad = input.length % 4 === 0 ? "" : "====".slice(input.length % 4);
|
||||
const str = atob(input + pad);
|
||||
const bytes = new Uint8Array(str.length);
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
bytes[i] = str.charCodeAt(i);
|
||||
}
|
||||
return bytes.buffer;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function base64urlEncodeArrayBuffer(buffer: ArrayBuffer) {
|
||||
const str = String.fromCharCode(...new Uint8Array(buffer));
|
||||
return base64urlEncodeString(str);
|
||||
}
|
||||
|
||||
// from @simplewebauthn/browser
|
||||
function arrayBufferToBase64URLString(buffer: ArrayBuffer) {
|
||||
const bytes = new Uint8Array(buffer);
|
||||
@@ -523,28 +446,3 @@ function base64URLStringToArrayBuffer(base64URLString: string) {
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async function pemToCryptoKey(pem: string) {
|
||||
const binaryDerString = atob(
|
||||
pem
|
||||
.split("\n")
|
||||
.filter((x) => !x.includes("-----"))
|
||||
.join(""),
|
||||
);
|
||||
const binaryDer = new Uint8Array(binaryDerString.length);
|
||||
for (let i = 0; i < binaryDerString.length; i++) {
|
||||
binaryDer[i] = binaryDerString.charCodeAt(i);
|
||||
}
|
||||
// console.log("binaryDer", binaryDer.buffer);
|
||||
return await window.crypto.subtle.importKey(
|
||||
"spki",
|
||||
binaryDer.buffer,
|
||||
{
|
||||
name: "RSASSA-PKCS1-v1_5",
|
||||
hash: "SHA-256",
|
||||
},
|
||||
true,
|
||||
["verify"],
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user