@@ -197,13 +197,35 @@ Now call the WebAuthn API on the client side:
197
197
198
198
[source,javascript]
199
199
----------
200
+ function base64urlToUint8array(base64Bytes) {
201
+ const padding = '===='.substring(0, (4 - (base64Bytes.length % 4)) % 4);
202
+ return base64js.toByteArray((base64Bytes + padding).replace(/\//g, "_").replace(/\+/g, "-"));
203
+ }
200
204
function uint8arrayToBase64url(bytes) {
201
205
return base64js.fromByteArray(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
202
206
}
203
207
204
208
fetch(/* ... */) // Make the call that returns the credentialCreateJson above
205
- .then(credentialCreateJson => // Call WebAuthn ceremony
206
- navigator.credentials.create(credentialCreateJson))
209
+ .then(credentialCreateJson => ({ // Decode byte arrays from base64url
210
+ publicKey: {
211
+ ...credentialCreateJson.publicKey,
212
+
213
+ challenge: base64urlToUint8Array(credentialCreateJson.publicKey.challenge),
214
+ user: {
215
+ ...credentialCreateJson.publicKey.user,
216
+ id: base64urlToUint8Array(credentialCreateJson.publicKey.user.id),
217
+ },
218
+ excludeCredentials: credentialCreateJson.publicKey.excludeCredentials.map(credential => ({
219
+ ...credential,
220
+ id: base64urlToUint8Array(credential.id),
221
+ })),
222
+
223
+ // Warning: Extension inputs could also contain binary data that needs encoding
224
+ extensions: credentialCreateJson.publicKey.extensions,
225
+ },
226
+ }))
227
+ .then(credentialCreateOptions => // Call WebAuthn ceremony
228
+ navigator.credentials.create(credentialCreateOptions))
207
229
.then(publicKeyCredential => ({ // Encode PublicKeyCredential for transport to server (example)
208
230
type: publicKeyCredential.type,
209
231
id: publicKeyCredential.id,
@@ -287,13 +309,32 @@ Now call the WebAuthn API on the client side:
287
309
288
310
[source,javascript]
289
311
----------
312
+ function base64urlToUint8array(base64Bytes) {
313
+ const padding = '===='.substring(0, (4 - (base64Bytes.length % 4)) % 4);
314
+ return base64js.toByteArray((base64Bytes + padding).replace(/\//g, "_").replace(/\+/g, "-"));
315
+ }
290
316
function uint8arrayToBase64url(bytes) {
291
317
return base64js.fromByteArray(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
292
318
}
293
319
294
320
fetch(/* ... */) // Make the call that returns the credentialGetJson above
295
- .then(credentialGetJson => // Call WebAuthn ceremony
296
- navigator.credentials.get(credentialGetJson))
321
+ .then(credentialGetJson => ({ // Decode byte arrays from base64url
322
+ publicKey: {
323
+ ...credentialGetJson.publicKey,
324
+ allowCredentials: credentialGetJson.publicKey.allowCredentials
325
+ && credentialGetJson.publicKey.allowCredentials.map(credential => ({
326
+ ...credential,
327
+ id: base64urlToUint8Array(credential.id),
328
+ })),
329
+
330
+ challenge: base64urlToUint8Array(credentialGetJson.publicKey.challenge),
331
+
332
+ // Warning: Extension inputs could also contain binary data that needs encoding
333
+ extensions: credentialGetJson.publicKey.extensions,
334
+ },
335
+ }))
336
+ .then(credentialGetOptions => // Call WebAuthn ceremony
337
+ navigator.credentials.get(credentialGetOptions))
297
338
.then(publicKeyCredential => ({ // Encode PublicKeyCredential for transport to server (example)
298
339
type: publicKeyCredential.type,
299
340
id: publicKeyCredential.id,
0 commit comments