Files
Felis/panel/src/lib/passkey.ts
T

32 lines
1.4 KiB
TypeScript

import { clientError } from "@/lib/api";
import { base64urlToBytes, bytesToBase64url } from "@/lib/utils";
/** requestAssertion runs the WebAuthn get() ceremony for the server's request
* options (their JSON form: challenge and credential ids base64url) and returns
* the assertion in the JSON form the API's finish endpoints decode. Begins that
* answer with go-webauthn's {"publicKey": {...}} envelope pass the inner object. */
export async function requestAssertion(options: any) {
const publicKey: PublicKeyCredentialRequestOptions = {
...options,
challenge: base64urlToBytes(options.challenge),
allowCredentials: options.allowCredentials?.map((cred: any) => ({
...cred,
id: base64urlToBytes(cred.id),
})),
};
const credential = (await navigator.credentials.get({ publicKey })) as PublicKeyCredential | null;
if (!credential) throw clientError("passkey_no_credential");
const response = credential.response as AuthenticatorAssertionResponse;
return {
id: credential.id,
rawId: bytesToBase64url(credential.rawId),
type: credential.type,
response: {
clientDataJSON: bytesToBase64url(response.clientDataJSON),
authenticatorData: bytesToBase64url(response.authenticatorData),
signature: bytesToBase64url(response.signature),
userHandle: response.userHandle ? bytesToBase64url(response.userHandle) : null,
},
};
}