this repo has no description
1export interface PublicKeyCredentialDescriptorJSON {
2 type: "public-key";
3 id: string;
4 transports?: AuthenticatorTransport[];
5}
6
7export interface PublicKeyCredentialUserEntityJSON {
8 id: string;
9 name: string;
10 displayName: string;
11}
12
13export interface PublicKeyCredentialRpEntityJSON {
14 name: string;
15 id?: string;
16}
17
18export interface PublicKeyCredentialParametersJSON {
19 type: "public-key";
20 alg: number;
21}
22
23export interface AuthenticatorSelectionCriteriaJSON {
24 authenticatorAttachment?: AuthenticatorAttachment;
25 residentKey?: ResidentKeyRequirement;
26 requireResidentKey?: boolean;
27 userVerification?: UserVerificationRequirement;
28}
29
30export interface PublicKeyCredentialCreationOptionsJSON {
31 rp: PublicKeyCredentialRpEntityJSON;
32 user: PublicKeyCredentialUserEntityJSON;
33 challenge: string;
34 pubKeyCredParams: PublicKeyCredentialParametersJSON[];
35 timeout?: number;
36 excludeCredentials?: PublicKeyCredentialDescriptorJSON[];
37 authenticatorSelection?: AuthenticatorSelectionCriteriaJSON;
38 attestation?: AttestationConveyancePreference;
39}
40
41export interface PublicKeyCredentialRequestOptionsJSON {
42 challenge: string;
43 timeout?: number;
44 rpId?: string;
45 allowCredentials?: PublicKeyCredentialDescriptorJSON[];
46 userVerification?: UserVerificationRequirement;
47}
48
49export interface WebAuthnCreationOptionsResponse {
50 publicKey: PublicKeyCredentialCreationOptionsJSON;
51}
52
53export interface WebAuthnRequestOptionsResponse {
54 publicKey: PublicKeyCredentialRequestOptionsJSON;
55}
56
57export interface CredentialAssertionJSON {
58 id: string;
59 type: string;
60 rawId: string;
61 response: {
62 clientDataJSON: string;
63 authenticatorData: string;
64 signature: string;
65 userHandle: string | null;
66 };
67}
68
69export interface CredentialAttestationJSON {
70 id: string;
71 type: string;
72 rawId: string;
73 response: {
74 clientDataJSON: string;
75 attestationObject: string;
76 };
77}
78
79export function base64UrlToArrayBuffer(base64url: string): ArrayBuffer {
80 const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
81 const padded = base64 + "=".repeat((4 - (base64.length % 4)) % 4);
82 const binary = atob(padded);
83 return Uint8Array.from(binary, (char) => char.charCodeAt(0)).buffer;
84}
85
86export function arrayBufferToBase64Url(buffer: ArrayBuffer): string {
87 const bytes = new Uint8Array(buffer);
88 const binary = Array.from(bytes, (byte) => String.fromCharCode(byte)).join(
89 "",
90 );
91 return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
92}
93
94export function prepareCreationOptions(
95 options: WebAuthnCreationOptionsResponse,
96): PublicKeyCredentialCreationOptions {
97 const pk = options.publicKey;
98 return {
99 ...pk,
100 challenge: base64UrlToArrayBuffer(pk.challenge),
101 user: {
102 ...pk.user,
103 id: base64UrlToArrayBuffer(pk.user.id),
104 },
105 excludeCredentials: (pk.excludeCredentials ?? []).map((cred) => ({
106 ...cred,
107 id: base64UrlToArrayBuffer(cred.id),
108 })),
109 };
110}
111
112export function prepareRequestOptions(
113 options: WebAuthnRequestOptionsResponse,
114): PublicKeyCredentialRequestOptions {
115 const pk = options.publicKey;
116 return {
117 ...pk,
118 challenge: base64UrlToArrayBuffer(pk.challenge),
119 allowCredentials: (pk.allowCredentials ?? []).map((cred) => ({
120 ...cred,
121 id: base64UrlToArrayBuffer(cred.id),
122 })),
123 };
124}
125
126export function serializeAttestationResponse(
127 credential: PublicKeyCredential,
128): CredentialAttestationJSON {
129 const response = credential.response as AuthenticatorAttestationResponse;
130 return {
131 id: credential.id,
132 type: credential.type,
133 rawId: arrayBufferToBase64Url(credential.rawId),
134 response: {
135 clientDataJSON: arrayBufferToBase64Url(response.clientDataJSON),
136 attestationObject: arrayBufferToBase64Url(response.attestationObject),
137 },
138 };
139}
140
141export function serializeAssertionResponse(
142 credential: PublicKeyCredential,
143): CredentialAssertionJSON {
144 const response = credential.response as AuthenticatorAssertionResponse;
145 return {
146 id: credential.id,
147 type: credential.type,
148 rawId: arrayBufferToBase64Url(credential.rawId),
149 response: {
150 clientDataJSON: arrayBufferToBase64Url(response.clientDataJSON),
151 authenticatorData: arrayBufferToBase64Url(response.authenticatorData),
152 signature: arrayBufferToBase64Url(response.signature),
153 userHandle: response.userHandle
154 ? arrayBufferToBase64Url(response.userHandle)
155 : null,
156 },
157 };
158}