pomerium/ui/src/components/WebAuthnAuthenticateButton.tsx
Caleb Doxsey ab388211f2
core/ui: improve frontend build size (#5109)
* core/ui: improve frontend build size

* remove luxon

* add lodash

* remove console.log

* only generate sourcemap when watching
2024-05-09 07:10:00 -06:00

71 lines
2.1 KiB
TypeScript

import React, { FC } from "react";
import { WebAuthnRequestOptions } from "../types";
import { decode, encodeUrl } from "../util/base64";
import WebAuthnButton, { WebAuthnButtonProps } from "./WebAuthnButton";
type CredentialForAuthenticate = {
id: string;
type: string;
rawId: ArrayBuffer;
response: {
authenticatorData: ArrayBuffer;
clientDataJSON: ArrayBuffer;
signature: ArrayBuffer;
userHandle: ArrayBuffer;
};
};
async function authenticateCredential(
requestOptions: WebAuthnRequestOptions
): Promise<CredentialForAuthenticate> {
const credential = await navigator.credentials.get({
publicKey: {
allowCredentials: requestOptions?.allowCredentials?.map((c) => ({
type: c.type,
id: decode(c.id),
})),
challenge: decode(requestOptions?.challenge),
timeout: requestOptions?.timeout,
userVerification: requestOptions?.userVerification,
rpId: requestOptions?.rpId,
},
});
return credential as CredentialForAuthenticate;
}
export type WebAuthnAuthenticateButtonProps = Omit<
WebAuthnButtonProps,
"action" | "enable" | "onClick" | "text"
> & {
requestOptions: WebAuthnRequestOptions;
};
export const WebAuthnAuthenticateButton: FC<
WebAuthnAuthenticateButtonProps
> = ({ requestOptions, ...props }) => {
async function authenticate(): Promise<unknown> {
const credential = await authenticateCredential(requestOptions);
return {
id: credential.id,
type: credential.type,
rawId: encodeUrl(credential.rawId),
response: {
authenticatorData: encodeUrl(credential.response.authenticatorData),
clientDataJSON: encodeUrl(credential.response.clientDataJSON),
signature: encodeUrl(credential.response.signature),
userHandle: encodeUrl(credential.response.userHandle),
},
};
}
return (
<WebAuthnButton
action="authenticate"
enable={requestOptions?.allowCredentials?.length > 0}
onClick={authenticate}
text={"Authenticate Existing Device"}
{...props}
/>
);
};
export default WebAuthnAuthenticateButton;